diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 933f851503..8d7b0b5b69 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -569,6 +569,17 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) kernelImmDatas.push_back(std::move(kernelImmData)); } + auto refBin = ArrayRef::fromAny(translationUnit->unpackedDeviceBinary.get(), translationUnit->unpackedDeviceBinarySize); + if (NEO::isDeviceBinaryFormat(refBin)) { + isZebinBinary = true; + } + + StackVec moduleAllocs = getModuleAllocations(); + if (!moduleAllocs.empty()) { + auto minGpuAddressAlloc = std::min_element(moduleAllocs.begin(), moduleAllocs.end(), [](const auto &alloc1, const auto &alloc2) { return alloc1->getGpuAddress() < alloc2->getGpuAddress(); }); + moduleLoadAddress = (*minGpuAddressAlloc)->getGpuAddress(); + } + registerElfInDebuggerL0(); this->maxGroupSize = static_cast(this->translationUnit->device->getNEODevice()->getDeviceInfo().maxWorkGroupSize); @@ -608,7 +619,7 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) } void ModuleImp::createDebugZebin() { - auto refBin = ArrayRef(reinterpret_cast(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize); + auto refBin = ArrayRef::fromAny(translationUnit->unpackedDeviceBinary.get(), translationUnit->unpackedDeviceBinarySize); auto segments = getZebinSegments(); auto debugZebin = NEO::Debug::createDebugZebin(refBin, segments); @@ -619,8 +630,7 @@ void ModuleImp::createDebugZebin() { } void ModuleImp::passDebugData() { - auto refBin = ArrayRef(reinterpret_cast(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize); - if (NEO::isDeviceBinaryFormat(refBin)) { + if (isZebinBinary) { createDebugZebin(); if (device->getSourceLevelDebugger()) { NEO::DebugData debugData; // pass debug zebin in vIsa field @@ -757,8 +767,8 @@ ze_result_t ModuleImp::getDebugInfo(size_t *pDebugDataSize, uint8_t *pDebugData) if (translationUnit == nullptr) { return ZE_RESULT_ERROR_UNINITIALIZED; } - auto refBin = ArrayRef(reinterpret_cast(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize); - if (nullptr == translationUnit->debugData.get() && NEO::isDeviceBinaryFormat(refBin)) { + + if (nullptr == translationUnit->debugData.get() && isZebinBinary) { createDebugZebin(); } if (pDebugData != nullptr) { @@ -1173,14 +1183,19 @@ bool ModuleImp::populateHostGlobalSymbolsMap(std::unordered_mapgetL0Debugger() && tempHandle != 0) { tempDevice->getL0Debugger()->removeZebinModule(tempHandle); } + return ZE_RESULT_SUCCESS; } + void ModuleImp::registerElfInDebuggerL0() { auto debuggerL0 = device->getL0Debugger(); @@ -1188,8 +1203,7 @@ void ModuleImp::registerElfInDebuggerL0() { return; } - auto refBin = ArrayRef(reinterpret_cast(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize); - if (NEO::isDeviceBinaryFormat(refBin)) { + if (isZebinBinary) { size_t debugDataSize = 0; getDebugInfo(&debugDataSize, nullptr); @@ -1238,19 +1252,14 @@ void ModuleImp::notifyModuleCreate() { return; } - auto refBin = ArrayRef(reinterpret_cast(translationUnit->unpackedDeviceBinary.get()), translationUnit->unpackedDeviceBinarySize); - if (NEO::isDeviceBinaryFormat(refBin)) { + if (isZebinBinary) { size_t debugDataSize = 0; getDebugInfo(&debugDataSize, nullptr); NEO::DebugData debugData; // pass debug zebin in vIsa field debugData.vIsa = reinterpret_cast(translationUnit->debugData.get()); debugData.vIsaSize = static_cast(translationUnit->debugDataSize); - - StackVec segmentAllocs = getModuleAllocations(); - - auto minAddressGpuAlloc = std::min_element(segmentAllocs.begin(), segmentAllocs.end(), [](const auto &alloc1, const auto &alloc2) { return alloc1->getGpuAddress() < alloc2->getGpuAddress(); }); - debuggerL0->notifyModuleCreate(const_cast(debugData.vIsa), debugData.vIsaSize, (*minAddressGpuAlloc)->getGpuAddress()); + debuggerL0->notifyModuleCreate(const_cast(debugData.vIsa), debugData.vIsaSize, moduleLoadAddress); } else { for (auto &kernImmData : kernelImmDatas) { if (kernImmData->getKernelInfo()->kernelDescriptor.external.debugData.get()) { @@ -1271,6 +1280,24 @@ void ModuleImp::notifyModuleCreate() { } } +void ModuleImp::notifyModuleDestroy() { + auto debuggerL0 = device->getL0Debugger(); + + if (!debuggerL0) { + return; + } + + if (isZebinBinary) { + debuggerL0->notifyModuleDestroy(moduleLoadAddress); + } else { + for (auto &kernImmData : kernelImmDatas) { + if (kernImmData->getKernelInfo()->kernelDescriptor.external.debugData.get()) { + debuggerL0->notifyModuleDestroy(kernImmData->getIsaGraphicsAllocation()->getGpuAddress()); + } + } + } +} + StackVec ModuleImp::getModuleAllocations() { StackVec allocs; for (auto &kernImmData : kernelImmDatas) { diff --git a/level_zero/core/source/module/module_imp.h b/level_zero/core/source/module/module_imp.h index 2957777b3a..a0711f3149 100644 --- a/level_zero/core/source/module/module_imp.h +++ b/level_zero/core/source/module/module_imp.h @@ -142,6 +142,7 @@ struct ModuleImp : public Module { void createDebugZebin(); void registerElfInDebuggerL0(); void notifyModuleCreate(); + void notifyModuleDestroy(); bool populateHostGlobalSymbolsMap(std::unordered_map &devToHostNameMapping); StackVec getModuleAllocations(); @@ -164,11 +165,13 @@ struct ModuleImp : public Module { bool debugEnabled = false; bool isFullyLinked = false; bool allocatePrivateMemoryPerDispatch = true; + bool isZebinBinary = false; ModuleType type; NEO::Linker::UnresolvedExternals unresolvedExternalsInfo{}; std::set importedSymbolAllocations{}; uint32_t debugModuleHandle = 0; uint32_t profileFlags = 0; + uint64_t moduleLoadAddress = std::numeric_limits::max(); NEO::Linker::PatchableSegments isaSegmentsForPatching; std::vector> patchedIsaTempStorage; diff --git a/level_zero/core/test/unit_tests/fixtures/module_fixture.h b/level_zero/core/test/unit_tests/fixtures/module_fixture.h index 662c594c98..908ee67f7e 100644 --- a/level_zero/core/test/unit_tests/fixtures/module_fixture.h +++ b/level_zero/core/test/unit_tests/fixtures/module_fixture.h @@ -340,10 +340,13 @@ struct ModuleWithZebinFixture : public DeviceFixture { struct MockModuleWithZebin : public L0::ModuleImp { using ModuleImp::getDebugInfo; using ModuleImp::getZebinSegments; + using ModuleImp::isZebinBinary; using ModuleImp::kernelImmDatas; using ModuleImp::passDebugData; using ModuleImp::translationUnit; - MockModuleWithZebin(L0::Device *device) : ModuleImp(device, nullptr, ModuleType::User) {} + MockModuleWithZebin(L0::Device *device) : ModuleImp(device, nullptr, ModuleType::User) { + isZebinBinary = true; + } void addSegments() { kernelImmDatas.push_back(std::make_unique(device)); diff --git a/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp b/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp index d140973450..96dfea19f9 100644 --- a/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp +++ b/level_zero/core/test/unit_tests/sources/debugger/test_module_with_debug.cpp @@ -652,6 +652,89 @@ HWTEST_F(ModuleWithZebinAndL0DebuggerTest, GivenZebinWhenModuleIsInitializedAndD moduleMock.release(); EXPECT_EQ(6u, getMockDebuggerL0Hw()->removedZebinModuleHandle); + EXPECT_EQ(1u, getMockDebuggerL0Hw()->notifyModuleDestroyCount); +} + +HWTEST_F(ModuleWithDebuggerL0Test, GivenNonZebinBinaryWhenDestroyModuleThenModuleDestroyNotified) { + NEO::MockCompilerEnableGuard mock(true); + auto cip = std::make_unique(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface = std::move(cip); + + uint8_t binary[10] = {0}; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + ModuleBuildLog *moduleBuildLog = nullptr; + + std::unique_ptr moduleMock = std::make_unique(device, moduleBuildLog, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + + uint32_t kernelHeap = 0; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + Mock<::L0::Kernel> kernelMock; + kernelMock.module = moduleMock.get(); + kernelMock.immutableData.kernelInfo = kernelInfo; + kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0; + + moduleMock->kernelImmData = &kernelMock.immutableData; + moduleMock->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + + kernelInfo->kernelDescriptor.external.debugData = std::make_unique(); + + std::vector data; + data.resize(4); + NEO::Elf::ElfEncoder<> elfEncoder; + elfEncoder.getElfFileHeader().type = NEO::Elf::SHT_PROGBITS; + elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix, data); + auto elfBinary = elfEncoder.encode(); + + kernelInfo->kernelDescriptor.external.debugData->vIsaSize = static_cast(elfBinary.size()); + kernelInfo->kernelDescriptor.external.debugData->vIsa = reinterpret_cast(elfBinary.data()); + kernelInfo->kernelDescriptor.external.debugData->genIsa = nullptr; + kernelInfo->kernelDescriptor.external.debugData->genIsaSize = 0; + + EXPECT_TRUE(moduleMock->initialize(&moduleDesc, neoDevice)); + moduleMock->destroy(); + moduleMock.release(); + EXPECT_EQ(1u, getMockDebuggerL0Hw()->notifyModuleDestroyCount); +} + +HWTEST_F(ModuleWithDebuggerL0Test, GivenNoDebugDataWhenDestroyingModuleThenDoNotNotifyModuleDestroy) { + NEO::MockCompilerEnableGuard mock(true); + auto cip = std::make_unique(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface = std::move(cip); + + uint8_t binary[10] = {0}; + ze_module_desc_t moduleDesc = {}; + moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV; + moduleDesc.pInputModule = binary; + moduleDesc.inputSize = 10; + ModuleBuildLog *moduleBuildLog = nullptr; + + std::unique_ptr moduleMock = std::make_unique(device, moduleBuildLog, ModuleType::User); + moduleMock->translationUnit = std::make_unique(device); + + uint32_t kernelHeap = 0; + auto kernelInfo = new KernelInfo(); + kernelInfo->heapInfo.KernelHeapSize = 1; + kernelInfo->heapInfo.pKernelHeap = &kernelHeap; + + Mock<::L0::Kernel> kernelMock; + kernelMock.module = moduleMock.get(); + kernelMock.immutableData.kernelInfo = kernelInfo; + kernelInfo->kernelDescriptor.payloadMappings.implicitArgs.systemThreadSurfaceAddress.bindful = 0; + + moduleMock->kernelImmData = &kernelMock.immutableData; + moduleMock->translationUnit->programInfo.kernelInfos.push_back(kernelInfo); + + EXPECT_TRUE(moduleMock->initialize(&moduleDesc, neoDevice)); + moduleMock->destroy(); + moduleMock.release(); + EXPECT_EQ(0u, getMockDebuggerL0Hw()->notifyModuleDestroyCount); } HWTEST_F(ModuleWithZebinAndL0DebuggerTest, GivenModuleDebugHandleZeroWhenInitializingAndDestoryingModuleThenHandleIsNotPassedToDebugger) { diff --git a/level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp b/level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp index f1b3dc1d64..8219672226 100644 --- a/level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp +++ b/level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp @@ -16,6 +16,7 @@ #include "shared/test/common/mocks/windows/mock_wddm_eudebug.h" #include "shared/test/common/os_interface/windows/mock_wddm_memory_manager.h" #include "shared/test/common/test_macros/hw_test.h" +#include "shared/test/unit_test/helpers/gtest_helpers.h" #include "level_zero/core/source/device/device.h" #include "level_zero/core/test/unit_tests/mocks/mock_cmdqueue.h" @@ -108,7 +109,7 @@ HWTEST_F(L0DebuggerWindowsTest, givenDebuggingEnabledAndCommandQueuesAreCreatedA TEST_F(L0DebuggerWindowsTest, givenAllocateGraphicsMemoryWhenAllocationRegistrationIsRequiredThenAllocationIsRegistered) { auto memoryManager = executionEnvironment->memoryManager.get(); - EXPECT_GE(wddm->registerAllocationTypeCalled, 3u); // At least 1xSBA + 1xMODULE_DEBUG + 1xSTATE_SAVE_AREA during DebuggerL0 init + EXPECT_LE(3u, wddm->registerAllocationTypeCalled); // At least 1xSBA + 1xMODULE_DEBUG + 1xSTATE_SAVE_AREA during DebuggerL0 init uint32_t registerAllocationTypeCalled = wddm->registerAllocationTypeCalled; for (auto allocationType : {AllocationType::DEBUG_CONTEXT_SAVE_AREA, AllocationType::DEBUG_SBA_TRACKING_BUFFER, @@ -129,7 +130,7 @@ TEST_F(L0DebuggerWindowsTest, givenAllocateGraphicsMemoryWhenAllocationRegistrat TEST_F(L0DebuggerWindowsTest, givenAllocateGraphicsMemoryWhenAllocationRegistrationIsNotRequiredThenAllocationIsNotRegistered) { auto memoryManager = executionEnvironment->memoryManager.get(); - EXPECT_GE(wddm->registerAllocationTypeCalled, 3u); // At least 1xSBA + 1xMODULE_DEBUG + 1xSTATE_SAVE_AREA during DebuggerL0 init + EXPECT_LE(3u, wddm->registerAllocationTypeCalled); // At least 1xSBA + 1xMODULE_DEBUG + 1xSTATE_SAVE_AREA during DebuggerL0 init uint32_t registerAllocationTypeCalled = wddm->registerAllocationTypeCalled; auto wddmAlloc = static_cast(memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{0u, MemoryConstants::pageSize, AllocationType::BUFFER})); EXPECT_EQ(registerAllocationTypeCalled, wddm->registerAllocationTypeCalled); @@ -140,34 +141,58 @@ TEST_F(L0DebuggerWindowsTest, givenDebuggerL0NotifyModuleCreateCalledAndCreateDe wddm->createDebugDataPassedParam.ntStatus = STATUS_UNSUCCESSFUL; auto debugger = static_cast(neoDevice->getDebugger()); debugger->notifyModuleCreate((void *)0x12345678, 0x1000, 0x80000000); - EXPECT_EQ(wddm->createDebugDataCalled, 1u); - EXPECT_EQ(wddm->createDebugDataPassedParam.param.hElfAddressPtr, 0xDEADDEADu); - EXPECT_EQ(wddm->moduleCreateNotifyCalled, 0); + EXPECT_EQ(1u, wddm->createDebugDataCalled); + EXPECT_EQ(0xDEADDEADu, wddm->createDebugDataPassedParam.param.hElfAddressPtr); + EXPECT_EQ(0, wddm->moduleCreateNotifyCalled); } TEST_F(L0DebuggerWindowsTest, givenDebuggerL0NotifyModuleCreateCalledAndModuleCreateNotifyEscapeIsFailedThenModuleIsNotRegistered) { wddm->moduleCreateNotificationPassedParam.ntStatus = STATUS_UNSUCCESSFUL; auto debugger = static_cast(neoDevice->getDebugger()); debugger->notifyModuleCreate((void *)0x12345678, 0x1000, 0x80000000); - EXPECT_EQ(wddm->createDebugDataCalled, 1u); - EXPECT_EQ(wddm->createDebugDataPassedParam.param.hElfAddressPtr, 0x12345678u); - EXPECT_EQ(wddm->moduleCreateNotifyCalled, 1u); - EXPECT_EQ(wddm->moduleCreateNotificationPassedParam.param.hElfAddressPtr, 0xDEADDEADu); + EXPECT_EQ(1u, wddm->createDebugDataCalled); + EXPECT_EQ(0x12345678u, wddm->createDebugDataPassedParam.param.hElfAddressPtr); + EXPECT_EQ(1u, wddm->moduleCreateNotifyCalled); + EXPECT_EQ(0xDEADDEADu, wddm->moduleCreateNotificationPassedParam.param.hElfAddressPtr); } TEST_F(L0DebuggerWindowsTest, givenDebuggerL0NotifyModuleCreateCalledThenCreateDebugDataAndModuleCreateNotifyEscapesAreCalled) { auto debugger = static_cast(neoDevice->getDebugger()); debugger->notifyModuleCreate((void *)0x12345678, 0x1000, 0x80000000); - EXPECT_EQ(wddm->createDebugDataCalled, 1u); - EXPECT_EQ(wddm->createDebugDataPassedParam.param.DebugDataType, ELF_BINARY); - EXPECT_EQ(wddm->createDebugDataPassedParam.param.DataSize, 0x1000); - EXPECT_EQ(wddm->createDebugDataPassedParam.param.hElfAddressPtr, 0x12345678u); + EXPECT_EQ(1u, wddm->createDebugDataCalled); + EXPECT_EQ(ELF_BINARY, wddm->createDebugDataPassedParam.param.DebugDataType); + EXPECT_EQ(0x1000, wddm->createDebugDataPassedParam.param.DataSize); + EXPECT_EQ(0x12345678u, wddm->createDebugDataPassedParam.param.hElfAddressPtr); - EXPECT_EQ(wddm->moduleCreateNotifyCalled, 1u); + EXPECT_EQ(1u, wddm->moduleCreateNotifyCalled); EXPECT_TRUE(wddm->moduleCreateNotificationPassedParam.param.IsCreate); - EXPECT_EQ(wddm->moduleCreateNotificationPassedParam.param.Modulesize, 0x1000); - EXPECT_EQ(wddm->moduleCreateNotificationPassedParam.param.hElfAddressPtr, 0x12345678u); - EXPECT_EQ(wddm->moduleCreateNotificationPassedParam.param.LoadAddress, 0x80000000); + EXPECT_EQ(0x1000, wddm->moduleCreateNotificationPassedParam.param.Modulesize); + EXPECT_EQ(0x12345678u, wddm->moduleCreateNotificationPassedParam.param.hElfAddressPtr); + EXPECT_EQ(0x80000000, wddm->moduleCreateNotificationPassedParam.param.LoadAddress); +} + +TEST_F(L0DebuggerWindowsTest, givenDebuggerL0NotifyModuleDestroyCalledThenModuleDestroyNotifyEscapeIsCalled) { + auto debugger = static_cast(neoDevice->getDebugger()); + debugger->notifyModuleDestroy(0x80000000); + + EXPECT_EQ(1u, wddm->moduleCreateNotifyCalled); + EXPECT_FALSE(wddm->moduleCreateNotificationPassedParam.param.IsCreate); + EXPECT_EQ(0x1000, wddm->moduleCreateNotificationPassedParam.param.Modulesize); + EXPECT_EQ(std::numeric_limits::max(), wddm->moduleCreateNotificationPassedParam.param.hElfAddressPtr); + EXPECT_EQ(0x80000000, wddm->moduleCreateNotificationPassedParam.param.LoadAddress); +} + +TEST_F(L0DebuggerWindowsTest, givenDebuggerL0NotifyModuleDestroyCalledAndModuleDestroyNotifyEscapeIsFailedThenErrorMessageIsPrinted) { + DebugManagerStateRestore restorer; + NEO::DebugManager.flags.DebuggerLogBitmask.set(255); + + testing::internal::CaptureStderr(); + wddm->moduleCreateNotificationPassedParam.ntStatus = STATUS_UNSUCCESSFUL; + auto debugger = static_cast(neoDevice->getDebugger()); + debugger->notifyModuleDestroy(0x80000000); + + EXPECT_EQ(1u, wddm->moduleCreateNotifyCalled); + EXPECT_TRUE(hasSubstr(testing::internal::GetCapturedStderr(), std::string("KM_ESCAPE_EUDBG_UMD_MODULE_DESTROY_NOTIFY: Failed - Status:"))); } } // namespace ult diff --git a/level_zero/tools/source/debug/windows/debug_session.cpp b/level_zero/tools/source/debug/windows/debug_session.cpp index d2edbba0b7..e823d924ac 100644 --- a/level_zero/tools/source/debug/windows/debug_session.cpp +++ b/level_zero/tools/source/debug/windows/debug_session.cpp @@ -201,6 +201,8 @@ ze_result_t DebugSessionWindows::handleModuleCreateEvent(uint32_t seqNo, DBGUMD_ } else { auto it = std::find_if(allModules.begin(), allModules.end(), [&](auto &m) { return m.gpuAddress == moduleCreateParams.LoadAddress; }); if (it != allModules.end()) { + moduleCreateParams.hElfAddressPtr = it->cpuAddress; + moduleCreateParams.ElfModulesize = it->size; allModules.erase(it); } } 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 af193f9558..36f0f44b88 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 @@ -662,8 +662,8 @@ TEST_F(DebugApiWindowsTest, givenModuleDestroyNotificationeEventTypeWhenReadAndH mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION; mockWddm->eventQueue[0].seqNo = 123u; mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ModuleCreateEventParams.IsModuleCreate = false; - mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ModuleCreateEventParams.hElfAddressPtr = 0x12345678; - mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ModuleCreateEventParams.ElfModulesize = 0x1000; + mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ModuleCreateEventParams.hElfAddressPtr = 0xDEADDEAD; + mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ModuleCreateEventParams.ElfModulesize = 1; mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ModuleCreateEventParams.LoadAddress = 0x80000000; EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100)); diff --git a/shared/source/debugger/debugger_l0.h b/shared/source/debugger/debugger_l0.h index 3e0b659358..8356eab39a 100644 --- a/shared/source/debugger/debugger_l0.h +++ b/shared/source/debugger/debugger_l0.h @@ -96,6 +96,7 @@ class DebuggerL0 : public NEO::Debugger, NEO::NonCopyableOrMovableClass { MOCKABLE_VIRTUAL void notifyCommandQueueDestroyed(NEO::Device *device); MOCKABLE_VIRTUAL void notifyModuleLoadAllocations(const StackVec &allocs); MOCKABLE_VIRTUAL void notifyModuleCreate(void *module, uint32_t moduleSize, uint64_t moduleLoadAddress); + MOCKABLE_VIRTUAL void notifyModuleDestroy(uint64_t moduleLoadAddress); MOCKABLE_VIRTUAL void registerAllocationType(GraphicsAllocation *allocation); void initSbaTrackingMode(); diff --git a/shared/source/debugger/linux/debugger_l0_linux.cpp b/shared/source/debugger/linux/debugger_l0_linux.cpp index d357fe9a75..cc9c89bd7a 100644 --- a/shared/source/debugger/linux/debugger_l0_linux.cpp +++ b/shared/source/debugger/linux/debugger_l0_linux.cpp @@ -64,6 +64,8 @@ bool DebuggerL0::removeZebinModule(uint32_t moduleHandle) { return true; } +void DebuggerL0::notifyModuleDestroy(uint64_t moduleLoadAddress) {} + void DebuggerL0::notifyCommandQueueCreated(NEO::Device *device) { if (this->device->getRootDeviceEnvironment().osInterface.get() != nullptr) { std::unique_lock commandQueueCountLock(debuggerL0Mutex); diff --git a/shared/source/debugger/windows/debugger_l0_windows.cpp b/shared/source/debugger/windows/debugger_l0_windows.cpp index eaa0a62d25..a2bf16abb6 100644 --- a/shared/source/debugger/windows/debugger_l0_windows.cpp +++ b/shared/source/debugger/windows/debugger_l0_windows.cpp @@ -74,8 +74,7 @@ void DebuggerL0::registerAllocationType(GraphicsAllocation *allocation) { allocationDebugDataInfo.DataSize = sizeof(registrationData); allocationDebugDataInfo.DataPointer = reinterpret_cast(®istrationData); - KM_ESCAPE_INFO escapeInfo; - memset(&escapeInfo, 0, sizeof(escapeInfo)); + KM_ESCAPE_INFO escapeInfo = {0}; escapeInfo.Header.EscapeCode = GFX_ESCAPE_KMD; escapeInfo.Header.Size = sizeof(escapeInfo) - sizeof(escapeInfo.Header); escapeInfo.EscapeOperation = KM_ESCAPE_EUDBG_UMD_REGISTER_ALLOCATION_TYPE; @@ -111,8 +110,7 @@ void DebuggerL0::notifyModuleCreate(void *module, uint32_t moduleSize, uint64_t } // Register ELF - KM_ESCAPE_INFO escapeInfo; - memset(&escapeInfo, 0, sizeof(escapeInfo)); + KM_ESCAPE_INFO escapeInfo = {0}; escapeInfo.Header.EscapeCode = GFX_ESCAPE_KMD; escapeInfo.Header.Size = sizeof(escapeInfo) - sizeof(escapeInfo.Header); escapeInfo.EscapeOperation = KM_ESCAPE_EUDBG_UMD_CREATE_DEBUG_DATA; @@ -142,7 +140,7 @@ void DebuggerL0::notifyModuleCreate(void *module, uint32_t moduleSize, uint64_t PRINT_DEBUGGER_INFO_LOG("KM_ESCAPE_EUDBG_UMD_CREATE_DEBUG_DATA - Success\n"); // Fire MODULE_CREATE event - memset(&escapeInfo, 0, sizeof(escapeInfo)); + escapeInfo = {0}; escapeInfo.Header.EscapeCode = GFX_ESCAPE_KMD; escapeInfo.Header.Size = sizeof(escapeInfo) - sizeof(escapeInfo.Header); escapeInfo.EscapeOperation = KM_ESCAPE_EUDBG_UMD_MODULE_CREATE_NOTIFY; @@ -151,8 +149,6 @@ void DebuggerL0::notifyModuleCreate(void *module, uint32_t moduleSize, uint64_t escapeInfo.KmEuDbgUmdCreateModuleNotification.hElfAddressPtr = reinterpret_cast(module); escapeInfo.KmEuDbgUmdCreateModuleNotification.LoadAddress = moduleLoadAddress; - PRINT_DEBUGGER_INFO_LOG("Sending KM_ESCAPE_EUDBG_UMD_MODULE_CREATE_NOTIFY...\n"); - status = wddm->escape(escapeCommand); if (STATUS_SUCCESS != status) { @@ -163,6 +159,42 @@ void DebuggerL0::notifyModuleCreate(void *module, uint32_t moduleSize, uint64_t PRINT_DEBUGGER_INFO_LOG("KM_ESCAPE_EUDBG_UMD_MODULE_CREATE_NOTIFY - Success\n"); } +void DebuggerL0::notifyModuleDestroy(uint64_t moduleLoadAddress) { + if (device->getRootDeviceEnvironment().osInterface == nullptr) { + return; + } + + KM_ESCAPE_INFO escapeInfo = {0}; + escapeInfo.Header.EscapeCode = GFX_ESCAPE_KMD; + escapeInfo.Header.Size = sizeof(escapeInfo) - sizeof(escapeInfo.Header); + escapeInfo.EscapeOperation = KM_ESCAPE_EUDBG_UMD_MODULE_CREATE_NOTIFY; + escapeInfo.KmEuDbgUmdCreateModuleNotification.IsCreate = false; + escapeInfo.KmEuDbgUmdCreateModuleNotification.Modulesize = 0x1000; + escapeInfo.KmEuDbgUmdCreateModuleNotification.hElfAddressPtr = uint64_t(-1); + escapeInfo.KmEuDbgUmdCreateModuleNotification.LoadAddress = moduleLoadAddress; + + auto wddm = device->getRootDeviceEnvironment().osInterface->getDriverModel()->as(); + + D3DKMT_ESCAPE escapeCommand = {0}; + escapeCommand.Flags.HardwareAccess = 0; + escapeCommand.Flags.Reserved = 0; + escapeCommand.hAdapter = wddm->getAdapter(); + escapeCommand.hContext = (D3DKMT_HANDLE)0; + escapeCommand.hDevice = wddm->getDeviceHandle(); + escapeCommand.pPrivateDriverData = &escapeInfo; + escapeCommand.PrivateDriverDataSize = sizeof(escapeInfo); + escapeCommand.Type = D3DKMT_ESCAPE_DRIVERPRIVATE; + + auto status = wddm->escape(escapeCommand); + + if (STATUS_SUCCESS != status) { + PRINT_DEBUGGER_ERROR_LOG("KM_ESCAPE_EUDBG_UMD_MODULE_DESTROY_NOTIFY: Failed - Status: 0x%llX\n", status); + return; + } + + PRINT_DEBUGGER_INFO_LOG("KM_ESCAPE_EUDBG_UMD_MODULE_DESTROY_NOTIFY - Success\n"); +} + bool DebuggerL0::removeZebinModule(uint32_t moduleHandle) { return false; } diff --git a/shared/test/common/mocks/mock_l0_debugger.h b/shared/test/common/mocks/mock_l0_debugger.h index 4408cba867..67e02e2582 100644 --- a/shared/test/common/mocks/mock_l0_debugger.h +++ b/shared/test/common/mocks/mock_l0_debugger.h @@ -101,6 +101,11 @@ class MockDebuggerL0Hw : public NEO::DebuggerL0Hw { NEO::DebuggerL0Hw::notifyModuleCreate(module, moduleSize, moduleLoadAddress); } + void notifyModuleDestroy(uint64_t moduleLoadAddress) override { + notifyModuleDestroyCount++; + NEO::DebuggerL0Hw::notifyModuleDestroy(moduleLoadAddress); + } + uint32_t captureStateBaseAddressCount = 0; uint32_t programSbaTrackingCommandsCount = 0; uint32_t getSbaTrackingCommandsSizeCount = 0; @@ -109,6 +114,7 @@ class MockDebuggerL0Hw : public NEO::DebuggerL0Hw { uint32_t commandQueueDestroyedCount = 0; uint32_t registerAllocationTypeCount = 0; uint32_t notifyModuleCreateCount = 0; + uint32_t notifyModuleDestroyCount = 0; const char *lastReceivedElf = nullptr; uint32_t segmentCountWithAttachedModuleHandle = 0;