From 0248b53d860d0da53e2e43ca2fcc65d7dafd1bcc Mon Sep 17 00:00:00 2001 From: Jitendra Sharma Date: Tue, 17 Dec 2024 22:55:45 +0000 Subject: [PATCH] feature: Retrieve vmToTile map information for multi tile eudebug support Related-To: NEO-11104 Signed-off-by: Jitendra Sharma --- .../tools/source/debug/linux/debug_session.h | 56 ++++++++ .../source/debug/linux/prelim/debug_session.h | 56 -------- .../source/debug/linux/xe/debug_session.cpp | 78 +++++++--- .../linux/xe/test_debug_api_linux_xe.cpp | 136 ++++++++++++++---- .../linux/xe/eudebug/eudebug_wrappers.h | 11 ++ 5 files changed, 233 insertions(+), 104 deletions(-) diff --git a/level_zero/tools/source/debug/linux/debug_session.h b/level_zero/tools/source/debug/linux/debug_session.h index 3b6b1f8ca6..d751ed9cf1 100644 --- a/level_zero/tools/source/debug/linux/debug_session.h +++ b/level_zero/tools/source/debug/linux/debug_session.h @@ -197,6 +197,62 @@ struct DebugSessionLinux : DebugSessionImp { apiEventCondition.notify_all(); } + bool isTileWithinDeviceBitfield(uint32_t tileIndex) { + return connectedDevice->getNEODevice()->getDeviceBitfield().test(tileIndex); + } + + bool checkAllOtherTileIsaAllocationsPresent(uint32_t tileIndex, uint64_t isaVa) { + bool allInstancesPresent = true; + for (uint32_t i = 0; i < NEO::EngineLimits::maxHandleCount; i++) { + if (i != tileIndex && connectedDevice->getNEODevice()->getDeviceBitfield().test(i)) { + if (getClientConnection(clientHandle)->isaMap[i].find(isaVa) == getClientConnection(clientHandle)->isaMap[i].end()) { + allInstancesPresent = false; + break; + } + } + } + return allInstancesPresent; + } + + bool checkAllOtherTileIsaAllocationsRemoved(uint32_t tileIndex, uint64_t isaVa) { + bool allInstancesRemoved = true; + for (uint32_t i = 0; i < NEO::EngineLimits::maxHandleCount; i++) { + if (i != tileIndex && connectedDevice->getNEODevice()->getDeviceBitfield().test(i)) { + if (getClientConnection(clientHandle)->isaMap[i].find(isaVa) != getClientConnection(clientHandle)->isaMap[i].end()) { + allInstancesRemoved = false; + break; + } + } + } + return allInstancesRemoved; + } + + bool checkAllOtherTileModuleSegmentsPresent(uint32_t tileIndex, const Module &module) { + bool allInstancesPresent = true; + for (uint32_t i = 0; i < NEO::EngineLimits::maxHandleCount; i++) { + if (i != tileIndex && connectedDevice->getNEODevice()->getDeviceBitfield().test(i)) { + if (module.loadAddresses[i].size() != module.segmentCount) { + allInstancesPresent = false; + break; + } + } + } + return allInstancesPresent; + } + + bool checkAllOtherTileModuleSegmentsRemoved(uint32_t tileIndex, const Module &module) { + bool allInstancesRemoved = true; + for (uint32_t i = 0; i < NEO::EngineLimits::maxHandleCount; i++) { + if (i != tileIndex && connectedDevice->getNEODevice()->getDeviceBitfield().test(i)) { + if (module.loadAddresses[i].size() != 0) { + allInstancesRemoved = false; + break; + } + } + } + return allInstancesRemoved; + } + void updateStoppedThreadsAndCheckTriggerEvents(const AttentionEventFields &attention, uint32_t tileIndex, std::vector &threadsWithAttention) override; virtual void updateContextAndLrcHandlesForThreadsWithAttention(EuThread::ThreadId threadId, const AttentionEventFields &attention) = 0; virtual uint64_t getVmHandleFromClientAndlrcHandle(uint64_t clientHandle, uint64_t lrcHandle) = 0; 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 caa71eadcf..7eb34948fb 100644 --- a/level_zero/tools/source/debug/linux/prelim/debug_session.h +++ b/level_zero/tools/source/debug/linux/prelim/debug_session.h @@ -150,62 +150,6 @@ struct DebugSessionLinuxi915 : DebugSessionLinux { int threadControl(const std::vector &threads, uint32_t tile, ThreadControlCmd threadCmd, std::unique_ptr &bitmask, size_t &bitmaskSize) override; void printContextVms(); - bool isTileWithinDeviceBitfield(uint32_t tileIndex) { - return connectedDevice->getNEODevice()->getDeviceBitfield().test(tileIndex); - } - - bool checkAllOtherTileIsaAllocationsPresent(uint32_t tileIndex, uint64_t isaVa) { - bool allInstancesPresent = true; - for (uint32_t i = 0; i < NEO::EngineLimits::maxHandleCount; i++) { - if (i != tileIndex && connectedDevice->getNEODevice()->getDeviceBitfield().test(i)) { - if (clientHandleToConnection[clientHandle]->isaMap[i].find(isaVa) == clientHandleToConnection[clientHandle]->isaMap[i].end()) { - allInstancesPresent = false; - break; - } - } - } - return allInstancesPresent; - } - - bool checkAllOtherTileIsaAllocationsRemoved(uint32_t tileIndex, uint64_t isaVa) { - bool allInstancesRemoved = true; - for (uint32_t i = 0; i < NEO::EngineLimits::maxHandleCount; i++) { - if (i != tileIndex && connectedDevice->getNEODevice()->getDeviceBitfield().test(i)) { - if (clientHandleToConnection[clientHandle]->isaMap[i].find(isaVa) != clientHandleToConnection[clientHandle]->isaMap[i].end()) { - allInstancesRemoved = false; - break; - } - } - } - return allInstancesRemoved; - } - - bool checkAllOtherTileModuleSegmentsPresent(uint32_t tileIndex, const Module &module) { - bool allInstancesPresent = true; - for (uint32_t i = 0; i < NEO::EngineLimits::maxHandleCount; i++) { - if (i != tileIndex && connectedDevice->getNEODevice()->getDeviceBitfield().test(i)) { - if (module.loadAddresses[i].size() != module.segmentCount) { - allInstancesPresent = false; - break; - } - } - } - return allInstancesPresent; - } - - bool checkAllOtherTileModuleSegmentsRemoved(uint32_t tileIndex, const Module &module) { - bool allInstancesRemoved = true; - for (uint32_t i = 0; i < NEO::EngineLimits::maxHandleCount; i++) { - if (i != tileIndex && connectedDevice->getNEODevice()->getDeviceBitfield().test(i)) { - if (module.loadAddresses[i].size() != 0) { - allInstancesRemoved = false; - break; - } - } - } - return allInstancesRemoved; - } - std::vector> pendingVmBindEvents; uint32_t i915DebuggerVersion = 0; 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 27a63d35a0..a8a0bc86d7 100644 --- a/level_zero/tools/source/debug/linux/xe/debug_session.cpp +++ b/level_zero/tools/source/debug/linux/xe/debug_session.cpp @@ -344,8 +344,38 @@ void DebugSessionLinuxXe::handleEvent(NEO::EuDebugEvent *event) { vmBindOpData.vmBindOpMetadataVec.push_back(*vmBindOpMetadata); vmBindOpData.pendingNumExtensions--; handleVmBind(vmBindMap[vmBindSeqNo]); - } else if (type == euDebugInterface->getParamValue(NEO::EuDebugParam::eventTypePagefault) || - type == euDebugInterface->getParamValue(NEO::EuDebugParam::eventTypeExecQueuePlacements)) { + } else if (type == euDebugInterface->getParamValue(NEO::EuDebugParam::eventTypeExecQueuePlacements)) { + NEO::EuDebugEventExecQueuePlacements *execQueuePlacements = reinterpret_cast(event); + + PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE_PLACEMENTS client_handle = %" SCNx64 + " vm_handle = %" SCNx64 + " exec_queue_handle = %" SCNx64 + " lrc_handle = %" SCNx64 + " num_placements = %" SCNx32 + "\n ", + static_cast(execQueuePlacements->clientHandle), + static_cast(execQueuePlacements->vmHandle), + static_cast(execQueuePlacements->execQueueHandle), static_cast(execQueuePlacements->lrcHandle), + static_cast(execQueuePlacements->numPlacements)); + + UNRECOVERABLE_IF(execQueuePlacements->numPlacements == 0); + auto engine = reinterpret_cast(&(execQueuePlacements->instances[0])); + NEO::EngineClassInstance engineClassInstance = {engine->engineClass, engine->engineInstance}; + auto tileIndex = DrmHelper::getEngineTileIndex(connectedDevice, engineClassInstance); + + auto &vmToTile = clientHandleToConnection[execQueuePlacements->clientHandle]->vmToTile; + if (vmToTile.find(execQueuePlacements->vmHandle) != vmToTile.end()) { + if (vmToTile[execQueuePlacements->vmHandle] != tileIndex) { + PRINT_DEBUGGER_ERROR_LOG("vmToTile map: For vm_handle = %lu tileIndex = %u already present. Attempt to overwrite with tileIndex = %u\n", + static_cast(execQueuePlacements->vmHandle), vmToTile[execQueuePlacements->vmHandle], tileIndex); + DEBUG_BREAK_IF(true); + } + } else { + clientHandleToConnection[execQueuePlacements->clientHandle]->vmToTile[execQueuePlacements->vmHandle] = tileIndex; + PRINT_DEBUGGER_INFO_LOG("clientHandleToConnection[%" SCNx64 "]->vmToTile[%" SCNx64 "] = %u\n", + static_cast(execQueuePlacements->clientHandle), static_cast(execQueuePlacements->vmHandle), tileIndex); + } + } else if (type == euDebugInterface->getParamValue(NEO::EuDebugParam::eventTypePagefault)) { PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: UNHANDLED %u flags = %u len = %lu\n", type, event->flags, event->len); } else { additionalEvents(event); @@ -383,6 +413,10 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { uint64_t isaAddr = 0; bool triggerModuleLoadEvent = false; + uint32_t tileIndex = 0; + if (connection->vmToTile.find(vmBindData.vmBind.vmHandle) != connection->vmToTile.end()) { + tileIndex = connection->vmToTile[vmBindData.vmBind.vmHandle]; + } for (auto &vmBindOpData : vmBindData.vmBindOpMap) { auto &vmBindOp = vmBindOpData.second.vmBindOp; for (const auto &vmBindOpMetadata : vmBindOpData.second.vmBindOpMetadataVec) { @@ -398,8 +432,8 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { } if (metaDataEntry.metadata.type == euDebugInterface->getParamValue(NEO::EuDebugParam::metadataModuleArea)) { isaAddr = vmBindOp.addr; - if (connection->isaMap[0].find(vmBindOp.addr) == connection->isaMap[0].end()) { - auto &isaMap = connection->isaMap[0]; + if (connection->isaMap[tileIndex].find(vmBindOp.addr) == connection->isaMap[tileIndex].end()) { + auto &isaMap = connection->isaMap[tileIndex]; auto isa = std::make_unique(); isa->bindInfo = {vmBindOp.addr, vmBindOp.range}; isa->vmHandle = vmBindData.vmBind.vmHandle; @@ -424,8 +458,8 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { if (metaDataEntry.metadata.type == euDebugInterface->getParamValue(NEO::EuDebugParam::metadataElfBinary)) { isaAddr = vmBindOp.addr; - if (connection->isaMap[0].find(vmBindOp.addr) == connection->isaMap[0].end()) { - auto &isaMap = connection->isaMap[0]; + if (connection->isaMap[tileIndex].find(vmBindOp.addr) == connection->isaMap[tileIndex].end()) { + auto &isaMap = connection->isaMap[tileIndex]; auto &elfMap = connection->elfMap; auto isa = std::make_unique(); isa->bindInfo = {vmBindOp.addr, vmBindOp.range}; @@ -441,19 +475,19 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { isaMap[vmBindOp.addr]->moduleLoadEventAck = true; elfHandleInVmBind = vmBindOpMetadata.metadataHandle; } else { - auto &isa = connection->isaMap[0][vmBindOp.addr]; + auto &isa = connection->isaMap[tileIndex][vmBindOp.addr]; isa->validVMs.insert(vmBindData.vmBind.vmHandle); } } if (metaDataEntry.metadata.type == euDebugInterface->getParamValue(NEO::EuDebugParam::metadataProgramModule)) { auto &module = connection->metaDataToModule[vmBindOpMetadata.metadataHandle]; - module.segmentVmBindCounter[0]++; - DEBUG_BREAK_IF(module.loadAddresses[0].size() > module.segmentCount); + module.segmentVmBindCounter[tileIndex]++; + DEBUG_BREAK_IF(module.loadAddresses[tileIndex].size() > module.segmentCount); - bool canTriggerEvent = module.loadAddresses[0].size() == (module.segmentCount - 1); - module.loadAddresses[0].insert(vmBindOp.addr); + bool canTriggerEvent = module.loadAddresses[tileIndex].size() == (module.segmentCount - 1); + module.loadAddresses[tileIndex].insert(vmBindOp.addr); moduleHandle = vmBindOpMetadata.metadataHandle; - if (canTriggerEvent && module.loadAddresses[0].size() == module.segmentCount) { + if (canTriggerEvent && module.loadAddresses[tileIndex].size() == module.segmentCount) { triggerModuleLoadEvent = true; } } @@ -461,16 +495,16 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { } if (vmBindOp.base.flags & euDebugInterface->getParamValue(NEO::EuDebugParam::eventBitDestroy)) { - if (connection->isaMap[0].count(vmBindOp.addr)) { - auto &isa = connection->isaMap[0][vmBindOp.addr]; + if (connection->isaMap[tileIndex].count(vmBindOp.addr)) { + auto &isa = connection->isaMap[tileIndex][vmBindOp.addr]; if (isa->validVMs.count(vmBindData.vmBind.vmHandle)) { auto &module = connection->metaDataToModule[isa->moduleHandle]; - module.segmentVmBindCounter[0]--; - if (module.segmentVmBindCounter[0] == 0) { + module.segmentVmBindCounter[tileIndex]--; + if (module.segmentVmBindCounter[tileIndex] == 0) { zet_debug_event_t debugEvent = {}; auto &metaDataEntry = connection->metaDataMap[isa->moduleHandle]; auto gmmHelper = connectedDevice->getNEODevice()->getGmmHelper(); - auto loadAddress = gmmHelper->canonize(*std::min_element(module.loadAddresses[0].begin(), module.loadAddresses[0].end())); + auto loadAddress = gmmHelper->canonize(*std::min_element(module.loadAddresses[tileIndex].begin(), module.loadAddresses[tileIndex].end())); debugEvent.type = ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD; debugEvent.info.module.format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF; debugEvent.info.module.load = loadAddress; @@ -478,8 +512,8 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { debugEvent.info.module.moduleBegin = reinterpret_cast(elfMetadata.data.get()); debugEvent.info.module.moduleEnd = reinterpret_cast(elfMetadata.data.get()) + elfMetadata.metadata.len; pushApiEvent(debugEvent, metaDataEntry.metadata.metadataHandle); - module.loadAddresses[0].clear(); - module.moduleLoadEventAcked[0] = false; + module.loadAddresses[tileIndex].clear(); + module.moduleLoadEventAcked[tileIndex] = false; } isa->validVMs.erase(vmBindData.vmBind.vmHandle); } @@ -488,7 +522,7 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { } if (isaAddr && moduleHandle != invalidHandle) { - connection->isaMap[0][isaAddr]->moduleHandle = moduleHandle; + connection->isaMap[tileIndex][isaAddr]->moduleHandle = moduleHandle; } if (triggerModuleLoadEvent) { @@ -497,7 +531,7 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { auto &metaDataEntry = connection->metaDataMap[moduleHandle]; auto &module = connection->metaDataToModule[moduleHandle]; auto gmmHelper = connectedDevice->getNEODevice()->getGmmHelper(); - auto loadAddress = gmmHelper->canonize(*std::min_element(module.loadAddresses[0].begin(), module.loadAddresses[0].end())); + auto loadAddress = gmmHelper->canonize(*std::min_element(module.loadAddresses[tileIndex].begin(), module.loadAddresses[tileIndex].end())); PRINT_DEBUGGER_INFO_LOG("Zebin module loaded at: %p, with %u isa allocations", (void *)loadAddress, module.segmentCount); auto &elfMetadata = connection->metaDataMap[elfHandleInVmBind]; @@ -514,7 +548,7 @@ void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) { if (vmBindData.vmBind.flags & euDebugInterface->getParamValue(NEO::EuDebugParam::eventVmBindFlagUfence)) { if (vmBindData.vmBindUfence.base.flags & euDebugInterface->getParamValue(NEO::EuDebugParam::eventBitNeedAck)) { EventToAck ackEvent(vmBindData.vmBindUfence.base.seqno, vmBindData.vmBindUfence.base.type); - module.ackEvents[0].push_back(ackEvent); + module.ackEvents[tileIndex].push_back(ackEvent); shouldAckEvent = false; } } 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 d96fcbba78..1ca9cac4f7 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 @@ -1243,13 +1243,15 @@ TEST_P(DebugApiLinuxTestXeMetadataOpEventTest, GivenVmBindOpMetadataEventForMeta metadata.len = sizeof(metadata); connection->metaDataMap[10].metadata = metadata; + constexpr uint64_t vmHandle = 0x1234; + connection->vmToTile[vmHandle] = 0u; NEO::EuDebugEventVmBind vmBind{}; vmBind.base.type = static_cast(NEO::EuDebugParam::eventTypeVmBind); vmBind.base.flags = static_cast(NEO::shiftLeftBy(static_cast(NEO::EuDebugParam::eventBitStateChange))); vmBind.base.len = sizeof(NEO::EuDebugEventVmBind); vmBind.base.seqno = 1; vmBind.clientHandle = client1.clientHandle; - vmBind.vmHandle = 0x1234; + vmBind.vmHandle = vmHandle; vmBind.flags = static_cast(NEO::EuDebugParam::eventVmBindFlagUfence); vmBind.numBinds = 1; @@ -1289,18 +1291,18 @@ TEST_P(DebugApiLinuxTestXeMetadataOpEventTest, GivenVmBindOpMetadataEventForMeta session->handleEvent(reinterpret_cast(&vmBindUfence.base)); if (metadataType == static_cast(NEO::EuDebugParam::metadataSbaArea)) { - EXPECT_EQ(connection->vmToStateBaseAreaBindInfo[0x1234].gpuVa, vmBindOp.addr); - EXPECT_EQ(connection->vmToStateBaseAreaBindInfo[0x1234].size, vmBindOp.range); + EXPECT_EQ(connection->vmToStateBaseAreaBindInfo[vmHandle].gpuVa, vmBindOp.addr); + EXPECT_EQ(connection->vmToStateBaseAreaBindInfo[vmHandle].size, vmBindOp.range); } if (metadataType == static_cast(NEO::EuDebugParam::metadataModuleArea)) { - EXPECT_EQ(connection->vmToModuleDebugAreaBindInfo[0x1234].gpuVa, vmBindOp.addr); - EXPECT_EQ(connection->vmToModuleDebugAreaBindInfo[0x1234].size, vmBindOp.range); + EXPECT_EQ(connection->vmToModuleDebugAreaBindInfo[vmHandle].gpuVa, vmBindOp.addr); + EXPECT_EQ(connection->vmToModuleDebugAreaBindInfo[vmHandle].size, vmBindOp.range); } if (metadataType == static_cast(NEO::EuDebugParam::metadataSipArea)) { - EXPECT_EQ(connection->vmToContextStateSaveAreaBindInfo[0x1234].gpuVa, vmBindOp.addr); - EXPECT_EQ(connection->vmToContextStateSaveAreaBindInfo[0x1234].size, vmBindOp.range); + EXPECT_EQ(connection->vmToContextStateSaveAreaBindInfo[vmHandle].gpuVa, vmBindOp.addr); + EXPECT_EQ(connection->vmToContextStateSaveAreaBindInfo[vmHandle].size, vmBindOp.range); } if (metadataType == static_cast(NEO::EuDebugParam::metadataElfBinary)) { @@ -1361,13 +1363,15 @@ TEST_F(DebugApiLinuxTestXe, GivenVmBindOpMetadataCreateEventAndUfenceForProgramM connection->metaDataMap[11].data = std::move(ptr); connection->metaDataMap[11].metadata.len = 10000; + const uint64_t vmHandle = 0x1234; + connection->vmToTile[vmHandle] = 0u; NEO::EuDebugEventVmBind vmBind{}; vmBind.base.type = static_cast(NEO::EuDebugParam::eventTypeVmBind); vmBind.base.flags = static_cast(NEO::shiftLeftBy(static_cast(NEO::EuDebugParam::eventBitStateChange))); vmBind.base.len = sizeof(NEO::EuDebugEventVmBind); vmBind.base.seqno = 1; vmBind.clientHandle = client1.clientHandle; - vmBind.vmHandle = 0x1234; + vmBind.vmHandle = vmHandle; vmBind.flags = static_cast(NEO::EuDebugParam::eventVmBindFlagUfence); vmBind.numBinds = 1; @@ -1464,13 +1468,15 @@ TEST_F(DebugApiLinuxTestXe, GivenVmUnbindForLastIsaSegmentThenL0ModuleUnloadEven connection->metaDataMap[11].data = std::move(ptr); connection->metaDataMap[11].metadata.len = 10000; + const uint64_t vmHandle = 0x1234; + connection->vmToTile[vmHandle] = 0u; NEO::EuDebugEventVmBind vmBind{}; vmBind.base.type = static_cast(NEO::EuDebugParam::eventTypeVmBind); vmBind.base.flags = static_cast(NEO::shiftLeftBy(static_cast(NEO::EuDebugParam::eventBitStateChange))); vmBind.base.len = sizeof(NEO::EuDebugEventVmBind); vmBind.base.seqno = seqno++; vmBind.clientHandle = client1.clientHandle; - vmBind.vmHandle = 0x1234; + vmBind.vmHandle = vmHandle; vmBind.flags = static_cast(NEO::EuDebugParam::eventVmBindFlagUfence); vmBind.numBinds = 1; @@ -2362,23 +2368,25 @@ TEST_F(DebugApiLinuxTestXe, GivenSharedModuleDebugAreaWhenVmBindDebugAreaThenIsa auto handler = new MockIoctlHandlerXe; session->ioctlHandler.reset(handler); + constexpr uint64_t vmHandle1 = 1; + constexpr uint64_t vmHandle2 = 2; NEO::EuDebugEventVm vm1 = {}; NEO::EuDebugEventVm vm2 = {}; vm1.base.type = static_cast(NEO::EuDebugParam::eventTypeVm); vm1.base.flags = static_cast(NEO::shiftLeftBy(static_cast(NEO::EuDebugParam::eventBitCreate))); vm1.clientHandle = MockDebugSessionLinuxXe::mockClientHandle; - vm1.vmHandle = 1; + vm1.vmHandle = vmHandle1; vm2.base.type = static_cast(NEO::EuDebugParam::eventTypeVm); vm2.base.flags = static_cast(NEO::shiftLeftBy(static_cast(NEO::EuDebugParam::eventBitCreate))); vm2.clientHandle = MockDebugSessionLinuxXe::mockClientHandle; - vm2.vmHandle = 2; + vm2.vmHandle = vmHandle2; session->handleEvent(reinterpret_cast(&vm1)); session->handleEvent(reinterpret_cast(&vm2)); - uint64_t vmHandle = 1; session->clientHandle = MockDebugSessionLinuxXe::mockClientHandle; - session->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle]->vmToModuleDebugAreaBindInfo[vmHandle] = {debugAreaVA, 0x1000}; + session->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle]->vmToModuleDebugAreaBindInfo[vmHandle1] = {debugAreaVA, 0x1000}; + session->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle]->vmToTile[vmHandle1] = 0u; { NEO::EuDebugEventVmBind vmBindEvent = {}; @@ -2387,7 +2395,7 @@ TEST_F(DebugApiLinuxTestXe, GivenSharedModuleDebugAreaWhenVmBindDebugAreaThenIsa vmBindEvent.base.len = sizeof(NEO::EuDebugEventVmBind); vmBindEvent.base.seqno = 1; vmBindEvent.clientHandle = MockDebugSessionLinuxXe::mockClientHandle; - vmBindEvent.vmHandle = 1; + vmBindEvent.vmHandle = vmHandle1; vmBindEvent.flags = static_cast(NEO::EuDebugParam::eventVmBindFlagUfence); vmBindEvent.numBinds = 1; session->handleEvent(reinterpret_cast(&vmBindEvent.base)); @@ -2534,18 +2542,6 @@ TEST_F(DebugApiLinuxTestXe, GivenNotImplementedEventTypeWhenHandleEventThenDebug output = testing::internal::GetCapturedStdout(); expectedOutput = std::string("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: UNHANDLED ") + std::to_string(pagefaultEvent.type) + " flags = 3 len = 2\n"; EXPECT_NE(std::string::npos, output.find(expectedOutput.c_str())); - - NEO::EuDebugEvent execQueuePlacementsEvent{}; - execQueuePlacementsEvent.len = 4; - execQueuePlacementsEvent.type = static_cast(NEO::EuDebugParam::eventTypeExecQueuePlacements); - execQueuePlacementsEvent.flags = 5; - - ::testing::internal::CaptureStdout(); - session->handleEvent(&execQueuePlacementsEvent); - - output = testing::internal::GetCapturedStdout(); - expectedOutput = std::string("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: UNHANDLED ") + std::to_string(execQueuePlacementsEvent.type) + " flags = 5 len = 4\n"; - EXPECT_NE(std::string::npos, output.find(expectedOutput.c_str())) << output; } TEST(DebugSessionLinuxXeTest, GivenRootDebugSessionWhenCreateTileSessionCalledThenSessionIsNotCreated) { @@ -2566,5 +2562,93 @@ TEST(DebugSessionLinuxXeTest, GivenRootDebugSessionWhenCreateTileSessionCalledTh EXPECT_EQ(nullptr, tileSession); } +TEST_F(DebugApiLinuxTestXe, GivenExecQueuePlacementEventWhenHandlingThenVmToTileMapUpdates) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device, 10); + ASSERT_NE(nullptr, session); + + session->clientHandleToConnection.clear(); + + NEO::EuDebugEventClient client1; + client1.base.type = static_cast(NEO::EuDebugParam::eventTypeOpen); + client1.base.flags = static_cast(NEO::shiftLeftBy(static_cast(NEO::EuDebugParam::eventBitCreate))); + client1.clientHandle = 0x123456789; + session->handleEvent(reinterpret_cast(&client1)); + + constexpr uint64_t vmHandle = 10; + // Allocate memory for the structure including the flexible array member + constexpr auto size = sizeof(NEO::EuDebugEventExecQueuePlacements) + sizeof(drm_xe_engine_class_instance) * 1; + auto memory = alignedMalloc(size, sizeof(NEO::EuDebugEventExecQueuePlacements)); + auto execQueuePlacements = static_cast(memory); + memset(execQueuePlacements, 0, size); + execQueuePlacements->base.type = static_cast(NEO::EuDebugParam::eventTypeExecQueuePlacements); + execQueuePlacements->base.len = sizeof(NEO::EuDebugEventExecQueuePlacements); + execQueuePlacements->clientHandle = client1.clientHandle; + execQueuePlacements->vmHandle = vmHandle; + execQueuePlacements->execQueueHandle = 200; + execQueuePlacements->lrcHandle = 10; + execQueuePlacements->numPlacements = 1; + + auto engineClassInstance = reinterpret_cast(&(execQueuePlacements->instances[0])); + engineClassInstance[0].engine_class = 0; + engineClassInstance[0].engine_instance = 1; + engineClassInstance[0].gt_id = 1; + + session->handleEvent(&execQueuePlacements->base); + alignedFree(memory); + + EXPECT_NE(session->clientHandleToConnection[client1.clientHandle]->vmToTile.end(), + session->clientHandleToConnection[client1.clientHandle]->vmToTile.find(vmHandle)); + EXPECT_EQ(0u, session->clientHandleToConnection[client1.clientHandle]->vmToTile[vmHandle]); +} + +TEST_F(DebugApiLinuxTestXe, GivenMultipleExecQueuePlacementEventForSameVmHandleWithDifferentTileIndexWhenHandlingThenErrorReported) { + DebugManagerStateRestore restorer; + NEO::debugManager.flags.DebuggerLogBitmask.set(NEO::DebugVariables::DEBUGGER_LOG_BITMASK::LOG_ERROR); + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device, 10); + ASSERT_NE(nullptr, session); + + session->clientHandleToConnection.clear(); + + NEO::EuDebugEventClient client1; + client1.base.type = static_cast(NEO::EuDebugParam::eventTypeOpen); + client1.base.flags = static_cast(NEO::shiftLeftBy(static_cast(NEO::EuDebugParam::eventBitCreate))); + client1.clientHandle = 0x123456789; + session->handleEvent(reinterpret_cast(&client1)); + + constexpr uint64_t vmHandle = 10; + session->clientHandleToConnection[client1.clientHandle]->vmToTile[vmHandle] = 1; + // Allocate memory for the structure including the flexible array member + constexpr auto size = sizeof(NEO::EuDebugEventExecQueuePlacements) + sizeof(drm_xe_engine_class_instance) * 1; + auto memory = alignedMalloc(size, sizeof(NEO::EuDebugEventExecQueuePlacements)); + auto execQueuePlacements = static_cast(memory); + memset(execQueuePlacements, 0, size); + execQueuePlacements->base.type = static_cast(NEO::EuDebugParam::eventTypeExecQueuePlacements); + execQueuePlacements->base.len = sizeof(NEO::EuDebugEventExecQueuePlacements); + execQueuePlacements->clientHandle = client1.clientHandle; + execQueuePlacements->vmHandle = vmHandle; + execQueuePlacements->execQueueHandle = 200; + execQueuePlacements->lrcHandle = 10; + execQueuePlacements->numPlacements = 1; + + auto engineClassInstance = reinterpret_cast(&(execQueuePlacements->instances[0])); + engineClassInstance[0].engine_class = 0; + engineClassInstance[0].engine_instance = 1; + engineClassInstance[0].gt_id = 1; + + ::testing::internal::CaptureStderr(); + session->handleEvent(&execQueuePlacements->base); + alignedFree(memory); + + auto infoMessage = ::testing::internal::GetCapturedStderr(); + EXPECT_EQ(1u, session->clientHandleToConnection[client1.clientHandle]->vmToTile[vmHandle]); + EXPECT_TRUE(hasSubstr(infoMessage, std::string("tileIndex = 1 already present. Attempt to overwrite with tileIndex = 0"))); +} + } // namespace ult } // namespace L0 diff --git a/shared/source/os_interface/linux/xe/eudebug/eudebug_wrappers.h b/shared/source/os_interface/linux/xe/eudebug/eudebug_wrappers.h index c1b866bc78..82a79dbb6a 100644 --- a/shared/source/os_interface/linux/xe/eudebug/eudebug_wrappers.h +++ b/shared/source/os_interface/linux/xe/eudebug/eudebug_wrappers.h @@ -54,6 +54,17 @@ struct EuDebugEventExecQueue { uint64_t lrcHandle[]; }; +struct EuDebugEventExecQueuePlacements { + struct EuDebugEvent base; + uint64_t clientHandle; + uint64_t vmHandle; + uint64_t execQueueHandle; + uint64_t lrcHandle; + uint64_t numPlacements; + uint64_t pad; + uint64_t instances[]; +}; + struct EuDebugEventMetadata { struct EuDebugEvent base; uint64_t clientHandle;