diff --git a/level_zero/core/source/module/module_imp.cpp b/level_zero/core/source/module/module_imp.cpp index 1eb82e970c..933f851503 100644 --- a/level_zero/core/source/module/module_imp.cpp +++ b/level_zero/core/source/module/module_imp.cpp @@ -1249,7 +1249,7 @@ void ModuleImp::notifyModuleCreate() { StackVec segmentAllocs = getModuleAllocations(); - auto minAddressGpuAlloc = std::min_element(segmentAllocs.begin(), segmentAllocs.end(), [](const auto alloc1, const auto alloc2) { return alloc1->getGpuAddress() < alloc2->getGpuAddress(); }); + 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()); } else { for (auto &kernImmData : kernelImmDatas) { diff --git a/level_zero/tools/source/debug/windows/debug_session.cpp b/level_zero/tools/source/debug/windows/debug_session.cpp index f63c86ba19..c727417228 100644 --- a/level_zero/tools/source/debug/windows/debug_session.cpp +++ b/level_zero/tools/source/debug/windows/debug_session.cpp @@ -189,22 +189,31 @@ ze_result_t DebugSessionWindows::handleModuleCreateEvent(uint32_t seqNo, DBGUMD_ PRINT_DEBUGGER_INFO_LOG("DBGUMD_READ_EVENT_MODULE_CREATE_EVENT_PARAMS: hElfAddressPtr=0x%llX IsModuleCreate=%d LoadAddress=0x%llX ElfModuleSize=%d\n", moduleCreateParams.hElfAddressPtr, moduleCreateParams.IsModuleCreate, moduleCreateParams.LoadAddress, moduleCreateParams.ElfModulesize); - if (moduleCreateParams.IsModuleCreate) { - Module module = {0}; - module.cpuAddress = moduleCreateParams.hElfAddressPtr; - module.gpuAddress = moduleCreateParams.LoadAddress; - module.size = moduleCreateParams.ElfModulesize; - allModules.push_back(module); - - PRINT_DEBUGGER_INFO_LOG("DBGUMD_READ_EVENT_MODULE_CREATE_EVENT_PARAMS: Immediately acknowledge...\n"); - return acknowledgeEventImp(seqNo, DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION); - } else { - auto it = std::find_if(allModules.begin(), allModules.end(), [&](auto &m) { return m.gpuAddress == moduleCreateParams.LoadAddress; }); - if (it != allModules.end()) { - allModules.erase(it); + { + std::unique_lock lock(asyncThreadMutex); + if (moduleCreateParams.IsModuleCreate) { + Module module = {0}; + module.cpuAddress = moduleCreateParams.hElfAddressPtr; + module.gpuAddress = moduleCreateParams.LoadAddress; + module.size = moduleCreateParams.ElfModulesize; + allModules.push_back(module); + } else { + auto it = std::find_if(allModules.begin(), allModules.end(), [&](auto &m) { return m.gpuAddress == moduleCreateParams.LoadAddress; }); + if (it != allModules.end()) { + allModules.erase(it); + } } } + zet_debug_event_t debugEvent = {}; + debugEvent.type = moduleCreateParams.IsModuleCreate ? ZET_DEBUG_EVENT_TYPE_MODULE_LOAD : ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD; + debugEvent.flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK; + debugEvent.info.module.format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF; + debugEvent.info.module.load = moduleCreateParams.LoadAddress; + debugEvent.info.module.moduleBegin = moduleCreateParams.hElfAddressPtr; + debugEvent.info.module.moduleEnd = moduleCreateParams.hElfAddressPtr + moduleCreateParams.ElfModulesize; + pushApiEvent(debugEvent, seqNo, DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION); + return ZE_RESULT_SUCCESS; } @@ -299,11 +308,11 @@ ze_result_t DebugSessionWindows::handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CR } else if (createDebugDataParams.DebugDataType == static_cast(NEO::DebugDataType::CMD_QUEUE_CREATED)) { zet_debug_event_t debugEvent = {}; debugEvent.type = ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY; - pushApiEvent(debugEvent); + pushApiEvent(debugEvent, 0, 0); } else if (createDebugDataParams.DebugDataType == static_cast(NEO::DebugDataType::CMD_QUEUE_DESTROYED)) { zet_debug_event_t debugEvent = {}; debugEvent.type = ZET_DEBUG_EVENT_TYPE_PROCESS_EXIT; - pushApiEvent(debugEvent); + pushApiEvent(debugEvent, 0, 0); } return ZE_RESULT_SUCCESS; @@ -445,7 +454,17 @@ ze_result_t DebugSessionWindows::writeMemory(ze_device_thread_t thread, const ze } ze_result_t DebugSessionWindows::acknowledgeEvent(const zet_debug_event_t *event) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + std::unique_lock lock(asyncThreadMutex); + + ze_result_t ret = ZE_RESULT_ERROR_UNKNOWN; + auto it = std::find_if(eventsToAck.begin(), eventsToAck.end(), [&](auto &e) { return !memcmp(&e, event, sizeof(zet_debug_event_t)); }); + + if (it != eventsToAck.end()) { + ret = acknowledgeEventImp(it->second.first, it->second.second); + eventsToAck.erase(it); + } + + return ret; } ze_result_t DebugSessionWindows::resumeImp(const std::vector &threads, uint32_t deviceIndex) { diff --git a/level_zero/tools/source/debug/windows/debug_session.h b/level_zero/tools/source/debug/windows/debug_session.h index 62a54e822d..844f817665 100644 --- a/level_zero/tools/source/debug/windows/debug_session.h +++ b/level_zero/tools/source/debug/windows/debug_session.h @@ -37,9 +37,12 @@ struct DebugSessionWindows : DebugSessionImp { protected: ze_result_t resumeImp(const std::vector &threads, uint32_t deviceIndex) override; - void pushApiEvent(zet_debug_event_t &debugEvent) { + void DebugSessionWindows::pushApiEvent(zet_debug_event_t &debugEvent, uint32_t seqNo, uint32_t type) { std::unique_lock lock(asyncThreadMutex); apiEvents.push(debugEvent); + if (debugEvent.flags & ZET_DEBUG_EVENT_FLAG_NEED_ACK) { + eventsToAck.push_back({debugEvent, {seqNo, type}}); + } apiEventCondition.notify_all(); } @@ -98,6 +101,7 @@ struct DebugSessionWindows : DebugSessionImp { std::unordered_set allContexts; std::vector allElfs; std::vector allModules; + std::vector>> eventsToAck; }; } // 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 ef53e30ada..af193f9558 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 @@ -32,11 +32,13 @@ struct MockDebugSessionWindows : DebugSessionWindows { using DebugSessionWindows::debugAreaVA; using DebugSessionWindows::debugHandle; using DebugSessionWindows::ElfRange; + using DebugSessionWindows::eventsToAck; using DebugSessionWindows::getSbaBufferGpuVa; using DebugSessionWindows::initialize; using DebugSessionWindows::invalidHandle; using DebugSessionWindows::moduleDebugAreaCaptured; using DebugSessionWindows::processId; + using DebugSessionWindows::pushApiEvent; using DebugSessionWindows::readAllocationDebugData; using DebugSessionWindows::readAndHandleEvent; using DebugSessionWindows::readGpuMemory; @@ -608,7 +610,7 @@ TEST_F(DebugApiWindowsTest, givenContextCreateEventTypeWhenReadAndHandleEventCal EXPECT_EQ(0u, session->allContexts.size()); } -TEST_F(DebugApiWindowsTest, givenModuleCreateNotificationeEventTypeWhenReadAndHandleEventCalledThenModuleIsRegisteredAndEventIsAcknowledged) { +TEST_F(DebugApiWindowsTest, givenModuleCreateNotificationeEventTypeWhenReadAndHandleEventCalledThenModuleIsRegisteredAndEventIsQueuedForAcknowledge) { zet_debug_config_t config = {}; config.pid = 0x1234; @@ -630,12 +632,24 @@ TEST_F(DebugApiWindowsTest, givenModuleCreateNotificationeEventTypeWhenReadAndHa EXPECT_EQ(0x80000000u, session->allModules[0].gpuAddress); EXPECT_EQ(0x1000u, session->allModules[0].size); - EXPECT_EQ(1u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ACKNOWLEDGE_EVENT]); - EXPECT_EQ(123u, mockWddm->acknowledgeEventPassedParam.EventSeqNo); - EXPECT_EQ(DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION, mockWddm->acknowledgeEventPassedParam.ReadEventType); + EXPECT_EQ(1u, session->apiEvents.size()); + auto event = session->apiEvents.front(); + EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_MODULE_LOAD, event.type); + EXPECT_EQ(ZET_DEBUG_EVENT_FLAG_NEED_ACK, event.flags); + EXPECT_EQ(ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF, event.info.module.format); + EXPECT_EQ(0x80000000u, event.info.module.load); + EXPECT_EQ(0x12345678u, event.info.module.moduleBegin); + EXPECT_EQ(0x12345678u + 0x1000, event.info.module.moduleEnd); + + EXPECT_EQ(1u, session->eventsToAck.size()); + EXPECT_EQ(123, session->eventsToAck[0].second.first); + EXPECT_EQ(DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION, session->eventsToAck[0].second.second); + EXPECT_EQ(0u, memcmp(&event, &session->eventsToAck[0].first, sizeof(event))); + + EXPECT_EQ(0u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ACKNOWLEDGE_EVENT]); } -TEST_F(DebugApiWindowsTest, givenModuleDestroyNotificationeEventTypeWhenReadAndHandleEventCalledThenModuleIsUnregisteredAndEventIsNotAcknowledged) { +TEST_F(DebugApiWindowsTest, givenModuleDestroyNotificationeEventTypeWhenReadAndHandleEventCalledThenModuleIsUnregisteredAndEventIsQueuedForAcknowledge) { zet_debug_config_t config = {}; config.pid = 0x1234; @@ -646,6 +660,7 @@ TEST_F(DebugApiWindowsTest, givenModuleDestroyNotificationeEventTypeWhenReadAndH mockWddm->numEvents = 1; 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; @@ -654,6 +669,21 @@ TEST_F(DebugApiWindowsTest, givenModuleDestroyNotificationeEventTypeWhenReadAndH EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100)); EXPECT_EQ(0u, session->allModules.size()); + + EXPECT_EQ(1u, session->apiEvents.size()); + auto event = session->apiEvents.front(); + EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD, event.type); + EXPECT_EQ(ZET_DEBUG_EVENT_FLAG_NEED_ACK, event.flags); + EXPECT_EQ(ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF, event.info.module.format); + EXPECT_EQ(0x80000000u, event.info.module.load); + EXPECT_EQ(0x12345678u, event.info.module.moduleBegin); + EXPECT_EQ(0x12345678u + 0x1000, event.info.module.moduleEnd); + + EXPECT_EQ(1u, session->eventsToAck.size()); + EXPECT_EQ(123, session->eventsToAck[0].second.first); + EXPECT_EQ(DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION, session->eventsToAck[0].second.second); + EXPECT_EQ(0u, memcmp(&event, &session->eventsToAck[0].first, sizeof(event))); + EXPECT_EQ(0u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ACKNOWLEDGE_EVENT]); } @@ -668,6 +698,7 @@ TEST_F(DebugApiWindowsTest, givenModuleDestroyNotificationeEventTypeWhenReadAndH mockWddm->numEvents = 1; 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; @@ -678,6 +709,103 @@ TEST_F(DebugApiWindowsTest, givenModuleDestroyNotificationeEventTypeWhenReadAndH EXPECT_EQ(0u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ACKNOWLEDGE_EVENT]); } +TEST_F(DebugApiWindowsTest, givenNoEventsToAckWhenAcknowledgeEventIsCalledThenErrorUnknownReturned) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device); + session->wddm = mockWddm; + + zet_debug_event_t event = {}; + event.type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD; + event.flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK; + event.info.module.format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF; + event.info.module.load = 0x80000000u; + event.info.module.moduleBegin = 0x12345678u; + event.info.module.moduleEnd = 0x12345678u + 0x1000; + + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->acknowledgeEvent(&event)); + EXPECT_EQ(0u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ACKNOWLEDGE_EVENT]); +} + +TEST_F(DebugApiWindowsTest, givenEventsToAckWhenAcknowledgeEventIsCalledAndWrongEventIsPassedForAcknowledgeThenErrorUnknownReturned) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device); + session->wddm = mockWddm; + + zet_debug_event_t event = {}; + event.type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD; + event.flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK; + event.info.module.format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF; + event.info.module.load = 0x80000000u; + event.info.module.moduleBegin = 0x12345678u; + event.info.module.moduleEnd = 0x12345678u + 0x1000; + + session->eventsToAck.push_back({event, {123u, DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION}}); + + event.type = ZET_DEBUG_EVENT_TYPE_INVALID; + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->acknowledgeEvent(&event)); + EXPECT_EQ(0u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ACKNOWLEDGE_EVENT]); +} + +TEST_F(DebugApiWindowsTest, givenNoNeedAckFlagSetWhenPushDebugApiCalledThenEventIsNotEnqueuedForAcknowledge) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device); + session->wddm = mockWddm; + + zet_debug_event_t event = {}; + event.type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD; + event.flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK; + + session->pushApiEvent(event, 123, ZET_DEBUG_EVENT_TYPE_MODULE_LOAD); + EXPECT_EQ(1u, session->apiEvents.size()); + EXPECT_EQ(1u, session->eventsToAck.size()); +} + +TEST_F(DebugApiWindowsTest, givenNeedAckFlagSetWhenPushDebugApiCalledThenEventIsEnqueuedForAcknowledge) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device); + session->wddm = mockWddm; + + zet_debug_event_t event = {}; + event.type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD; + event.flags = 0; + + session->pushApiEvent(event, 123, ZET_DEBUG_EVENT_TYPE_MODULE_LOAD); + EXPECT_EQ(1u, session->apiEvents.size()); + EXPECT_EQ(0u, session->eventsToAck.size()); +} + +TEST_F(DebugApiWindowsTest, givenEventsToAckWhenAcknowledgeEventIsCalledThenSuccessReturned) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device); + session->wddm = mockWddm; + + zet_debug_event_t event = {}; + event.type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD; + event.flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK; + event.info.module.format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF; + event.info.module.load = 0x80000000u; + event.info.module.moduleBegin = 0x12345678u; + event.info.module.moduleEnd = 0x12345678u + 0x1000; + + session->eventsToAck.push_back({event, {123u, DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION}}); + + EXPECT_EQ(ZE_RESULT_SUCCESS, session->acknowledgeEvent(&event)); + EXPECT_EQ(0u, session->eventsToAck.size()); + EXPECT_EQ(1u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ACKNOWLEDGE_EVENT]); + EXPECT_EQ(123u, mockWddm->acknowledgeEventPassedParam.EventSeqNo); + EXPECT_EQ(DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION, mockWddm->acknowledgeEventPassedParam.ReadEventType); +} + TEST_F(DebugApiWindowsTest, givenAcknowledgeEventEscapeFailedWhenAcknolegeEventImpIsCalledThenResultUnknownIsReturned) { zet_debug_config_t config = {}; config.pid = 0x1234;