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 ea077a3ec0..47b75c62fd 100644 --- a/level_zero/tools/source/debug/linux/xe/debug_session.cpp +++ b/level_zero/tools/source/debug/linux/xe/debug_session.cpp @@ -126,6 +126,9 @@ void DebugSessionLinuxXe::readInternalEventsAsync() { if (result == ZE_RESULT_SUCCESS) { std::lock_guard lock(internalEventThreadMutex); + if (event->type == DRM_XE_EUDEBUG_EVENT_EU_ATTENTION) { + newestAttSeqNo.store(event->seqno); + } auto memory = std::make_unique(maxEventSize / sizeof(uint64_t)); memcpy(memory.get(), event, maxEventSize); @@ -253,7 +256,11 @@ void DebugSessionLinuxXe::handleEvent(drm_xe_eudebug_event *event) { PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_EU_ATTENTION client_handle = %llu flags = %llu bitmask_size = %lu exec_queue_handle = %llu lrc_handle = %llu\n", (uint64_t)attention->client_handle, (uint64_t)attention->flags, (uint32_t)attention->bitmask_size, uint64_t(attention->exec_queue_handle), uint64_t(attention->lrc_handle)); - handleAttentionEvent(attention); + if (attention->base.seqno < newestAttSeqNo.load()) { + PRINT_DEBUGGER_INFO_LOG("Dropping stale ATT event seqno=%llu\n", (uint64_t)attention->base.seqno); + } else { + handleAttentionEvent(attention); + } } break; case DRM_XE_EUDEBUG_EVENT_VM_BIND: { diff --git a/level_zero/tools/source/debug/linux/xe/debug_session.h b/level_zero/tools/source/debug/linux/xe/debug_session.h index 034c602fc6..872e804f8b 100644 --- a/level_zero/tools/source/debug/linux/xe/debug_session.h +++ b/level_zero/tools/source/debug/linux/xe/debug_session.h @@ -67,7 +67,7 @@ struct DebugSessionLinuxXe : DebugSessionLinux { int threadControlInterruptAll(drm_xe_eudebug_eu_control &euControl); int threadControlResume(const std::vector &threads, drm_xe_eudebug_eu_control &euControl); int threadControlStopped(drm_xe_eudebug_eu_control &euControl, std::unique_ptr &bitmaskOut, size_t &bitmaskSizeOut); - void handleAttentionEvent(drm_xe_eudebug_event_eu_attention *attention); + MOCKABLE_VIRTUAL void handleAttentionEvent(drm_xe_eudebug_event_eu_attention *attention); void handleMetadataEvent(drm_xe_eudebug_event_metadata *pMetaData); bool handleMetadataOpEvent(drm_xe_eudebug_event_vm_bind_op_metadata *vmBindOpMetadata); void updateContextAndLrcHandlesForThreadsWithAttention(EuThread::ThreadId threadId, AttentionEventFields &attention) override; @@ -158,6 +158,7 @@ struct DebugSessionLinuxXe : DebugSessionLinux { ze_result_t readEventImp(drm_xe_eudebug_event *drmDebugEvent); int ioctl(unsigned long request, void *arg); std::atomic processEntryEventGenerated = false; + std::atomic newestAttSeqNo = 0; }; } // namespace L0 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 1ea615e33e..d0126b4a38 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 @@ -171,6 +171,7 @@ struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe { using L0::DebugSessionLinuxXe::internalEventThread; using L0::DebugSessionLinuxXe::invalidClientHandle; using L0::DebugSessionLinuxXe::ioctlHandler; + using L0::DebugSessionLinuxXe::newestAttSeqNo; using L0::DebugSessionLinuxXe::newlyStoppedThreads; using L0::DebugSessionLinuxXe::pendingInterrupts; using L0::DebugSessionLinuxXe::readEventImp; @@ -203,6 +204,11 @@ struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe { return DebugSessionLinuxXe::initialize(); } + void handleAttentionEvent(drm_xe_eudebug_event_eu_attention *attention) override { + handleAttentionEventCalled++; + return DebugSessionLinuxXe::handleAttentionEvent(attention); + } + int threadControl(const std::vector &threads, uint32_t tile, ThreadControlCmd threadCmd, std::unique_ptr &bitmask, size_t &bitmaskSize) override { numThreadsPassedToThreadControl = threads.size(); return L0::DebugSessionLinuxXe::threadControl(threads, tile, threadCmd, bitmask, bitmaskSize); @@ -266,6 +272,7 @@ struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe { std::unordered_map stoppedThreads; uint32_t countToAddThreadToNewlyStoppedFromRaisedAttentionForTileSession = 0; int64_t returnTimeDiff = -1; + uint32_t handleAttentionEventCalled = 0; }; struct MockAsyncThreadDebugSessionLinuxXe : public MockDebugSessionLinuxXe { 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 cc88c95a77..ff95a3aaf4 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 @@ -2099,6 +2099,32 @@ TEST_F(DebugApiLinuxTestXe, GivenSentInterruptWhenHandlingAttEventThenAttBitsAre EXPECT_EQ(0u, sessionMock->readSystemRoutineIdentCallCount); } +TEST_F(DebugApiLinuxTestXe, GivenStaleAttentionEventThenEventNotHandled) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto sessionMock = std::make_unique(config, device, 10); + ASSERT_NE(nullptr, sessionMock); + sessionMock->clientHandle = MockDebugSessionLinuxXe::mockClientHandle; + sessionMock->newestAttSeqNo.store(10); + drm_xe_eudebug_event_eu_attention attention = {}; + attention.base.type = DRM_XE_EUDEBUG_EVENT_EU_ATTENTION; + attention.base.flags = DRM_XE_EUDEBUG_EVENT_STATE_CHANGE; + attention.base.len = sizeof(drm_xe_eudebug_event_eu_attention); + attention.base.seqno = 2; + attention.client_handle = MockDebugSessionLinuxXe::mockClientHandle; + attention.lrc_handle = 0; + attention.flags = 0; + attention.exec_queue_handle = 0; + attention.bitmask_size = 0; + uint8_t data[sizeof(drm_xe_eudebug_event_eu_attention) + 128]; + memcpy(data, &attention, sizeof(drm_xe_eudebug_event_eu_attention)); + + sessionMock->handleEvent(reinterpret_cast(data)); + + EXPECT_EQ(sessionMock->handleAttentionEventCalled, 0u); +} + TEST_F(DebugApiLinuxTestXe, GivenInterruptedThreadsWhenAttentionEventReceivedThenEventsTriggeredAfterExpectedAttentionEventCount) { zet_debug_config_t config = {}; config.pid = 0x1234;