From ab92499b5649fad928edeb56948667524619e9d8 Mon Sep 17 00:00:00 2001 From: Brandon Yates Date: Tue, 25 Jun 2024 03:03:26 +0000 Subject: [PATCH] feature: Add support for V3 state save header Related-to: NEO-8396 Signed-off-by: Brandon Yates --- level_zero/include/zet_intel_gpu_debug.h | 26 +- .../tools/source/debug/debug_session_imp.cpp | 273 ++++++++++++++---- .../tools/source/debug/debug_session_imp.h | 13 +- .../sources/debug/debug_session_common.h | 10 + .../debug/debug_session_registers_access.cpp | 17 +- .../debug/debug_session_registers_access.h | 8 +- .../sources/debug/debug_session_tests.cpp | 79 +++++ .../linux/debug_session_fixtures_linux.h | 10 +- .../linux/prelim/test_debug_api_linux.cpp | 116 +++++++- .../sources/debug/mock_debug_session.h | 19 +- .../sources/debug/test_debug_api.cpp | 154 ++++++++++ .../debug/windows/test_debug_api_windows.cpp | 4 +- shared/source/built_ins/sip.cpp | 27 +- shared/source/debugger/debugger_l0.h | 26 +- shared/test/common/helpers/sip_init.cpp | 59 ++++ shared/test/unit_test/built_ins/sip_tests.cpp | 4 + 16 files changed, 744 insertions(+), 101 deletions(-) diff --git a/level_zero/include/zet_intel_gpu_debug.h b/level_zero/include/zet_intel_gpu_debug.h index 979081f892..c2199f9c3e 100644 --- a/level_zero/include/zet_intel_gpu_debug.h +++ b/level_zero/include/zet_intel_gpu_debug.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Intel Corporation + * Copyright (C) 2021-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,7 +20,7 @@ extern "C" { #endif // !ZET_INTEL_GPU_DEBUG_MAJOR #ifndef ZET_INTEL_GPU_DEBUG_MINOR -#define ZET_INTEL_GPU_DEBUG_MINOR 0 +#define ZET_INTEL_GPU_DEBUG_MINOR 1 #endif //! ZET_INTEL_GPU_DEBUG_MINOR #if ZET_INTEL_GPU_DEBUG_MAJOR == 1 @@ -42,10 +42,32 @@ typedef enum _zet_debug_regset_type_intel_gpu_t { ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU = 11, ///< The state base address register set ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU = 12, ///< The debug register set ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU = 13, ///< The flow control register set +#if ZET_INTEL_GPU_DEBUG_MINOR >= 1 + ZET_DEBUG_REGSET_TYPE_MSG_INTEL_GPU = 14, ///< The msg register set + ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU = 15, ///< System Routine mode flags register set + ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU = 16, ///< Debug Scratch register set + ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU = 17, ///< Thread Scratch register set + ZET_DEBUG_REGSET_TYPE_SCALAR_INTEL_GPU = 18, ///< The scalar register set +#endif // ZET_INTEL_GPU_DEBUG_MINOR >= 1 ZET_DEBUG_REGSET_TYPE_FORCE_UINT32 = 0x7fffffff #endif // ZET_INTEL_GPU_DEBUG_MINOR >= 0 } zet_debug_regset_type_intel_gpu_t; +#if ZET_INTEL_GPU_DEBUG_MINOR >= 1 +//////////////////////////////////////////////////////////////////////////////// +/// @brief ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU flag values +typedef enum _zet_debug_mode_flags_intel_gpu_t { + ZET_DEBUG_MODE_FLAG_HEAPLESS = 1 ///< Bit set indicates heapless mode +} zet_debug_mode_flags_intel_gpu_t; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU register layout +typedef enum _zet_debug_debug_scratch_intel_gpu_t { + ZET_DEBUG_DEBUG_SCRATCH_ADDRESS = 0, ///< VA of scratch area for debugger code injection. + ///< VA is in default address space of device + ZET_DEBUG_DEBUG_SCRATCH_SIZE = 1, ///< Size of scratch area in bytes +} zet_debug_debug_scratch_intel_gpu_t; +#endif // ZET_INTEL_GPU_DEBUG_MINOR >= 1 //////////////////////////////////////////////////////////////////////////////// /// @brief SBA register set layout typedef enum _zet_debug_sba_intel_gpu_t { diff --git a/level_zero/tools/source/debug/debug_session_imp.cpp b/level_zero/tools/source/debug/debug_session_imp.cpp index e0e7d913d0..ef7925006e 100644 --- a/level_zero/tools/source/debug/debug_session_imp.cpp +++ b/level_zero/tools/source/debug/debug_session_imp.cpp @@ -702,6 +702,17 @@ void DebugSessionImp::sendInterrupts() { } } +size_t DebugSessionImp::calculateSrMagicOffset(const NEO::StateSaveAreaHeader *stateSaveAreaHeader, EuThread *thread) { + auto threadSlotOffset = calculateThreadSlotOffset(thread->getThreadId()); + size_t srMagicOffset = 0; + if (stateSaveAreaHeader->versionHeader.version.major >= 3) { + srMagicOffset = threadSlotOffset + stateSaveAreaHeader->regHeaderV3.sr_magic_offset; + } else { + srMagicOffset = threadSlotOffset + stateSaveAreaHeader->regHeader.sr_magic_offset; + } + return srMagicOffset; +} + bool DebugSessionImp::readSystemRoutineIdent(EuThread *thread, uint64_t memoryHandle, SIP::sr_ident &srIdent) { auto stateSaveAreaHeader = getStateSaveAreaHeader(); if (!stateSaveAreaHeader) { @@ -713,8 +724,7 @@ bool DebugSessionImp::readSystemRoutineIdent(EuThread *thread, uint64_t memoryHa return false; } - auto threadSlotOffset = calculateThreadSlotOffset(thread->getThreadId()); - auto srMagicOffset = threadSlotOffset + stateSaveAreaHeader->regHeader.sr_magic_offset; + auto srMagicOffset = calculateSrMagicOffset(stateSaveAreaHeader, thread); if (ZE_RESULT_SUCCESS != readGpuMemory(memoryHandle, reinterpret_cast(&srIdent), sizeof(srIdent), gpuVa + srMagicOffset)) { return false; @@ -729,12 +739,12 @@ bool DebugSessionImp::readSystemRoutineIdent(EuThread *thread, uint64_t memoryHa } bool DebugSessionImp::readSystemRoutineIdentFromMemory(EuThread *thread, const void *stateSaveArea, SIP::sr_ident &srIdent) { auto stateSaveAreaHeader = getStateSaveAreaHeader(); - auto threadSlotOffset = calculateThreadSlotOffset(thread->getThreadId()); - auto srMagicOffset = threadSlotOffset + stateSaveAreaHeader->regHeader.sr_magic_offset; + + auto srMagicOffset = calculateSrMagicOffset(stateSaveAreaHeader, thread); auto threadSlot = ptrOffset(stateSaveArea, srMagicOffset); memcpy_s(&srIdent, sizeof(SIP::sr_ident), threadSlot, sizeof(SIP::sr_ident)); - PRINT_DEBUGGER_INFO_LOG("readSystemRoutineIdentFromMemory - threadSlotOffset %zu srMagicOffset %lu for thread %s\n", threadSlotOffset, srMagicOffset, EuThread::toString(thread->getThreadId()).c_str()); + PRINT_DEBUGGER_INFO_LOG("readSystemRoutineIdentFromMemory - srMagicOffset %lu for thread %s\n", srMagicOffset, EuThread::toString(thread->getThreadId()).c_str()); if (0 != strcmp(srIdent.magic, "srmagic")) { PRINT_DEBUGGER_ERROR_LOG("readSystemRoutineIdentFromMemory - Failed to read srMagic for thread %s\n", EuThread::toString(thread->getThreadId()).c_str()); return false; @@ -975,19 +985,31 @@ ze_result_t DebugSessionImp::readEvent(uint64_t timeout, zet_debug_event_t *outp } void DebugSessionImp::validateAndSetStateSaveAreaHeader(uint64_t vmHandle, uint64_t gpuVa) { - auto headerSize = sizeof(SIP::StateSaveAreaHeader); + auto headerSize = sizeof(NEO::StateSaveAreaHeader); std::vector data(headerSize); - auto retVal = readGpuMemory(vmHandle, data.data(), headerSize, gpuVa); + auto retVal = readGpuMemory(vmHandle, data.data(), sizeof(SIP::StateSaveArea), gpuVa); if (retVal != ZE_RESULT_SUCCESS) { - PRINT_DEBUGGER_ERROR_LOG("Reading Context State Save Area failed, error = %d\n", retVal); + PRINT_DEBUGGER_ERROR_LOG("Reading Context State Save Area Version Header failed, error = %d\n", retVal); return; } - auto pStateSaveArea = reinterpret_cast(data.data()); + auto pStateSaveArea = reinterpret_cast(data.data()); if (0 == strcmp(pStateSaveArea->versionHeader.magic, "tssarea")) { size_t size = pStateSaveArea->versionHeader.size * 8u; - DEBUG_BREAK_IF(size != sizeof(SIP::StateSaveAreaHeader)); + size_t regHeaderSize = 0; + if (pStateSaveArea->versionHeader.version.major == 3) { + DEBUG_BREAK_IF(size != sizeof(NEO::StateSaveAreaHeader)); + regHeaderSize = sizeof(SIP::intelgt_state_save_area_V3); + } else { + DEBUG_BREAK_IF(size != sizeof(NEO::StateSaveAreaHeader::regHeader) + sizeof(NEO::StateSaveAreaHeader::versionHeader)); + regHeaderSize = sizeof(SIP::intelgt_state_save_area); + } + auto retVal = readGpuMemory(vmHandle, data.data() + sizeof(SIP::StateSaveArea), regHeaderSize, gpuVa + sizeof(SIP::StateSaveArea)); + if (retVal != ZE_RESULT_SUCCESS) { + PRINT_DEBUGGER_ERROR_LOG("Reading Context State Save Area Reg Header failed, error = %d\n", retVal); + return; + } stateSaveAreaHeader.assign(data.begin(), data.begin() + size); PRINT_DEBUGGER_INFO_LOG("Context State Save Area : version == %d.%d.%d\n", (int)pStateSaveArea->versionHeader.version.major, (int)pStateSaveArea->versionHeader.version.minor, (int)pStateSaveArea->versionHeader.version.patch); slmSipVersionCheck(); @@ -1009,17 +1031,41 @@ void DebugSessionImp::slmSipVersionCheck() { } } -const SIP::StateSaveAreaHeader *DebugSessionImp::getStateSaveAreaHeader() { +const NEO::StateSaveAreaHeader *DebugSessionImp::getStateSaveAreaHeader() { if (stateSaveAreaHeader.empty()) { readStateSaveAreaHeader(); } - return reinterpret_cast(stateSaveAreaHeader.data()); + return reinterpret_cast(stateSaveAreaHeader.data()); } -const SIP::regset_desc *DebugSessionImp::getSbaRegsetDesc() { - // SBA virtual register set is always present +const SIP::regset_desc *DebugSessionImp::getModeFlagsRegsetDesc() { + static const SIP::regset_desc mode = {0, 1, 32, 4}; + return &mode; +} + +const SIP::regset_desc *DebugSessionImp::getDebugScratchRegsetDesc() { + static const SIP::regset_desc debugScratch = {0, 2, 64, 8}; + return &debugScratch; +} + +const SIP::regset_desc *DebugSessionImp::getThreadScratchRegsetDesc() { + static const SIP::regset_desc threadScratch = {0, 2, 64, 8}; + return &threadScratch; +} + +bool DebugSessionImp::isHeaplessMode(const SIP::intelgt_state_save_area_V3 &ssa) { + return (ssa.sip_flags & SIP::SIP_FLAG_HEAPLESS); +} + +const SIP::regset_desc *DebugSessionImp::getSbaRegsetDesc(const NEO::StateSaveAreaHeader &ssah) { + + static const SIP::regset_desc sbaHeapless = {0, 0, 0, 0}; static const SIP::regset_desc sba = {0, ZET_DEBUG_SBA_COUNT_INTEL_GPU, 64, 8}; - return &sba; + if (ssah.versionHeader.version.major >= 3 && isHeaplessMode(ssah.regHeaderV3)) { + return &sbaHeapless; + } else { + return &sba; + } } const SIP::regset_desc *DebugSessionImp::typeToRegsetDesc(uint32_t type) { @@ -1029,36 +1075,84 @@ const SIP::regset_desc *DebugSessionImp::typeToRegsetDesc(uint32_t type) { DEBUG_BREAK_IF(pStateSaveAreaHeader == nullptr); return nullptr; } - - switch (type) { - case ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.grf; - case ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.addr; - case ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.flag; - case ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.emask; - case ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.sr; - case ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.cr; - case ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.tdr; - case ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.acc; - case ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.mme; - case ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.sp; - case ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.dbg_reg; - case ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU: - return &pStateSaveAreaHeader->regHeader.fc; - case ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU: - return DebugSessionImp::getSbaRegsetDesc(); - default: - return nullptr; + if (pStateSaveAreaHeader->versionHeader.version.major >= 3) { + switch (type) { + case ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.grf; + case ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.addr; + case ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.flag; + case ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.emask; + case ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.sr; + case ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.cr; + case ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.tdr; + case ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.acc; + case ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.mme; + case ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.sp; + case ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.dbg_reg; + case ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.fc; + case ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU: + return DebugSessionImp::getModeFlagsRegsetDesc(); + case ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU: + return DebugSessionImp::getDebugScratchRegsetDesc(); + case ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU: + return DebugSessionImp::getThreadScratchRegsetDesc(); + case ZET_DEBUG_REGSET_TYPE_SCALAR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.scalar; + case ZET_DEBUG_REGSET_TYPE_MSG_INTEL_GPU: + return &pStateSaveAreaHeader->regHeaderV3.msg; + case ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU: { + auto &stateSaveAreaHeader = NEO::SipKernel::getBindlessDebugSipKernel(*connectedDevice->getNEODevice()).getStateSaveAreaHeader(); + auto pStateSaveArea = reinterpret_cast(stateSaveAreaHeader.data()); + return DebugSessionImp::getSbaRegsetDesc(*pStateSaveArea); + } + default: + return nullptr; + } + } else { + switch (type) { + case ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.grf; + case ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.addr; + case ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.flag; + case ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.emask; + case ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.sr; + case ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.cr; + case ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.tdr; + case ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.acc; + case ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.mme; + case ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.sp; + case ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.dbg_reg; + case ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU: + return &pStateSaveAreaHeader->regHeader.fc; + case ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU: { + auto &stateSaveAreaHeader = NEO::SipKernel::getBindlessDebugSipKernel(*connectedDevice->getNEODevice()).getStateSaveAreaHeader(); + auto pStateSaveArea = reinterpret_cast(stateSaveAreaHeader.data()); + return DebugSessionImp::getSbaRegsetDesc(*pStateSaveArea); + } + default: + return nullptr; + } } } @@ -1082,11 +1176,16 @@ uint32_t DebugSessionImp::typeToRegsetFlags(uint32_t type) { case ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU: case ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU: case ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU: + case ZET_DEBUG_REGSET_TYPE_SCALAR_INTEL_GPU: + case ZET_DEBUG_REGSET_TYPE_MSG_INTEL_GPU: return ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE; case ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU: case ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU: case ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU: + case ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU: + case ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU: + case ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU: return ZET_DEBUG_REGSET_FLAG_READABLE; default: @@ -1096,15 +1195,39 @@ uint32_t DebugSessionImp::typeToRegsetFlags(uint32_t type) { size_t DebugSessionImp::calculateThreadSlotOffset(EuThread::ThreadId threadId) { auto pStateSaveAreaHeader = getStateSaveAreaHeader(); - return pStateSaveAreaHeader->versionHeader.size * 8 + pStateSaveAreaHeader->regHeader.state_area_offset + ((((threadId.slice * pStateSaveAreaHeader->regHeader.num_subslices_per_slice + threadId.subslice) * pStateSaveAreaHeader->regHeader.num_eus_per_subslice + threadId.eu) * pStateSaveAreaHeader->regHeader.num_threads_per_eu + threadId.thread) * pStateSaveAreaHeader->regHeader.state_save_size); + if (pStateSaveAreaHeader->versionHeader.version.major >= 3) { + return pStateSaveAreaHeader->versionHeader.size * 8 + pStateSaveAreaHeader->regHeaderV3.state_area_offset + ((((threadId.slice * pStateSaveAreaHeader->regHeaderV3.num_subslices_per_slice + threadId.subslice) * pStateSaveAreaHeader->regHeaderV3.num_eus_per_subslice + threadId.eu) * pStateSaveAreaHeader->regHeaderV3.num_threads_per_eu + threadId.thread) * pStateSaveAreaHeader->regHeaderV3.state_save_size); + } else { + return pStateSaveAreaHeader->versionHeader.size * 8 + pStateSaveAreaHeader->regHeader.state_area_offset + ((((threadId.slice * pStateSaveAreaHeader->regHeader.num_subslices_per_slice + threadId.subslice) * pStateSaveAreaHeader->regHeader.num_eus_per_subslice + threadId.eu) * pStateSaveAreaHeader->regHeader.num_threads_per_eu + threadId.thread) * pStateSaveAreaHeader->regHeader.state_save_size); + } } size_t DebugSessionImp::calculateRegisterOffsetInThreadSlot(const SIP::regset_desc *regdesc, uint32_t start) { return regdesc->offset + regdesc->bytes * start; } +ze_result_t DebugSessionImp::readModeFlags(uint32_t start, uint32_t count, void *pRegisterValues) { + if (start != 0 || count != 1) { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + auto &stateSaveAreaHeader = NEO::SipKernel::getBindlessDebugSipKernel(*connectedDevice->getNEODevice()).getStateSaveAreaHeader(); + auto pStateSaveArea = reinterpret_cast(stateSaveAreaHeader.data()); + const size_t size = 4; + memcpy_s(pRegisterValues, size, &pStateSaveArea->regHeaderV3.sip_flags, size); + return ZE_RESULT_SUCCESS; +} +ze_result_t DebugSessionImp::readDebugScratchRegisters(uint32_t start, uint32_t count, void *pRegisterValues) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} +ze_result_t DebugSessionImp::readThreadScratchRegisters(EuThread::ThreadId threadId, uint32_t start, uint32_t count, void *pRegisterValues) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + ze_result_t DebugSessionImp::readSbaRegisters(EuThread::ThreadId threadId, uint32_t start, uint32_t count, void *pRegisterValues) { - auto sbaRegDesc = DebugSessionImp::getSbaRegsetDesc(); + + auto &stateSaveAreaHeader = NEO::SipKernel::getBindlessDebugSipKernel(*connectedDevice->getNEODevice()).getStateSaveAreaHeader(); + auto pStateSaveArea = reinterpret_cast(stateSaveAreaHeader.data()); + auto sbaRegDesc = DebugSessionImp::getSbaRegsetDesc(*pStateSaveArea); if (start >= sbaRegDesc->num) { return ZE_RESULT_ERROR_INVALID_ARGUMENT; @@ -1272,23 +1395,43 @@ ze_result_t DebugSession::getRegisterSetProperties(Device *device, uint32_t *pCo } }; - auto pStateSaveArea = reinterpret_cast(stateSaveAreaHeader.data()); + auto pStateSaveArea = reinterpret_cast(stateSaveAreaHeader.data()); - parseRegsetDesc(pStateSaveArea->regHeader.grf, ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.addr, ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.flag, ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.emask, ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.sr, ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.cr, ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.tdr, ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.acc, ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.mme, ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.sp, ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU); + if (pStateSaveArea->versionHeader.version.major >= 3) { + parseRegsetDesc(pStateSaveArea->regHeaderV3.grf, ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.addr, ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.flag, ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.emask, ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.sr, ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.cr, ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.tdr, ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.acc, ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.mme, ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.sp, ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU); + parseRegsetDesc(*DebugSessionImp::getSbaRegsetDesc(*pStateSaveArea), ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.dbg_reg, ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.fc, ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.msg, ZET_DEBUG_REGSET_TYPE_MSG_INTEL_GPU); + parseRegsetDesc(*DebugSessionImp::getModeFlagsRegsetDesc(), ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU); + parseRegsetDesc(*DebugSessionImp::getDebugScratchRegsetDesc(), ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU); + parseRegsetDesc(*DebugSessionImp::getThreadScratchRegsetDesc(), ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeaderV3.scalar, ZET_DEBUG_REGSET_TYPE_SCALAR_INTEL_GPU); - parseRegsetDesc(*DebugSessionImp::getSbaRegsetDesc(), ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU); - - parseRegsetDesc(pStateSaveArea->regHeader.dbg_reg, ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU); - parseRegsetDesc(pStateSaveArea->regHeader.fc, ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU); + } else { + parseRegsetDesc(pStateSaveArea->regHeader.grf, ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.addr, ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.flag, ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.emask, ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.sr, ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.cr, ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.tdr, ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.acc, ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.mme, ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.sp, ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU); + parseRegsetDesc(*DebugSessionImp::getSbaRegsetDesc(*pStateSaveArea), ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.dbg_reg, ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU); + parseRegsetDesc(pStateSaveArea->regHeader.fc, ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU); + } if (!*pCount || (*pCount > totalRegsetNum)) { *pCount = totalRegsetNum; @@ -1356,6 +1499,12 @@ ze_result_t DebugSessionImp::readRegisters(ze_device_thread_t thread, uint32_t t if (type == ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU) { return readSbaRegisters(threadId, start, count, pRegisterValues); + } else if (type == ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU) { + return readModeFlags(start, count, pRegisterValues); + } else if (type == ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU) { + return readDebugScratchRegisters(start, count, pRegisterValues); + } else if (type == ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU) { + return readThreadScratchRegisters(threadId, start, count, pRegisterValues); } return readRegistersImp(threadId, type, start, count, pRegisterValues); diff --git a/level_zero/tools/source/debug/debug_session_imp.h b/level_zero/tools/source/debug/debug_session_imp.h index 63046239e4..dc8246123c 100644 --- a/level_zero/tools/source/debug/debug_session_imp.h +++ b/level_zero/tools/source/debug/debug_session_imp.h @@ -64,7 +64,11 @@ struct DebugSessionImp : DebugSession { virtual void detachTile() = 0; virtual void cleanRootSessionAfterDetach(uint32_t deviceIndex) = 0; - static const SIP::regset_desc *getSbaRegsetDesc(); + static bool isHeaplessMode(const SIP::intelgt_state_save_area_V3 &ssa); + static const SIP::regset_desc *getSbaRegsetDesc(const NEO::StateSaveAreaHeader &ssah); + static const SIP::regset_desc *getModeFlagsRegsetDesc(); + static const SIP::regset_desc *getDebugScratchRegsetDesc(); + static const SIP::regset_desc *getThreadScratchRegsetDesc(); static uint32_t typeToRegsetFlags(uint32_t type); constexpr static int64_t interruptTimeout = 2000; @@ -92,10 +96,15 @@ struct DebugSessionImp : DebugSession { ze_result_t validateThreadAndDescForMemoryAccess(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc); virtual void enqueueApiEvent(zet_debug_event_t &debugEvent) = 0; + size_t calculateSrMagicOffset(const NEO::StateSaveAreaHeader *header, EuThread *thread); MOCKABLE_VIRTUAL bool readSystemRoutineIdent(EuThread *thread, uint64_t vmHandle, SIP::sr_ident &srMagic); MOCKABLE_VIRTUAL bool readSystemRoutineIdentFromMemory(EuThread *thread, const void *stateSaveArea, SIP::sr_ident &srIdent); ze_result_t readSbaRegisters(EuThread::ThreadId thread, uint32_t start, uint32_t count, void *pRegisterValues); + ze_result_t readModeFlags(uint32_t start, uint32_t count, void *pRegisterValues); + ze_result_t readDebugScratchRegisters([[maybe_unused]] uint32_t start, [[maybe_unused]] uint32_t count, [[maybe_unused]] void *pRegisterValues); + ze_result_t readThreadScratchRegisters([[maybe_unused]] EuThread::ThreadId thread, [[maybe_unused]] uint32_t start, [[maybe_unused]] uint32_t count, [[maybe_unused]] void *pRegisterValues); + MOCKABLE_VIRTUAL bool isForceExceptionOrForceExternalHaltOnlyExceptionReason(uint32_t *cr0); MOCKABLE_VIRTUAL bool isAIPequalToThreadStartIP(uint32_t *cr0, uint32_t *dbg0); @@ -107,7 +116,7 @@ struct DebugSessionImp : DebugSession { MOCKABLE_VIRTUAL void generateEventsForStoppedThreads(const std::vector &threadIds); MOCKABLE_VIRTUAL void generateEventsForPendingInterrupts(); - const SIP::StateSaveAreaHeader *getStateSaveAreaHeader(); + const NEO::StateSaveAreaHeader *getStateSaveAreaHeader(); void validateAndSetStateSaveAreaHeader(uint64_t vmHandle, uint64_t gpuVa); virtual void readStateSaveAreaHeader(){}; diff --git a/level_zero/tools/test/unit_tests/sources/debug/debug_session_common.h b/level_zero/tools/test/unit_tests/sources/debug/debug_session_common.h index e976ec186c..54a0c02617 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/debug_session_common.h +++ b/level_zero/tools/test/unit_tests/sources/debug/debug_session_common.h @@ -7,6 +7,7 @@ #pragma once +#include "shared/source/debugger/debugger_l0.h" #include "shared/source/os_interface/os_interface.h" #include "shared/test/common/mocks/mock_device.h" #include "shared/test/common/mocks/mock_sip.h" @@ -29,6 +30,15 @@ struct DebugApiFixture : public DeviceFixture { MockRootDeviceEnvironment::resetBuiltins(neoDevice->executionEnvironment->rootDeviceEnvironments[0].get(), mockBuiltins); } + void setUpV3Header() { + mockBuiltins->stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(3); + } + void setUpV3HeaderHeapless() { + mockBuiltins->stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(3); + auto pStateSaveArea = reinterpret_cast(mockBuiltins->stateSaveAreaHeader.data()); + pStateSaveArea->regHeaderV3.sip_flags = 0; + } + void tearDown() { DeviceFixture::tearDown(); } diff --git a/level_zero/tools/test/unit_tests/sources/debug/debug_session_registers_access.cpp b/level_zero/tools/test/unit_tests/sources/debug/debug_session_registers_access.cpp index 3ea73df0b4..d6fc426750 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/debug_session_registers_access.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/debug_session_registers_access.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2023-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -15,6 +15,21 @@ namespace L0 { namespace ult { DebugSessionRegistersAccess::DebugSessionRegistersAccess() = default; DebugSessionRegistersAccess::~DebugSessionRegistersAccess() = default; + +void DebugSessionRegistersAccessV3::setUp() { + zet_debug_config_t config = {}; + config.pid = 0x1234; + auto hwInfo = *NEO::defaultHwInfo.get(); + + neoDevice = NEO::MockDevice::createWithNewExecutionEnvironment(&hwInfo, 0); + deviceImp = std::make_unique(neoDevice, neoDevice->getExecutionEnvironment()); + + session = std::make_unique(config, deviceImp.get(), true, 3); + + session->allThreads[stoppedThreadId]->stopThread(1u); + session->allThreads[stoppedThreadId]->reportAsStopped(); +} + void DebugSessionRegistersAccess::setUp() { zet_debug_config_t config = {}; config.pid = 0x1234; diff --git a/level_zero/tools/test/unit_tests/sources/debug/debug_session_registers_access.h b/level_zero/tools/test/unit_tests/sources/debug/debug_session_registers_access.h index d459943552..4f4fc6107b 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/debug_session_registers_access.h +++ b/level_zero/tools/test/unit_tests/sources/debug/debug_session_registers_access.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2023 Intel Corporation + * Copyright (C) 2022-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,7 +20,7 @@ struct MockDebugSession; struct DebugSessionRegistersAccess { DebugSessionRegistersAccess(); ~DebugSessionRegistersAccess(); - void setUp(); + virtual void setUp(); void tearDown(); @@ -33,5 +33,9 @@ struct DebugSessionRegistersAccess { NEO::MockDevice *neoDevice = nullptr; }; +struct DebugSessionRegistersAccessV3 : public DebugSessionRegistersAccess { + void setUp() override; +}; + } // namespace ult } // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/debug/debug_session_tests.cpp b/level_zero/tools/test/unit_tests/sources/debug/debug_session_tests.cpp index f07050aed5..892d7a23df 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/debug_session_tests.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/debug_session_tests.cpp @@ -461,6 +461,24 @@ TEST(DebugSessionTest, givenNoStoppedThreadWhenAddingNewlyStoppedThenThreadIsNot EXPECT_EQ(0u, sessionMock->newlyStoppedThreads.size()); } +TEST(DebugSessionTest, givenV3SipHeaderWhenCalculatingThreadOffsetThenCorrectResultReturned) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + auto hwInfo = *NEO::defaultHwInfo.get(); + + NEO::MockDevice *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment(&hwInfo, 0)); + MockDeviceImp deviceImp(neoDevice, neoDevice->getExecutionEnvironment()); + + auto sessionMock = std::make_unique(config, &deviceImp, true, 3); + ze_device_thread_t thread = {0, 0, 0, 0}; + EuThread::ThreadId threadId(0, thread); + + auto threadSlotOffset = sessionMock->calculateThreadSlotOffset(threadId); + auto pStateSaveAreaHeader = reinterpret_cast(sessionMock->stateSaveAreaHeader.data()); + size_t expectedOffset = pStateSaveAreaHeader->versionHeader.size * 8 + pStateSaveAreaHeader->regHeaderV3.state_area_offset + ((((threadId.slice * pStateSaveAreaHeader->regHeaderV3.num_subslices_per_slice + threadId.subslice) * pStateSaveAreaHeader->regHeaderV3.num_eus_per_subslice + threadId.eu) * pStateSaveAreaHeader->regHeaderV3.num_threads_per_eu + threadId.thread) * pStateSaveAreaHeader->regHeaderV3.state_save_size); + EXPECT_EQ(threadSlotOffset, expectedOffset); +} + TEST(DebugSessionTest, givenStoppedThreadAndNoSrMagicWhenAddingNewlyStoppedThenThreadIsNotAddedToNewlyStopped) { zet_debug_config_t config = {}; config.pid = 0x1234; @@ -2315,6 +2333,43 @@ TEST_F(MultiTileDebugSessionTest, GivenMultitileDeviceWhenCallingAreRequestedThr EXPECT_TRUE(stopped); } +using DebugSessionRegistersAccessTestV3 = Test; + +TEST_F(DebugSessionRegistersAccessTestV3, givenV3StateSaveHeaderWhenCalculatingSrMagicOffsetResultIsCorrect) { + + auto pStateSaveAreaHeader = session->getStateSaveAreaHeader(); + EuThread::ThreadId thread0(0, 0, 0, 0, 0); + auto threadSlotOffset = session->calculateThreadSlotOffset(thread0); + auto size = session->calculateSrMagicOffset(pStateSaveAreaHeader, session->allThreads[thread0].get()); + ASSERT_EQ(size, threadSlotOffset + pStateSaveAreaHeader->regHeaderV3.sr_magic_offset); +} + +TEST_F(DebugSessionRegistersAccessTestV3, givenTypeToRegsetDescCalledThenCorrectRegdescIsReturned) { + auto pStateSaveAreaHeader = session->getStateSaveAreaHeader(); + + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_INVALID_INTEL_GPU), nullptr); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.grf); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.addr); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.flag); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.emask); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.sr); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.cr); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.tdr); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.acc); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.mme); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.sp); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.dbg_reg); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.fc); + EXPECT_NE(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU), nullptr); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_MSG_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.msg); + EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_SCALAR_INTEL_GPU), &pStateSaveAreaHeader->regHeaderV3.scalar); + EXPECT_NE(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU), nullptr); + EXPECT_NE(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU), nullptr); + EXPECT_NE(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU), nullptr); + + EXPECT_EQ(session->typeToRegsetDesc(0x1234), nullptr); +} + using DebugSessionRegistersAccessTest = Test; TEST_F(DebugSessionRegistersAccessTest, givenTypeToRegsetDescCalledThenCorrectRegdescIsReturned) { @@ -2334,6 +2389,7 @@ TEST_F(DebugSessionRegistersAccessTest, givenTypeToRegsetDescCalledThenCorrectRe EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU), &pStateSaveAreaHeader->regHeader.dbg_reg); EXPECT_EQ(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU), &pStateSaveAreaHeader->regHeader.fc); EXPECT_NE(session->typeToRegsetDesc(ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU), nullptr); + EXPECT_EQ(session->typeToRegsetDesc(0x1234), nullptr); } TEST_F(DebugSessionRegistersAccessTest, givenNoStateSaveAreWhenTypeToRegsetDescCalledThennullptrReturned) { @@ -2665,6 +2721,29 @@ TEST_F(DebugSessionRegistersAccessTest, GivenBindlessSipVersion2WhenCallingResum EXPECT_EQ(1u, session->writeResumeCommandCalled); } +TEST_F(DebugSessionRegistersAccessTestV3, WhenReadingDebugScratchRegisterThenUnsupportedFeatureReturned) { + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, session->readDebugScratchRegisters(0, 0, nullptr)); +} + +TEST_F(DebugSessionRegistersAccessTestV3, WhenReadingThreadScratchRegisterThenUnsupportedFeatureReturned) { + ze_device_thread_t thread = {0, 0, 0, 0}; + EuThread::ThreadId threadId = {0, thread}; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, session->readThreadScratchRegisters(threadId, 0, 0, nullptr)); +} + +TEST_F(DebugSessionRegistersAccessTestV3, WhenReadingModeRegisterThenCorrectResultReturned) { + auto mockBuiltins = new MockBuiltins(); + mockBuiltins->stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(3); + MockRootDeviceEnvironment::resetBuiltins(neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0].get(), mockBuiltins); + + uint32_t modeFlags; + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, session->readModeFlags(1, 1, &modeFlags)); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, session->readModeFlags(0, 2, &modeFlags)); + EXPECT_EQ(ZE_RESULT_SUCCESS, session->readModeFlags(0, 1, &modeFlags)); + EXPECT_EQ(modeFlags, SIP::SIP_FLAG_HEAPLESS); + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(); +} + TEST_F(DebugSessionRegistersAccessTest, WhenReadingSbaRegistersThenCorrectAddressesAreReturned) { { diff --git a/level_zero/tools/test/unit_tests/sources/debug/linux/debug_session_fixtures_linux.h b/level_zero/tools/test/unit_tests/sources/debug/linux/debug_session_fixtures_linux.h index 1347a592a0..fbab4076ba 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/linux/debug_session_fixtures_linux.h +++ b/level_zero/tools/test/unit_tests/sources/debug/linux/debug_session_fixtures_linux.h @@ -52,6 +52,9 @@ struct MockIoctlHandler : public L0::DebugSessionLinux::IoctlHandler { } if (!pReadArrayRef.empty()) { + if (pread2RetVal && preadCalled == 2) { + return pread2RetVal; + } auto offsetInMemory = offset - pReadBase; auto result = memcpy_s(buf, count, pReadArrayRef.begin() + offsetInMemory, std::min(count, pReadArrayRef.size() - offsetInMemory)); if (result == 0) { @@ -63,7 +66,11 @@ struct MockIoctlHandler : public L0::DebugSessionLinux::IoctlHandler { if (count > 0 && preadRetVal > 0) { memset(buf, 0xaa, count); } - return preadRetVal; + if (pread2RetVal && preadCalled == 2) { + return pread2RetVal; + } else { + return preadRetVal; + } } int64_t pwrite(int fd, const void *buf, size_t count, off_t offset) override { @@ -134,6 +141,7 @@ struct MockIoctlHandler : public L0::DebugSessionLinux::IoctlHandler { uint64_t pReadBase = 0; int64_t preadCalled = 0; int64_t preadRetVal = 0; + int64_t pread2RetVal = 0; ArrayRef pWriteArrayRef; uint64_t pWriteBase = 0; diff --git a/level_zero/tools/test/unit_tests/sources/debug/linux/prelim/test_debug_api_linux.cpp b/level_zero/tools/test/unit_tests/sources/debug/linux/prelim/test_debug_api_linux.cpp index 3f600781ad..dbcb0f79ea 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/linux/prelim/test_debug_api_linux.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/linux/prelim/test_debug_api_linux.cpp @@ -2389,6 +2389,58 @@ TEST_F(DebugApiLinuxTest, GivenBindInfoForVmHandleWhenReadingModuleDebugAreaRetu } } +TEST_F(DebugApiLinuxTest, GivenBindInfoForVmHandleWhenReadingStateSaveAreaRegHeaderFailsThenHeaderNotSet) { + + auto session = std::make_unique(zet_debug_config_t{0x1234}, device, 10); + ASSERT_NE(nullptr, session); + + auto handler = new MockIoctlHandlerI915; + auto stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(2); + handler->mmapRet = stateSaveAreaHeader.data(); + + handler->setPreadMemory(stateSaveAreaHeader.data(), stateSaveAreaHeader.size(), 0x1000); + handler->pread2RetVal = -1; + + session->ioctlHandler.reset(handler); + session->clientHandle = MockDebugSessionLinuxi915::mockClientHandle; + + uint64_t vmHandle = 6; + session->clientHandleToConnection[MockDebugSessionLinuxi915::mockClientHandle]->vmToContextStateSaveAreaBindInfo[vmHandle] = {0x1000, sizeof(SIP::StateSaveAreaHeader)}; + + session->readStateSaveAreaHeader(); + EXPECT_EQ(2, handler->preadCalled); + EXPECT_EQ(session->stateSaveAreaHeader.size(), 0u); +} + +TEST_F(DebugApiLinuxTest, GivenBindInfoForVmHandleWhenReadingStateSaveAreaWithV4HeaderThenGpuMemoryIsRead) { + auto session = std::make_unique(zet_debug_config_t{0x1234}, device, 10); + ASSERT_NE(nullptr, session); + + auto handler = new MockIoctlHandlerI915; + auto stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(3); + handler->mmapRet = stateSaveAreaHeader.data(); + + handler->setPreadMemory(stateSaveAreaHeader.data(), stateSaveAreaHeader.size(), 0x1000); + + session->ioctlHandler.reset(handler); + session->clientHandle = MockDebugSessionLinuxi915::mockClientHandle; + + uint64_t vmHandle = 6; + session->clientHandleToConnection[MockDebugSessionLinuxi915::mockClientHandle]->vmToContextStateSaveAreaBindInfo[vmHandle] = {0x1000, sizeof(SIP::StateSaveAreaHeader)}; + + session->readStateSaveAreaHeader(); + + if (debugManager.flags.EnableDebuggerMmapMemoryAccess.get()) { + EXPECT_EQ(2, handler->mmapCalled); + EXPECT_EQ(2, handler->munmapCalled); + } else { + EXPECT_EQ(2, handler->preadCalled); + } + EXPECT_EQ(MockDebugSessionLinuxi915::mockClientHandle, handler->vmOpen.client_handle); + EXPECT_EQ(vmHandle, handler->vmOpen.handle); + EXPECT_EQ(static_cast(PRELIM_I915_DEBUG_VM_OPEN_READ_ONLY), handler->vmOpen.flags); +} + TEST_F(DebugApiLinuxTest, GivenBindInfoForVmHandleWhenReadingStateSaveAreaThenGpuMemoryIsRead) { auto session = std::make_unique(zet_debug_config_t{0x1234}, device, 10); ASSERT_NE(nullptr, session); @@ -2408,10 +2460,10 @@ TEST_F(DebugApiLinuxTest, GivenBindInfoForVmHandleWhenReadingStateSaveAreaThenGp session->readStateSaveAreaHeader(); if (debugManager.flags.EnableDebuggerMmapMemoryAccess.get()) { - EXPECT_EQ(1, handler->mmapCalled); - EXPECT_EQ(1, handler->munmapCalled); + EXPECT_EQ(2, handler->mmapCalled); + EXPECT_EQ(2, handler->munmapCalled); } else { - EXPECT_EQ(1, handler->preadCalled); + EXPECT_EQ(2, handler->preadCalled); } EXPECT_EQ(MockDebugSessionLinuxi915::mockClientHandle, handler->vmOpen.client_handle); EXPECT_EQ(vmHandle, handler->vmOpen.handle); @@ -7389,6 +7441,46 @@ TEST_F(DebugApiRegistersAccessTest, givenNoneThreadsStoppedWhenWriteRegistersCal EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, zetDebugWriteRegisters(session->toHandle(), stoppedThread, ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU, 0, 1, grf)); } +TEST_F(DebugApiRegistersAccessTest, GivenThreadAndV3HeaderWhenReadingSystemRoutineIdentThenCorrectStateSaveAreaLocationIsRead) { + + SIP::version version = {3, 0, 0}; + mockBuiltins->stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(3); + initStateSaveArea(session->stateSaveAreaHeader, version, device); + + ioctlHandler = new MockIoctlHandlerI915; + ioctlHandler->mmapRet = session->stateSaveAreaHeader.data(); + ioctlHandler->mmapBase = stateSaveAreaGpuVa; + + ioctlHandler->setPreadMemory(session->stateSaveAreaHeader.data(), session->stateSaveAreaHeader.size(), stateSaveAreaGpuVa); + ioctlHandler->setPwriteMemory(session->stateSaveAreaHeader.data(), session->stateSaveAreaHeader.size(), stateSaveAreaGpuVa); + + session->ioctlHandler.reset(ioctlHandler); + EuThread thread({0, 0, 0, 0, 0}); + + SIP::sr_ident srIdent = {{0}}; + auto result = session->readSystemRoutineIdent(&thread, vmHandle, srIdent); + + EXPECT_TRUE(result); + + EXPECT_EQ(2u, srIdent.count); + EXPECT_EQ(3u, srIdent.version.major); + EXPECT_EQ(0u, srIdent.version.minor); + EXPECT_EQ(0u, srIdent.version.patch); + EXPECT_STREQ("srmagic", srIdent.magic); + + EuThread thread2({0, 0, 0, 7, 3}); + + result = session->readSystemRoutineIdent(&thread, vmHandle, srIdent); + + EXPECT_TRUE(result); + + EXPECT_EQ(2u, srIdent.count); + EXPECT_EQ(3u, srIdent.version.major); + EXPECT_EQ(0u, srIdent.version.minor); + EXPECT_EQ(0u, srIdent.version.patch); + EXPECT_STREQ("srmagic", srIdent.magic); +} + TEST_F(DebugApiRegistersAccessTest, GivenThreadWhenReadingSystemRoutineIdentThenCorrectStateSaveAreaLocationIsRead) { SIP::version version = {2, 0, 0}; initStateSaveArea(session->stateSaveAreaHeader, version, device); @@ -7715,6 +7807,24 @@ TEST_F(DebugApiRegistersAccessTest, givenWriteSbaRegistersCalledThenErrorInvalid EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, zetDebugWriteRegisters(session->toHandle(), {0, 0, 0, 0}, ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU, 0, 1, nullptr)); } +TEST_F(DebugApiRegistersAccessTest, givenReadDebugScratchRegisterCalledThenUnsupportedFeatureReturned) { + SIP::version version = {3, 0, 0}; + initStateSaveArea(session->stateSaveAreaHeader, version, device); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zetDebugReadRegisters(session->toHandle(), {0, 0, 0, 0}, ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU, 0, 1, nullptr)); +} + +TEST_F(DebugApiRegistersAccessTest, givenReadThreadScratchRegisterCalledThenUnsupportedFeatureReturned) { + SIP::version version = {3, 0, 0}; + initStateSaveArea(session->stateSaveAreaHeader, version, device); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zetDebugReadRegisters(session->toHandle(), {0, 0, 0, 0}, ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU, 0, 1, nullptr)); +} + +TEST_F(DebugApiRegistersAccessTest, givenReadModeRegisterCalledThenSuccessIsReturned) { + SIP::version version = {3, 0, 0}; + initStateSaveArea(session->stateSaveAreaHeader, version, device); + EXPECT_EQ(ZE_RESULT_SUCCESS, zetDebugReadRegisters(session->toHandle(), {0, 0, 0, 0}, ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU, 0, 1, nullptr)); +} + using DebugApiLinuxMultitileTest = Test; TEST_F(DebugApiLinuxMultitileTest, GivenRootDeviceAndTileAttachDisabledWhenDebugSessionInitializedThenEuThreadsAreCreated) { diff --git a/level_zero/tools/test/unit_tests/sources/debug/mock_debug_session.h b/level_zero/tools/test/unit_tests/sources/debug/mock_debug_session.h index 343d1d4438..9b145727f3 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/mock_debug_session.h +++ b/level_zero/tools/test/unit_tests/sources/debug/mock_debug_session.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Intel Corporation + * Copyright (C) 2021-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -147,11 +147,11 @@ struct MockDebugSession : public L0::DebugSessionImp { using L0::DebugSession::allThreads; using L0::DebugSession::debugArea; - using L0::DebugSessionImp::addThreadToNewlyStoppedFromRaisedAttention; using L0::DebugSessionImp::allocateStateSaveAreaMemory; using L0::DebugSessionImp::apiEvents; using L0::DebugSessionImp::applyResumeWa; + using L0::DebugSessionImp::calculateSrMagicOffset; using L0::DebugSessionImp::calculateThreadSlotOffset; using L0::DebugSessionImp::checkTriggerEventsForAttention; using L0::DebugSessionImp::fillResumeAndStoppedThreadsFromNewlyStopped; @@ -161,7 +161,10 @@ struct MockDebugSession : public L0::DebugSessionImp { using L0::DebugSessionImp::getRegisterSize; using L0::DebugSessionImp::getStateSaveAreaHeader; using L0::DebugSessionImp::newAttentionRaised; + using L0::DebugSessionImp::readDebugScratchRegisters; + using L0::DebugSessionImp::readModeFlags; using L0::DebugSessionImp::readSbaRegisters; + using L0::DebugSessionImp::readThreadScratchRegisters; using L0::DebugSessionImp::registersAccessHelper; using L0::DebugSessionImp::resumeAccidentallyStoppedThreads; using L0::DebugSessionImp::sendInterrupts; @@ -189,7 +192,10 @@ struct MockDebugSession : public L0::DebugSessionImp { MockDebugSession(const zet_debug_config_t &config, L0::Device *device) : MockDebugSession(config, device, true) {} - MockDebugSession(const zet_debug_config_t &config, L0::Device *device, bool rootAttach) : DebugSessionImp(config, device) { + MockDebugSession(const zet_debug_config_t &config, L0::Device *device, bool rootAttach) : MockDebugSession(config, device, rootAttach, 2) { + } + + MockDebugSession(const zet_debug_config_t &config, L0::Device *device, bool rootAttach, uint32_t stateSaveHeaderVersion) : DebugSessionImp(config, device) { if (device) { topologyMap = DebugSessionMock::buildMockTopology(device); } @@ -197,9 +203,12 @@ struct MockDebugSession : public L0::DebugSessionImp { if (rootAttach) { createEuThreads(); } - stateSaveAreaHeader = NEO::MockSipData::createStateSaveAreaHeader(2); + if (stateSaveHeaderVersion == 3) { + stateSaveAreaHeader = NEO::MockSipData::createStateSaveAreaHeader(3); + } else { + stateSaveAreaHeader = NEO::MockSipData::createStateSaveAreaHeader(2); + } } - ~MockDebugSession() override { for (auto session : tileSessions) { delete session.first; diff --git a/level_zero/tools/test/unit_tests/sources/debug/test_debug_api.cpp b/level_zero/tools/test/unit_tests/sources/debug/test_debug_api.cpp index 620ae41043..c9f256ecbd 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/test_debug_api.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/test_debug_api.cpp @@ -282,6 +282,13 @@ TEST_F(DebugApiTest, givenZeroCountWhenGetRegisterSetPropertiesCalledThenCorrect EXPECT_EQ(13u, count); } +TEST_F(DebugApiTest, givenZeroCountWhenGetRegisterSetPropertiesCalledWithV3HeaderThenCorrectCountIsSet) { + uint32_t count = 0; + setUpV3Header(); + EXPECT_EQ(ZE_RESULT_SUCCESS, zetDebugGetRegisterSetProperties(device->toHandle(), &count, nullptr)); + EXPECT_EQ(17u, count); +} + TEST_F(DebugApiTest, givenGetRegisterSetPropertiesCalledAndExtraSpaceIsProvidedThenCorrectPropertiesReturned) { uint32_t count = 100; std::vector regsetProps(count); @@ -338,6 +345,95 @@ TEST_F(DebugApiTest, givenSIPHeaderGRFCountNotEqualTo128ThenGetRegisterSetProper } } +TEST_F(DebugApiTest, givenGetRegisterSetPropertiesCalledWithV3HeaderCorrectPropertiesReturned) { + + setUpV3Header(); + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zetDebugGetRegisterSetProperties(device->toHandle(), &count, nullptr)); + EXPECT_EQ(17u, count); + + std::vector regsetProps(count); + EXPECT_EQ(ZE_RESULT_SUCCESS, zetDebugGetRegisterSetProperties(device->toHandle(), &count, regsetProps.data())); + + EXPECT_EQ(17u, count); + + auto validateRegsetProps = [](const zet_debug_regset_properties_t ®setProps, + zet_debug_regset_type_intel_gpu_t type, zet_debug_regset_flags_t flags, + uint32_t num, uint32_t bits, uint32_t bytes) { + EXPECT_EQ(regsetProps.stype, ZET_STRUCTURE_TYPE_DEBUG_REGSET_PROPERTIES); + EXPECT_EQ(regsetProps.pNext, nullptr); + EXPECT_EQ(regsetProps.type, type); + EXPECT_EQ(regsetProps.version, 0u); + EXPECT_EQ(regsetProps.generalFlags, flags); + EXPECT_EQ(regsetProps.count, num); + EXPECT_EQ(regsetProps.bitSize, bits); + EXPECT_EQ(regsetProps.byteSize, bytes); + }; + + validateRegsetProps(regsetProps[0], ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 128, 256, 32); + validateRegsetProps(regsetProps[1], ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 256, 32); + validateRegsetProps(regsetProps[2], ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 2, 32, 4); + validateRegsetProps(regsetProps[3], ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 1, 32, 4); + validateRegsetProps(regsetProps[4], ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 2, 128, 16); + validateRegsetProps(regsetProps[5], ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 128, 16); + validateRegsetProps(regsetProps[6], ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 1, 128, 16); + validateRegsetProps(regsetProps[7], ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 10, 256, 32); + validateRegsetProps(regsetProps[8], ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 256, 32); + validateRegsetProps(regsetProps[9], ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 128, 16); + validateRegsetProps(regsetProps[10], ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 64, 8); + validateRegsetProps(regsetProps[11], ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 32, 4); + validateRegsetProps(regsetProps[12], ZET_DEBUG_REGSET_TYPE_MSG_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 64, 8); + validateRegsetProps(regsetProps[13], ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 1, 32, 4); + validateRegsetProps(regsetProps[14], ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 2, 64, 8); + validateRegsetProps(regsetProps[15], ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 2, 64, 8); + validateRegsetProps(regsetProps[16], ZET_DEBUG_REGSET_TYPE_SCALAR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 64, 8); +} + +TEST_F(DebugApiTest, givenGetRegisterSetPropertiesCalledWhenV3HeaderHeaplessThenCorrectPropertiesReturned) { + + setUpV3HeaderHeapless(); + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zetDebugGetRegisterSetProperties(device->toHandle(), &count, nullptr)); + EXPECT_EQ(18u, count); + + std::vector regsetProps(count); + EXPECT_EQ(ZE_RESULT_SUCCESS, zetDebugGetRegisterSetProperties(device->toHandle(), &count, regsetProps.data())); + + EXPECT_EQ(18u, count); + + auto validateRegsetProps = [](const zet_debug_regset_properties_t ®setProps, + zet_debug_regset_type_intel_gpu_t type, zet_debug_regset_flags_t flags, + uint32_t num, uint32_t bits, uint32_t bytes) { + EXPECT_EQ(regsetProps.stype, ZET_STRUCTURE_TYPE_DEBUG_REGSET_PROPERTIES); + EXPECT_EQ(regsetProps.pNext, nullptr); + EXPECT_EQ(regsetProps.type, type); + EXPECT_EQ(regsetProps.version, 0u); + EXPECT_EQ(regsetProps.generalFlags, flags); + EXPECT_EQ(regsetProps.count, num); + EXPECT_EQ(regsetProps.bitSize, bits); + EXPECT_EQ(regsetProps.byteSize, bytes); + }; + + validateRegsetProps(regsetProps[0], ZET_DEBUG_REGSET_TYPE_GRF_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 128, 256, 32); + validateRegsetProps(regsetProps[1], ZET_DEBUG_REGSET_TYPE_ADDR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 256, 32); + validateRegsetProps(regsetProps[2], ZET_DEBUG_REGSET_TYPE_FLAG_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 2, 32, 4); + validateRegsetProps(regsetProps[3], ZET_DEBUG_REGSET_TYPE_CE_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 1, 32, 4); + validateRegsetProps(regsetProps[4], ZET_DEBUG_REGSET_TYPE_SR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 2, 128, 16); + validateRegsetProps(regsetProps[5], ZET_DEBUG_REGSET_TYPE_CR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 128, 16); + validateRegsetProps(regsetProps[6], ZET_DEBUG_REGSET_TYPE_TDR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 1, 128, 16); + validateRegsetProps(regsetProps[7], ZET_DEBUG_REGSET_TYPE_ACC_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 10, 256, 32); + validateRegsetProps(regsetProps[8], ZET_DEBUG_REGSET_TYPE_MME_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 256, 32); + validateRegsetProps(regsetProps[9], ZET_DEBUG_REGSET_TYPE_SP_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 128, 16); + validateRegsetProps(regsetProps[10], ZET_DEBUG_REGSET_TYPE_SBA_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, ZET_DEBUG_SBA_COUNT_INTEL_GPU, 64, 8); + validateRegsetProps(regsetProps[11], ZET_DEBUG_REGSET_TYPE_DBG_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 64, 8); + validateRegsetProps(regsetProps[12], ZET_DEBUG_REGSET_TYPE_FC_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 32, 4); + validateRegsetProps(regsetProps[13], ZET_DEBUG_REGSET_TYPE_MSG_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 64, 8); + validateRegsetProps(regsetProps[14], ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 1, 32, 4); + validateRegsetProps(regsetProps[15], ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 2, 64, 8); + validateRegsetProps(regsetProps[16], ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE, 2, 64, 8); + validateRegsetProps(regsetProps[17], ZET_DEBUG_REGSET_TYPE_SCALAR_INTEL_GPU, ZET_DEBUG_REGSET_FLAG_READABLE | ZET_DEBUG_REGSET_FLAG_WRITEABLE, 1, 64, 8); +} + TEST_F(DebugApiTest, givenGetRegisterSetPropertiesCalledCorrectPropertiesReturned) { uint32_t count = 0; EXPECT_EQ(ZE_RESULT_SUCCESS, zetDebugGetRegisterSetProperties(device->toHandle(), &count, nullptr)); @@ -502,5 +598,63 @@ TEST_F(DebugApiTest, givenZeAffinityMaskAndEnabledDebugMessagesWhenDebugAttachCa EXPECT_EQ(std::string("ZE_AFFINITY_MASK is not recommended while using program debug API\n"), output); } +TEST_F(DebugApiTest, givenReadDebugScratchRegisterCalledThenUnsupportedFeatureReturned) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new OsInterfaceWithDebugAttach); + + L0::DeviceImp *deviceImp = static_cast(device); + auto session = new MockDebugSession(config, device, true); + session->initialize(); + deviceImp->setDebugSession(session); + SIP::version version = {3, 0, 0}; + initStateSaveArea(session->stateSaveAreaHeader, version, device); + ze_device_thread_t stoppedThread = {0, 0, 0, 0}; + EuThread::ThreadId stoppedThreadId{0, stoppedThread}; + session->allThreads[stoppedThreadId]->stopThread(1u); + session->allThreads[stoppedThreadId]->reportAsStopped(); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zetDebugReadRegisters(session->toHandle(), {0, 0, 0, 0}, ZET_DEBUG_REGSET_TYPE_DEBUG_SCRATCH_INTEL_GPU, 0, 1, nullptr)); +} + +TEST_F(DebugApiTest, givenReadThreadScratchRegisterCalledThenUnsupportedFeatureReturned) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new OsInterfaceWithDebugAttach); + + L0::DeviceImp *deviceImp = static_cast(device); + auto session = new MockDebugSession(config, device, true); + session->initialize(); + deviceImp->setDebugSession(session); + SIP::version version = {3, 0, 0}; + initStateSaveArea(session->stateSaveAreaHeader, version, device); + ze_device_thread_t stoppedThread = {0, 0, 0, 0}; + EuThread::ThreadId stoppedThreadId{0, stoppedThread}; + session->allThreads[stoppedThreadId]->stopThread(1u); + session->allThreads[stoppedThreadId]->reportAsStopped(); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zetDebugReadRegisters(session->toHandle(), {0, 0, 0, 0}, ZET_DEBUG_REGSET_TYPE_THREAD_SCRATCH_INTEL_GPU, 0, 1, nullptr)); +} + +TEST_F(DebugApiTest, givenReadModeRegisterCalledThenSuccessIsReturned) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new OsInterfaceWithDebugAttach); + + L0::DeviceImp *deviceImp = static_cast(device); + auto session = new MockDebugSession(config, device, true); + session->initialize(); + deviceImp->setDebugSession(session); + SIP::version version = {3, 0, 0}; + initStateSaveArea(session->stateSaveAreaHeader, version, device); + ze_device_thread_t stoppedThread = {0, 0, 0, 0}; + EuThread::ThreadId stoppedThreadId{0, stoppedThread}; + session->allThreads[stoppedThreadId]->stopThread(1u); + session->allThreads[stoppedThreadId]->reportAsStopped(); + uint32_t modeFlags; + EXPECT_EQ(ZE_RESULT_SUCCESS, zetDebugReadRegisters(session->toHandle(), {0, 0, 0, 0}, ZET_DEBUG_REGSET_TYPE_MODE_FLAGS_INTEL_GPU, 0, 1, &modeFlags)); +} + } // namespace ult } // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp b/level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp index 42a781b58e..806712e32c 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Intel Corporation + * Copyright (C) 2021-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -1906,7 +1906,7 @@ TEST_F(DebugApiWindowsTest, GivenStateSaveAreaVaWhenReadingStateSaveAreaThenGpuM mockWddm->srcReadBufferBaseAddress = session->stateSaveAreaVA.load(); session->readStateSaveAreaHeader(); - ASSERT_EQ(1u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]); + ASSERT_EQ(2u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]); auto stateSaveAreaRead = session->getStateSaveAreaHeader(); ASSERT_NE(nullptr, stateSaveAreaRead); EXPECT_EQ(0, memcmp(stateSaveAreaRead, stateSaveAreaHeader.data(), stateSaveAreaHeader.size())); diff --git a/shared/source/built_ins/sip.cpp b/shared/source/built_ins/sip.cpp index 8d965d3f03..a61ce8e390 100644 --- a/shared/source/built_ins/sip.cpp +++ b/shared/source/built_ins/sip.cpp @@ -10,6 +10,7 @@ #include "shared/source/built_ins/built_ins.h" #include "shared/source/debug_settings/debug_settings_manager.h" #include "shared/source/debugger/debugger.h" +#include "shared/source/debugger/debugger_l0.h" #include "shared/source/device/device.h" #include "shared/source/execution_environment/execution_environment.h" #include "shared/source/execution_environment/root_device_environment.h" @@ -93,16 +94,26 @@ size_t SipKernel::getStateSaveAreaSize(Device *device) const { return maxDbgSurfaceSize; } - auto hdr = reinterpret_cast(stateSaveAreaHeader.data()); - DEBUG_BREAK_IF(hdr->versionHeader.size * 8 != sizeof(SIP::StateSaveAreaHeader)); + auto hdr = reinterpret_cast(stateSaveAreaHeader.data()); auto numSlices = NEO::GfxCoreHelper::getHighestEnabledSlice(hwInfo); - auto stateSaveAreaSize = numSlices * - hdr->regHeader.num_subslices_per_slice * - hdr->regHeader.num_eus_per_subslice * - hdr->regHeader.num_threads_per_eu * - hdr->regHeader.state_save_size + - hdr->versionHeader.size * 8 + hdr->regHeader.state_area_offset; + size_t stateSaveAreaSize = 0; + if (hdr->versionHeader.version.major >= 3) { + stateSaveAreaSize = numSlices * + hdr->regHeaderV3.num_subslices_per_slice * + hdr->regHeaderV3.num_eus_per_subslice * + hdr->regHeaderV3.num_threads_per_eu * + hdr->regHeaderV3.state_save_size + + hdr->versionHeader.size * 8 + hdr->regHeaderV3.state_area_offset; + + } else { + stateSaveAreaSize = numSlices * + hdr->regHeader.num_subslices_per_slice * + hdr->regHeader.num_eus_per_subslice * + hdr->regHeader.num_threads_per_eu * + hdr->regHeader.state_save_size + + hdr->versionHeader.size * 8 + hdr->regHeader.state_area_offset; + } return alignUp(stateSaveAreaSize, MemoryConstants::pageSize); } diff --git a/shared/source/debugger/debugger_l0.h b/shared/source/debugger/debugger_l0.h index 881aa86b78..ed44803952 100644 --- a/shared/source/debugger/debugger_l0.h +++ b/shared/source/debugger/debugger_l0.h @@ -10,6 +10,8 @@ #include "shared/source/helpers/non_copyable_or_moveable.h" #include "shared/source/memory_manager/memory_manager.h" +#include "common/StateSaveAreaHeader.h" + #include #include #include @@ -21,6 +23,17 @@ class GraphicsAllocation; class LinearStream; class OSInterface; +// NOLINTBEGIN +struct StateSaveAreaHeader { + struct SIP::StateSaveArea versionHeader; + union { + struct SIP::intelgt_state_save_area regHeader; + struct SIP::intelgt_state_save_area_V3 regHeaderV3; + }; +}; + +// NOLINTEND + #pragma pack(1) struct SbaTrackedAddresses { char magic[8] = "sbaarea"; @@ -55,19 +68,6 @@ struct DebugAreaHeader { }; static_assert(sizeof(DebugAreaHeader) == 32u * sizeof(uint8_t)); -struct alignas(4) DebuggerVersion { - uint8_t major; - uint8_t minor; - uint16_t patch; -}; -struct alignas(8) StateSaveAreaHeader { - char magic[8] = "tssarea"; - uint64_t reserved1; - struct DebuggerVersion version; - uint8_t size; - uint8_t reserved2[3]; -}; - #pragma pack() class DebuggerL0 : public NEO::Debugger, NEO::NonCopyableOrMovableClass { diff --git a/shared/test/common/helpers/sip_init.cpp b/shared/test/common/helpers/sip_init.cpp index 1637be274b..9d10772a7a 100644 --- a/shared/test/common/helpers/sip_init.cpp +++ b/shared/test/common/helpers/sip_init.cpp @@ -5,6 +5,7 @@ * */ +#include "shared/source/debugger/debugger_l0.h" #include "shared/source/device/device.h" #include "shared/source/helpers/gfx_core_helper.h" #include "shared/source/memory_manager/memory_allocation.h" @@ -126,6 +127,61 @@ std::vector createStateSaveAreaHeader(uint32_t version, uint16_t grfNum, u }, }; + SIP::StateSaveArea versionHeader = { + // versionHeader + "tssarea", // magic + 0, // reserved1 + { // version + 3, // major + 0, // minor + 0}, // patch + 53, // size + {0, 0, 0}, // reserved2 + }; + SIP::intelgt_state_save_area_V3 regHeaderV3 = { + // regHeader + 1, // num_slices + 1, // num_subslices_per_slice + 8, // num_eus_per_subslice + 7, // num_threads_per_eu + 0, // state_area_offset + 6144, // state_save_size + 0, // slm_area_offset + 0, // slm_bank_size + 0, // reserved0 + 4740, // sr_magic_offset + 0, // fifo_offset; + 0, // fifo_size; + 0, // fifo_head; + 0, // fifo_tail; + 0, // fifo_version; + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // reserved1[10]; + SIP::SIP_FLAG_HEAPLESS, // sip_flags; + {0, grfNum, 256, 32}, // grf + {4096, 1, 256, 32}, // addr + {4128, 2, 32, 4}, // flag + {4156, 1, 32, 4}, // emask + {4160, 2, 128, 16}, // sr + {4192, 1, 128, 16}, // cr + {4256, 1, 96, 12}, // notification + {4288, 1, 128, 16}, // tdr + {4320, 10, 256, 32}, // acc + {4320, mmeNum, 256, 32}, // mme + {4672, 1, 32, 4}, // ce + {4704, 1, 128, 16}, // sp + {4768, 1, 128 * 8, 128}, // cmd + {4640, 1, 128, 16}, // tm + {0, 1, 32, 4}, // fc + {4736, 1, 32, 4}, // dbg + {4744, 1, 64, 8}, // ctx + {4752, 1, 64, 8}, // dbg_reg + {4760, 1, 64, 8}, // scalar + {4768, 1, 64, 8}, // msg + }; + NEO::StateSaveAreaHeader stateSaveAreaHeader3 = {}; + stateSaveAreaHeader3.versionHeader = versionHeader; + stateSaveAreaHeader3.regHeaderV3 = regHeaderV3; + char *begin = nullptr; unsigned long sizeOfHeader = 0u; if (version == 1) { @@ -134,6 +190,9 @@ std::vector createStateSaveAreaHeader(uint32_t version, uint16_t grfNum, u } else if (version == 2) { begin = reinterpret_cast(&stateSaveAreaHeader2); sizeOfHeader = offsetof(SIP::StateSaveAreaHeader, regHeader.dbg_reg) + sizeof(SIP::StateSaveAreaHeader::regHeader.dbg_reg); + } else if (version == 3) { + begin = reinterpret_cast(&stateSaveAreaHeader3); + sizeOfHeader = offsetof(NEO::StateSaveAreaHeader, regHeaderV3.msg) + sizeof(NEO::StateSaveAreaHeader::regHeaderV3.msg); } return std::vector(begin, begin + sizeOfHeader); diff --git a/shared/test/unit_test/built_ins/sip_tests.cpp b/shared/test/unit_test/built_ins/sip_tests.cpp index ea9ab71c10..fcb645eb0e 100644 --- a/shared/test/unit_test/built_ins/sip_tests.cpp +++ b/shared/test/unit_test/built_ins/sip_tests.cpp @@ -6,6 +6,7 @@ */ #include "shared/source/built_ins/built_ins.h" +#include "shared/source/debugger/debugger_l0.h" #include "shared/source/helpers/aligned_memory.h" #include "shared/source/helpers/gfx_core_helper.h" #include "shared/source/memory_manager/memory_allocation.h" @@ -399,6 +400,9 @@ TEST_F(StateSaveAreaSipTest, givenCorrectStateSaveAreaHeaderWhenGetStateSaveArea MockSipData::mockSipKernel->mockStateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(2); EXPECT_EQ(0x1800u * numSlices * 8 * 7 + alignUp(sizeof(SIP::StateSaveAreaHeader), MemoryConstants::pageSize), SipKernel::getSipKernel(*pDevice, nullptr).getStateSaveAreaSize(pDevice)); + + MockSipData::mockSipKernel->mockStateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(3); + EXPECT_EQ(0x1800u * numSlices * 8 * 7 + alignUp(sizeof(NEO::StateSaveAreaHeader), MemoryConstants::pageSize), SipKernel::getSipKernel(*pDevice, nullptr).getStateSaveAreaSize(pDevice)); } TEST(DebugBindlessSip, givenDebuggerAndUseBindlessDebugSipWhenGettingSipTypeThenDebugBindlessTypeIsReturned) {