fix(zebin): fix module load/unload events while debugging

- do not trigger incorrect / spurious events from internal modules
for debugger
- do not register Elf for internal modules

Related-To: NEO-7605

Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
Mateusz Hoppe
2023-01-04 09:55:29 +01:00
committed by Compute-Runtime-Automation
parent af81c79076
commit ee499d689b
5 changed files with 280 additions and 123 deletions

View File

@@ -616,6 +616,7 @@ ze_result_t ModuleImp::initialize(const ze_module_desc_t *desc, NEO::Device *neo
}
registerElfInDebuggerL0();
this->maxGroupSize = static_cast<uint32_t>(neoDevice->getDeviceInfo().maxWorkGroupSize);
checkIfPrivateMemoryPerDispatchIsNeeded();
@@ -1279,7 +1280,7 @@ ze_result_t ModuleImp::destroy() {
void ModuleImp::registerElfInDebuggerL0() {
auto debuggerL0 = device->getL0Debugger();
if (!debuggerL0) {
if (this->type != ModuleType::User || !debuggerL0) {
return;
}

View File

@@ -519,6 +519,48 @@ HWTEST_F(ModuleWithDebuggerL0Test, GivenDebugDataWithRelocationsWhenInitializing
EXPECT_EQ(reinterpret_cast<char *>(kernelInfo->kernelDescriptor.external.relocatedDebugData.get()), getMockDebuggerL0Hw<FamilyType>()->lastReceivedElf);
}
HWTEST_F(ModuleWithDebuggerL0Test, GivenBuiltinModuleWhenInitializingModuleThenModuleAndElfNOtificationsAreNotCalled) {
auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions();
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->compilerInterface.reset(cip);
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<MockModule> moduleMock = std::make_unique<MockModule>(device, moduleBuildLog, ModuleType::Builtin);
moduleMock->translationUnit = std::make_unique<MockModuleTranslationUnit>(device);
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<NEO::DebugData>();
auto debugData = MockElfEncoder<>::createRelocateableDebugDataElf();
kernelInfo->kernelDescriptor.external.debugData->vIsaSize = static_cast<uint32_t>(debugData.size());
kernelInfo->kernelDescriptor.external.debugData->vIsa = reinterpret_cast<char *>(debugData.data());
kernelInfo->kernelDescriptor.external.debugData->genIsa = nullptr;
kernelInfo->kernelDescriptor.external.debugData->genIsaSize = 0;
EXPECT_EQ(0u, getMockDebuggerL0Hw<FamilyType>()->registerElfCount);
EXPECT_EQ(moduleMock->initialize(&moduleDesc, neoDevice), ZE_RESULT_SUCCESS);
EXPECT_EQ(0u, getMockDebuggerL0Hw<FamilyType>()->registerElfAndLinkCount);
EXPECT_EQ(0u, getMockDebuggerL0Hw<FamilyType>()->notifyModuleCreateCount);
EXPECT_NE(nullptr, kernelInfo->kernelDescriptor.external.relocatedDebugData.get());
EXPECT_EQ(nullptr, getMockDebuggerL0Hw<FamilyType>()->lastReceivedElf);
}
HWTEST_F(ModuleWithDebuggerL0Test, GivenDebugDataWithoutRelocationsWhenInitializingModuleThenRegisterElfWithUnrelocatedElfAndModuleCreateNotified) {
auto cip = new NEO::MockCompilerInterfaceCaptureBuildOptions();

View File

@@ -1032,6 +1032,8 @@ bool DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *v
}
}
if (handleEvent) {
for (uint32_t uuidIter = 0; uuidIter < vmBind->num_uuids; uuidIter++) {
if (connection->uuidMap[vmBind->uuids[uuidIter]].classIndex == NEO::DrmResourceClass::L0ZebinModule) {
uint64_t loadAddress = 0;
@@ -1168,6 +1170,8 @@ bool DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *v
module.moduleLoadEventAcked[tileIndex] = false;
}
}
break;
}
}
}
}

View File

