diff --git a/level_zero/tools/source/debug/linux/debug_session.cpp b/level_zero/tools/source/debug/linux/debug_session.cpp index 0ccadea188..ee19a4dc32 100644 --- a/level_zero/tools/source/debug/linux/debug_session.cpp +++ b/level_zero/tools/source/debug/linux/debug_session.cpp @@ -1117,6 +1117,10 @@ void DebugSessionLinux::handlePageFaultEvent(PageFaultEvent &pfEvent) { } } for (auto &threadId : stoppedThreads) { + AttentionEventFields attention = {}; + attention.lrcHandle = pfEvent.lrcHandle; + attention.contextHandle = pfEvent.execQueueHandle; + updateContextAndLrcHandlesForThreadsWithAttention(threadId, attention); if (tileSessionsEnabled) { addThreadToNewlyStoppedFromRaisedAttentionForTileSession(threadId, pfEvent.vmHandle, stateSaveAreaMemory.data(), pfEvent.tileIndex); } else { diff --git a/level_zero/tools/source/debug/linux/debug_session.h b/level_zero/tools/source/debug/linux/debug_session.h index 4267b318ce..8bf25403d4 100644 --- a/level_zero/tools/source/debug/linux/debug_session.h +++ b/level_zero/tools/source/debug/linux/debug_session.h @@ -302,6 +302,8 @@ struct DebugSessionLinux : DebugSessionImp { uint64_t vmHandle; uint32_t tileIndex; uint64_t pageFaultAddress; + uint64_t execQueueHandle; + uint64_t lrcHandle; uint32_t bitmaskSize; uint8_t *bitmask; }; 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 9a0b3713d3..e8fc7bae74 100644 --- a/level_zero/tools/source/debug/linux/prelim/debug_session.cpp +++ b/level_zero/tools/source/debug/linux/prelim/debug_session.cpp @@ -445,7 +445,7 @@ void DebugSessionLinuxi915::handleEvent(prelim_drm_i915_debug_event *event) { if (vmHandle == invalidHandle) { return; } - PageFaultEvent pfEvent = {vmHandle, tileIndex, pf->page_fault_address, pf->bitmask_size, pf->bitmask}; + PageFaultEvent pfEvent = {vmHandle, tileIndex, pf->page_fault_address, 0u, 0u, pf->bitmask_size, pf->bitmask}; handlePageFaultEvent(pfEvent); } break; diff --git a/level_zero/tools/source/debug/linux/xe/debug_session.cpp b/level_zero/tools/source/debug/linux/xe/debug_session.cpp index 9e637cccd5..fa074a5245 100644 --- a/level_zero/tools/source/debug/linux/xe/debug_session.cpp +++ b/level_zero/tools/source/debug/linux/xe/debug_session.cpp @@ -394,7 +394,7 @@ void DebugSessionLinuxXe::handleEvent(NEO::EuDebugEvent *event) { if (vmHandle == invalidHandle) { return; } - PageFaultEvent pfEvent = {vmHandle, tileIndex, pf->pagefaultAddress, pf->bitmaskSize, pf->bitmask}; + PageFaultEvent pfEvent = {vmHandle, tileIndex, pf->pagefaultAddress, pf->execQueueHandle, pf->lrcHandle, pf->bitmaskSize, pf->bitmask}; handlePageFaultEvent(pfEvent); } else { additionalEvents(event); diff --git a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h b/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h index cad52d735d..5438dd35e5 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h +++ b/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h @@ -324,6 +324,16 @@ struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe { void handlePageFaultEvent(PageFaultEvent &pfEvent) override { handlePageFaultEventCalled++; + if (callHandlePageFaultBase) { + return DebugSessionLinux::handlePageFaultEvent(pfEvent); + } + } + + ze_result_t readGpuMemory(uint64_t vmHandle, char *output, size_t size, uint64_t gpuVa) override { + if (callReadGpuMemoryBase) { + return DebugSessionLinux::readGpuMemory(vmHandle, output, size, gpuVa); + } + return ZE_RESULT_SUCCESS; } uint64_t getContextStateSaveAreaGpuVa(uint64_t memoryHandle) override { @@ -349,6 +359,8 @@ struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe { uint32_t countToAddThreadToNewlyStoppedFromRaisedAttentionForTileSession = 0; int64_t returnTimeDiff = -1; uint32_t handleAttentionEventCalled = 0; + bool callHandlePageFaultBase = false; + bool callReadGpuMemoryBase = true; uint32_t handlePageFaultEventCalled = 0; uint32_t reachSteadyStateCount = 0; }; diff --git a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/test_debug_api_linux_xe.cpp b/level_zero/tools/test/unit_tests/sources/debug/linux/xe/test_debug_api_linux_xe.cpp index fc8e68ad11..80edcd4856 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/test_debug_api_linux_xe.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/linux/xe/test_debug_api_linux_xe.cpp @@ -3341,5 +3341,78 @@ TEST_F(DebugApiLinuxTestXe, GivenPageFaultEventThenPageFaultHandledCalled) { EXPECT_EQ(sessionMock->handlePageFaultEventCalled, 1u); } +TEST_F(DebugApiLinuxTestXe, givenHandlePageFaultEventCalledThenLrcAndExecQueueUpdatedForAllThreads) { + + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto sessionMock = std::make_unique(config, device, 10); + ASSERT_NE(nullptr, sessionMock); + sessionMock->clientHandle = MockDebugSessionLinuxXe::mockClientHandle; + + uint64_t execQueueHandle = 2; + uint64_t vmHandle = 7; + uint64_t lrcHandle = 8; + + sessionMock->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle]->lrcHandleToVmHandle[lrcHandle] = vmHandle; + + uint8_t data[sizeof(NEO::EuDebugEventPageFault) + (256 * 3)]; + ze_device_thread_t thread{0, 0, 0, 0}; + + sessionMock->stoppedThreads[EuThread::ThreadId(0, thread).packed] = 1; + sessionMock->pendingInterrupts.push_back(std::pair(thread, false)); + + sessionMock->interruptSent = true; + sessionMock->euControlInterruptSeqno = 1; + + std::vector threads; + auto &l0GfxCoreHelper = neoDevice->getRootDeviceEnvironment().getHelper(); + auto &hwInfo = neoDevice->getHardwareInfo(); + std::unique_ptr bitmaskBefore, bitmaskAfter, bitmaskResolved; + size_t bitmaskSize; + l0GfxCoreHelper.getAttentionBitmaskForSingleThreads(threads, hwInfo, bitmaskBefore, bitmaskSize); + l0GfxCoreHelper.getAttentionBitmaskForSingleThreads(threads, hwInfo, bitmaskAfter, bitmaskSize); + + threads.push_back({0, 0, 0, 0, 0}); + threads.push_back({0, 0, 0, 0, 2}); + threads.push_back({0, 0, 0, 0, 3}); + threads.push_back({0, 0, 0, 0, 4}); + threads.push_back({0, 0, 0, 0, 6}); + for (auto thread : threads) { + sessionMock->stoppedThreads[thread.packed] = 1; + } + l0GfxCoreHelper.getAttentionBitmaskForSingleThreads(threads, hwInfo, bitmaskResolved, bitmaskSize); + + NEO::EuDebugEventPageFault pf = {}; + pf.base.type = static_cast(NEO::EuDebugParam::eventTypePagefault); + pf.base.flags = static_cast(NEO::EuDebugParam::eventBitStateChange); + pf.base.len = sizeof(data); + pf.base.seqno = 2; + pf.clientHandle = MockDebugSessionLinuxXe::mockClientHandle; + pf.lrcHandle = lrcHandle; + pf.flags = 0; + pf.execQueueHandle = execQueueHandle; + pf.bitmaskSize = static_cast(bitmaskSize * 3); + memcpy(data, &pf, sizeof(NEO::EuDebugEventPageFault)); + memcpy(ptrOffset(data, offsetof(EuDebugEventPageFault, bitmask)), bitmaskBefore.get(), bitmaskSize); + memcpy(ptrOffset(data, offsetof(EuDebugEventPageFault, bitmask) + bitmaskSize), bitmaskAfter.get(), bitmaskSize); + memcpy(ptrOffset(data, offsetof(EuDebugEventPageFault, bitmask) + (2 * bitmaskSize)), bitmaskResolved.get(), bitmaskSize); + + sessionMock->callHandlePageFaultBase = true; + sessionMock->callReadGpuMemoryBase = false; + sessionMock->handleEvent(reinterpret_cast(data)); + + EXPECT_EQ(sessionMock->handlePageFaultEventCalled, 1u); + EXPECT_EQ(threads.size(), sessionMock->newlyStoppedThreads.size()); + for (auto thread : threads) { + EXPECT_TRUE(sessionMock->allThreads[thread]->getPageFault()); + uint64_t foundLrcHandle, foundExecQueueHandle; + sessionMock->allThreads[thread]->getLrcHandle(foundLrcHandle); + sessionMock->allThreads[thread]->getContextHandle(foundExecQueueHandle); + EXPECT_EQ(lrcHandle, foundLrcHandle); + EXPECT_EQ(execQueueHandle, foundExecQueueHandle); + } +} + } // namespace ult } // namespace L0