From ee8af8534153533d6da3e03406300909075b4014 Mon Sep 17 00:00:00 2001 From: Mateusz Hoppe Date: Tue, 30 Aug 2022 18:06:04 +0000 Subject: [PATCH] L0Debug fixes for multi tile devices - notify module allocation for (sub)device used to create module, makeResident called within (sub)device contexts - access ISA with vmHandle specific to device index Related-To: NEO-5784 Signed-off-by: Mateusz Hoppe --- level_zero/core/source/module/module_imp.cpp | 2 +- .../debugger/test_module_with_debug.cpp | 54 +++++++++++++++++++ .../debug/linux/prelim/debug_session.cpp | 6 +-- .../source/debug/linux/prelim/debug_session.h | 2 +- .../linux/tile_debug_session_linux_tests.cpp | 13 ++++- shared/source/debugger/debugger_l0.cpp | 2 +- shared/source/debugger/debugger_l0.h | 2 +- shared/test/common/mocks/mock_l0_debugger.h | 6 +++ .../unit_test/debugger/test_l0_debugger.cpp | 2 +- 9 files changed, 80 insertions(+), 9 deletions(-) diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 20ec03261a..261f06d555 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -613,7 +613,7 @@ bool ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neoDevice) if (device->getL0Debugger()) { auto allocs = getModuleAllocations(); - device->getL0Debugger()->notifyModuleLoadAllocations(allocs); + device->getL0Debugger()->notifyModuleLoadAllocations(device->getNEODevice(), allocs); notifyModuleCreate(); } } 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 2957c22428..5ab67cdffe 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 @@ -17,6 +17,7 @@ #include "shared/test/common/test_macros/hw_test.h" #include "level_zero/core/source/module/module_imp.h" +#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" #include "level_zero/core/test/unit_tests/fixtures/module_fixture.h" #include "level_zero/core/test/unit_tests/mocks/mock_module.h" #include "level_zero/core/test/unit_tests/sources/debugger/l0_debugger_fixture.h" @@ -419,6 +420,59 @@ TEST_F(KernelInitializeTest, givenDebuggingEnabledWhenKernelsAreInitializedThenA EXPECT_NE(0, memcmp(isa, &kernelHeap, sizeof(kernelHeap))); }; +using ModuleWithDebuggerL0MultiTileTest = Test; + +HWTEST_F(ModuleWithDebuggerL0MultiTileTest, GivenSubDeviceWhenCreatingModuleThenModuleCreateIsNotifiedWithCorrectDevice) { + NEO::MockCompilerEnableGuard mock(true); + auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip); + neoDevice->getExecutionEnvironment()->setDebuggingEnabled(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->initDebuggerL0(neoDevice); + auto memoryOperationsHandler = new NEO::MockMemoryOperations(); + neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->memoryOperationsInterface.reset(memoryOperationsHandler); + + auto subDevice0 = neoDevice->getSubDevice(0)->getSpecializedDevice(); + + uint8_t binary[10]; + 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(subDevice0, moduleBuildLog, ModuleType::User); + moduleMock->translationUnit = std::make_unique(subDevice0); + + 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(); + + auto debugData = MockElfEncoder<>::createRelocateableDebugDataElf(); + kernelInfo->kernelDescriptor.external.debugData->vIsaSize = static_cast(debugData.size()); + kernelInfo->kernelDescriptor.external.debugData->vIsa = reinterpret_cast(debugData.data()); + kernelInfo->kernelDescriptor.external.debugData->genIsa = nullptr; + kernelInfo->kernelDescriptor.external.debugData->genIsaSize = 0; + + EXPECT_TRUE(moduleMock->initialize(&moduleDesc, subDevice0->getNEODevice())); + + auto debuggerL0Hw = static_cast *>(device->getL0Debugger()); + EXPECT_EQ(1u, debuggerL0Hw->notifyModuleCreateCount); + EXPECT_EQ(subDevice0->getNEODevice(), debuggerL0Hw->notifyModuleLoadAllocationsCapturedDevice); + + EXPECT_EQ(1, memoryOperationsHandler->makeResidentCalledCount); +} + HWTEST_F(ModuleWithDebuggerL0Test, GivenDebugDataWithRelocationsWhenInitializingModuleThenRegisterElfWithRelocatedElfAndModuleCreateNotified) { NEO::MockCompilerEnableGuard mock(true); auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions(); diff --git a/level_zero/tools/source/debug/linux/prelim/debug_session.cpp b/level_zero/tools/source/debug/linux/prelim/debug_session.cpp index e2193d6f22..ad576bef03 100644 --- a/level_zero/tools/source/debug/linux/prelim/debug_session.cpp +++ b/level_zero/tools/source/debug/linux/prelim/debug_session.cpp @@ -1285,9 +1285,9 @@ ze_result_t DebugSessionLinux::interruptImp(uint32_t deviceIndex) { return result == 0 ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_NOT_AVAILABLE; } -ze_result_t DebugSessionLinux::getISAVMHandle(const zet_debug_memory_space_desc_t *desc, size_t size, uint64_t &vmHandle) { +ze_result_t DebugSessionLinux::getISAVMHandle(uint32_t deviceIndex, const zet_debug_memory_space_desc_t *desc, size_t size, uint64_t &vmHandle) { auto accessVA = desc->address; - auto &isaMap = clientHandleToConnection[clientHandle]->isaMap[0]; + auto &isaMap = clientHandleToConnection[clientHandle]->isaMap[deviceIndex]; ze_result_t status = ZE_RESULT_ERROR_UNINITIALIZED; vmHandle = invalidHandle; @@ -1450,7 +1450,7 @@ bool DebugSessionLinux::tryAccessIsa(uint32_t deviceIndex, const zet_debug_memor { std::lock_guard memLock(asyncThreadMutex); - status = getISAVMHandle(desc, size, vmHandle); + status = getISAVMHandle(deviceIndex, desc, size, vmHandle); if (status == ZE_RESULT_SUCCESS) { isaAccess = true; } else if (status == ZE_RESULT_ERROR_INVALID_ARGUMENT) { diff --git a/level_zero/tools/source/debug/linux/prelim/debug_session.h b/level_zero/tools/source/debug/linux/prelim/debug_session.h index 568e34c5c7..dfabeed4dd 100644 --- a/level_zero/tools/source/debug/linux/prelim/debug_session.h +++ b/level_zero/tools/source/debug/linux/prelim/debug_session.h @@ -252,7 +252,7 @@ struct DebugSessionLinux : DebugSessionImp { ze_result_t readGpuMemory(uint64_t vmHandle, char *output, size_t size, uint64_t gpuVa) override; ze_result_t writeGpuMemory(uint64_t vmHandle, const char *input, size_t size, uint64_t gpuVa) override; - ze_result_t getISAVMHandle(const zet_debug_memory_space_desc_t *desc, size_t size, uint64_t &vmHandle); + ze_result_t getISAVMHandle(uint32_t deviceIndex, const zet_debug_memory_space_desc_t *desc, size_t size, uint64_t &vmHandle); ze_result_t getElfOffset(const zet_debug_memory_space_desc_t *desc, size_t size, const char *&elfData, uint64_t &offset); ze_result_t readElfSpace(const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer, const char *&elfData, const uint64_t offset); diff --git a/level_zero/tools/test/unit_tests/sources/debug/linux/tile_debug_session_linux_tests.cpp b/level_zero/tools/test/unit_tests/sources/debug/linux/tile_debug_session_linux_tests.cpp index 441799309f..3867d3a36b 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/linux/tile_debug_session_linux_tests.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/linux/tile_debug_session_linux_tests.cpp @@ -494,7 +494,7 @@ TEST_F(TileAttachTest, GivenTileAndVmBindEventsForIsaWhenReadingEventThenModuleL TEST_F(TileAttachTest, GivenIsaWhenReadingOrWritingMemoryThenMemoryIsReadAndWritten) { zet_debug_config_t config = {}; config.pid = 0x1234; - zet_debug_session_handle_t debugSession0 = nullptr; + zet_debug_session_handle_t debugSession0 = nullptr, debugSession1 = nullptr; zetDebugAttach(neoDevice->getSubDevice(0)->getSpecializedDevice()->toHandle(), &config, &debugSession0); @@ -516,6 +516,7 @@ TEST_F(TileAttachTest, GivenIsaWhenReadingOrWritingMemoryThenMemoryIsReadAndWrit ze_result_t result = zetDebugReadMemory(tileSessions[0]->toHandle(), thread, &desc, bufferSize, &output); EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(vm0, handler->vmOpen.handle); for (int i = 0; i < bufferSize; i++) { EXPECT_EQ(static_cast(0xaa), output[i]); @@ -527,6 +528,16 @@ TEST_F(TileAttachTest, GivenIsaWhenReadingOrWritingMemoryThenMemoryIsReadAndWrit result = zetDebugWriteMemory(tileSessions[0]->toHandle(), thread, &desc, bufferSize, &output); EXPECT_EQ(ZE_RESULT_SUCCESS, result); EXPECT_EQ(1u, handler->pwriteCalled); + EXPECT_EQ(vm0, handler->vmOpen.handle); + + zetDebugAttach(neoDevice->getSubDevice(0)->getSpecializedDevice()->toHandle(), &config, &debugSession1); + addIsaVmBindEvent(rootSession, vm1, true, true); + handler->preadCalled = 0; + + result = zetDebugReadMemory(tileSessions[1]->toHandle(), thread, &desc, bufferSize, &output); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(vm1, handler->vmOpen.handle); + EXPECT_EQ(1u, handler->preadCalled); } TEST_F(TileAttachTest, GivenElfAddressWhenReadMemoryCalledTheElfMemoryIsRead) { diff --git a/shared/source/debugger/debugger_l0.cpp b/shared/source/debugger/debugger_l0.cpp index 3f7aeed894..4ad761a6eb 100644 --- a/shared/source/debugger/debugger_l0.cpp +++ b/shared/source/debugger/debugger_l0.cpp @@ -136,7 +136,7 @@ void DebuggerL0::captureStateBaseAddress(NEO::LinearStream &cmdStream, SbaAddres } } -void DebuggerL0::notifyModuleLoadAllocations(const StackVec &allocs) { +void DebuggerL0::notifyModuleLoadAllocations(Device *device, const StackVec &allocs) { NEO::MemoryOperationsHandler *memoryOperationsIface = device->getRootDeviceEnvironment().memoryOperationsInterface.get(); if (memoryOperationsIface) { for (auto gfxAlloc : allocs) { diff --git a/shared/source/debugger/debugger_l0.h b/shared/source/debugger/debugger_l0.h index 8356eab39a..bf55237ff1 100644 --- a/shared/source/debugger/debugger_l0.h +++ b/shared/source/debugger/debugger_l0.h @@ -94,7 +94,7 @@ class DebuggerL0 : public NEO::Debugger, NEO::NonCopyableOrMovableClass { MOCKABLE_VIRTUAL void registerElf(NEO::DebugData *debugData, NEO::GraphicsAllocation *isaAllocation); MOCKABLE_VIRTUAL void notifyCommandQueueCreated(NEO::Device *device); MOCKABLE_VIRTUAL void notifyCommandQueueDestroyed(NEO::Device *device); - MOCKABLE_VIRTUAL void notifyModuleLoadAllocations(const StackVec &allocs); + MOCKABLE_VIRTUAL void notifyModuleLoadAllocations(Device *device, 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); diff --git a/shared/test/common/mocks/mock_l0_debugger.h b/shared/test/common/mocks/mock_l0_debugger.h index 67e02e2582..a16b14a420 100644 --- a/shared/test/common/mocks/mock_l0_debugger.h +++ b/shared/test/common/mocks/mock_l0_debugger.h @@ -106,6 +106,11 @@ class MockDebuggerL0Hw : public NEO::DebuggerL0Hw { NEO::DebuggerL0Hw::notifyModuleDestroy(moduleLoadAddress); } + void notifyModuleLoadAllocations(NEO::Device *device, const StackVec &allocs) override { + notifyModuleLoadAllocationsCapturedDevice = device; + NEO::DebuggerL0Hw::notifyModuleLoadAllocations(device, allocs); + } + uint32_t captureStateBaseAddressCount = 0; uint32_t programSbaTrackingCommandsCount = 0; uint32_t getSbaTrackingCommandsSizeCount = 0; @@ -120,6 +125,7 @@ class MockDebuggerL0Hw : public NEO::DebuggerL0Hw { uint32_t segmentCountWithAttachedModuleHandle = 0; uint32_t removedZebinModuleHandle = 0; uint32_t moduleHandleToReturn = std::numeric_limits::max(); + NEO::Device *notifyModuleLoadAllocationsCapturedDevice = nullptr; }; template <> diff --git a/shared/test/unit_test/debugger/test_l0_debugger.cpp b/shared/test/unit_test/debugger/test_l0_debugger.cpp index f926e65cdf..003804638f 100644 --- a/shared/test/unit_test/debugger/test_l0_debugger.cpp +++ b/shared/test/unit_test/debugger/test_l0_debugger.cpp @@ -218,7 +218,7 @@ HWTEST_F(L0DebuggerTest, givenDebuggerWithoutMemoryOperationsHandlerWhenNotifyin MemoryPool::System4KBPages, MemoryManager::maxOsContextCount); allocs.push_back(&alloc); - debugger->notifyModuleLoadAllocations(allocs); + debugger->notifyModuleLoadAllocations(pDevice, allocs); } HWTEST_F(L0DebuggerTest, givenDebuggerWhenCreatedThenModuleHeapDebugAreaIsCreated) {