@@ -3911,6 +3911,59 @@ TEST_F(DebugApiLinuxVmBindTest, GivenTwoPendingEventsWhenAcknowledgeEventCalledT
EXPECT_EQ(1u, session->eventsToAck.size());
}
TEST_F(DebugApiLinuxVmBindTest, GivenNoIsaUUIDAndZebinModuleForDataSegmentWhenHandlingVmBindEventThenModuleLoadAndUnloadEventsAreTriggered) {
setupVmToTile(session.get());
uint64_t vmBindIsaData[(sizeof(prelim_drm_i915_debug_event_vm_bind) + 2 * sizeof(typeOfUUID) + sizeof(uint64_t)) / sizeof(uint64_t)];
prelim_drm_i915_debug_event_vm_bind *vmBindIsa = reinterpret_cast<prelim_drm_i915_debug_event_vm_bind *>(&vmBindIsaData);
vmBindIsa->base.type = PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND;
vmBindIsa->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
vmBindIsa->base.flags |= PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK;
vmBindIsa->base.size = sizeof(prelim_drm_i915_debug_event_vm_bind) + 2 * sizeof(typeOfUUID);
vmBindIsa->base.seqno = 10;
vmBindIsa->client_handle = MockDebugSessionLinux::mockClientHandle;
vmBindIsa->va_start = isaGpuVa;
DebugSessionLinux::UuidData zebinModuleUuidData = {
.handle = zebinModuleUUID,
.classHandle = zebinModuleClassHandle,
.classIndex = NEO::DrmResourceClass::L0ZebinModule,
.data = std::make_unique<char[]>(sizeof(1)),
.dataSize = sizeof(1)};
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->uuidMap.emplace(zebinModuleUUID, std::move(zebinModuleUuidData));
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->uuidToModule[zebinModuleUUID].segmentCount = 1;
vmBindIsa->va_length = isaSize;
vmBindIsa->vm_handle = vm0;
vmBindIsa->num_uuids = 2;
auto *uuids = reinterpret_cast<typeOfUUID *>(ptrOffset(vmBindIsaData, sizeof(prelim_drm_i915_debug_event_vm_bind)));
typeOfUUID uuidsTemp[2];
uuidsTemp[0] = static_cast<typeOfUUID>(elfUUID);
uuidsTemp[1] = static_cast<typeOfUUID>(zebinModuleUUID);
memcpy_s(uuids, 2 * sizeof(typeOfUUID), uuidsTemp, sizeof(uuidsTemp));
session->handleEvent(&vmBindIsa->base);
EXPECT_EQ(1u, session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->uuidToModule[zebinModuleUUID].ackEvents[0].size());
EXPECT_EQ(1u, session->apiEvents.size());
EXPECT_EQ(1u, session->eventsToAck.size());
zet_debug_event_t event0 = {};
auto result = session->readEvent(0, &event0);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_MODULE_LOAD, event0.type);
vmBindIsa->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_DESTROY;
session->handleEvent(&vmBindIsa->base);
EXPECT_EQ(1u, session->apiEvents.size());
result = session->readEvent(0, &event0);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD, event0.type);
}
TEST_F(DebugApiLinuxVmBindTest, GivenBlockOnFenceAndTwoPendingEventsWhenAcknowledgeEventCalledThenCorrectEventIsAcked) {
session->blockOnFenceMode = true;
setupVmToTile(session.get());
@@ -4670,6 +4723,61 @@ TEST_F(DebugApiLinuxVmBindTest, GivenMultipleSegmentsInL0ZebinModuleWhenLoadAddr
EXPECT_EQ(0u, session->apiEvents.size());
}
TEST_F(DebugApiLinuxVmBindTest, GivenMultipleSegmentsInL0ZebinModuleWhenLoadAddressCountReachesSegmentsCountThenModuleLoadEventIsTriggered) {
const uint64_t isaGpuVa = 0x345000;
const uint64_t dataGpuVa = 0x333000;
const uint64_t isaSize = 0x2000;
const uint64_t dataSize = 0x2000;
uint64_t vmBindIsaData[sizeof(prelim_drm_i915_debug_event_vm_bind) / sizeof(uint64_t) + 3 * sizeof(typeOfUUID)];
prelim_drm_i915_debug_event_vm_bind *vmBindIsa = reinterpret_cast<prelim_drm_i915_debug_event_vm_bind *>(&vmBindIsaData);
const uint32_t segmentCount = 2;
DebugSessionLinux::UuidData zebinModuleUuidData = {
.handle = zebinModuleUUID,
.classHandle = zebinModuleClassHandle,
.classIndex = NEO::DrmResourceClass::L0ZebinModule,
.data = std::make_unique<char[]>(sizeof(segmentCount)),
.dataSize = sizeof(segmentCount)};
memcpy(zebinModuleUuidData.data.get(), &segmentCount, sizeof(segmentCount));
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->classHandleToIndex[zebinModuleClassHandle] = {"L0_ZEBIN_MODULE", static_cast<uint32_t>(NEO::DrmResourceClass::L0ZebinModule)};
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->uuidMap.emplace(zebinModuleUUID, std::move(zebinModuleUuidData));
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->uuidToModule[zebinModuleUUID].segmentCount = segmentCount;
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->uuidMap[elfUUID].ptr = 0x1000;
vmBindIsa->base.type = PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND;
vmBindIsa->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
vmBindIsa->base.size = sizeof(prelim_drm_i915_debug_event_vm_bind) + 3 * sizeof(typeOfUUID);
vmBindIsa->client_handle = MockDebugSessionLinux::mockClientHandle;
vmBindIsa->va_start = isaGpuVa;
vmBindIsa->va_length = isaSize;
vmBindIsa->vm_handle = vmHandleForVmBind;
vmBindIsa->num_uuids = 4;
auto *uuids = reinterpret_cast<typeOfUUID *>(ptrOffset(vmBindIsaData, sizeof(prelim_drm_i915_debug_event_vm_bind)));
typeOfUUID uuidsTemp[4];
uuidsTemp[0] = static_cast<typeOfUUID>(isaUUID);
uuidsTemp[1] = static_cast<typeOfUUID>(cookieUUID);
uuidsTemp[2] = static_cast<typeOfUUID>(elfUUID);
uuidsTemp[3] = static_cast<typeOfUUID>(zebinModuleUUID);
memcpy(uuids, uuidsTemp, sizeof(uuidsTemp));
session->handleEvent(&vmBindIsa->base);
vmBindIsa->num_uuids = 1;
vmBindIsa->va_start = dataGpuVa;
vmBindIsa->va_length = dataSize;
vmBindIsa->base.size = sizeof(prelim_drm_i915_debug_event_vm_bind) + 1 * sizeof(typeOfUUID);
uuidsTemp[0] = static_cast<typeOfUUID>(zebinModuleUUID); // only module UUID attached
memcpy(uuids, uuidsTemp, sizeof(typeOfUUID));
session->handleEvent(&vmBindIsa->base);
EXPECT_EQ(1u, session->apiEvents.size());
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_MODULE_LOAD, session->apiEvents.front().type);
}
TEST_F(DebugApiLinuxVmBindTest, GivenMultipleBindEventsWithZebinModuleWhenHandlingEventsThenModuleLoadIsReportedOnceOnly) {
uint64_t isaGpuVa = 0x345000;
uint64_t isaSize = 0x2000;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2022 Intel Corporation
* Copyright (C) 2020-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -58,6 +58,8 @@ bool DebuggerL0::attachZebinModuleToSegmentAllocations(const StackVec<NEO::Graph
for (auto &allocation : allocs) {
auto drmAllocation = static_cast<NEO::DrmAllocation *>(allocation);
DEBUG_BREAK_IF(allocation->getAllocationType() == AllocationType::KERNEL_ISA_INTERNAL);
drmAllocation->linkWithRegisteredHandle(elfHandle);
drmAllocation->linkWithRegisteredHandle(moduleHandle);
}