L0Debug - zebin modules support for mirrored isa heaps

- all tileInstanced ISAs must be received before sending
MODULE LOAD/UNLOAD events for zebin modules

Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
Mateusz Hoppe
2022-09-26 18:28:04 +00:00
committed by Compute-Runtime-Automation
parent eaa4965ae8
commit 7e2e940d6e
4 changed files with 170 additions and 4 deletions

View File

@@ -854,6 +854,7 @@ void DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *v
DEBUG_BREAK_IF(module.elfUuidHandle != 0 && connection->uuidMap[vmBind->uuids[index]].ptr != connection->uuidMap[module.elfUuidHandle].ptr);
module.elfUuidHandle = vmBind->uuids[index];
module.deviceBitfield = devices;
}
}
}
@@ -994,8 +995,14 @@ void DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *v
debugEvent.info.module.moduleEnd = connection->uuidMap[module.elfUuidHandle].ptr + connection->uuidMap[module.elfUuidHandle].dataSize;
if (!tileSessionsEnabled) {
pushApiEvent(debugEvent, &vmBind->base);
shouldAckEvent = false;
bool allInstancesEventsReceived = true;
if (module.deviceBitfield.count() > 1) {
allInstancesEventsReceived = checkAllOtherTileModuleSegmentsPresent(tileIndex, module);
}
if (allInstancesEventsReceived) {
pushApiEvent(debugEvent, &vmBind->base);
shouldAckEvent = false;
}
} else {
auto tileAttached = static_cast<TileDebugSessionLinux *>(tileSessions[tileIndex].first)->insertModule(debugEvent.info.module);
@@ -1031,7 +1038,13 @@ void DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *v
}
} else {
pushApiEvent(debugEvent, nullptr);
bool notifyEvent = true;
if (module.deviceBitfield.count() > 1) {
notifyEvent = checkAllOtherTileModuleSegmentsRemoved(tileIndex, module);
}
if (notifyEvent) {
pushApiEvent(debugEvent, nullptr);
}
}
module.loadAddresses[tileIndex].clear();
}

View File

@@ -124,6 +124,7 @@ struct DebugSessionLinux : DebugSessionImp {
std::unordered_set<uint64_t> loadAddresses[NEO::EngineLimits::maxHandleCount];
uint64_t elfUuidHandle;
uint32_t segmentCount;
NEO::DeviceBitfield deviceBitfield;
int segmentVmBindCounter[NEO::EngineLimits::maxHandleCount];
};
@@ -300,6 +301,32 @@ struct DebugSessionLinux : DebugSessionImp {
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;
}
ThreadHelper internalEventThread;
std::mutex internalEventThreadMutex;
std::condition_variable internalEventCondition;

View File

@@ -600,7 +600,7 @@ struct MockDebugSessionLinuxHelper {
}
void addIsaVmBindEvent(MockDebugSessionLinux *session, uint64_t vm, bool ack, bool create) {
uint64_t vmBindIsaData[sizeof(prelim_drm_i915_debug_event_vm_bind) / sizeof(uint64_t) + 3 * sizeof(typeOfUUID)];
uint64_t vmBindIsaData[(sizeof(prelim_drm_i915_debug_event_vm_bind) + 3 * 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;
@@ -633,6 +633,39 @@ struct MockDebugSessionLinuxHelper {
session->handleEvent(&vmBindIsa->base);
}
void addZebinVmBindEvent(MockDebugSessionLinux *session, uint64_t vm, bool ack, bool create, uint64_t kernelIndex) {
uint64_t vmBindIsaData[(sizeof(prelim_drm_i915_debug_event_vm_bind) + 4 * 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;
if (create) {
vmBindIsa->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
} else {
vmBindIsa->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_DESTROY;
}
if (ack) {
vmBindIsa->base.flags |= PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK;
}
vmBindIsa->base.size = sizeof(prelim_drm_i915_debug_event_vm_bind) + 4 * sizeof(typeOfUUID);
vmBindIsa->base.seqno = 10;
vmBindIsa->client_handle = MockDebugSessionLinux::mockClientHandle;
vmBindIsa->va_start = kernelIndex == 0 ? isaGpuVa : isaGpuVa + isaSize;
vmBindIsa->va_length = isaSize;
vmBindIsa->vm_handle = vm;
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_s(uuids, 4 * sizeof(typeOfUUID), uuidsTemp, sizeof(uuidsTemp));
session->handleEvent(&vmBindIsa->base);
}
const uint64_t sbaClassHandle = 1;
const uint64_t moduleDebugClassHandle = 2;
const uint64_t contextSaveClassHandle = 3;

View File

@@ -6507,6 +6507,99 @@ TEST_F(DebugApiLinuxMultiDeviceVmBindTest, givenTileInstancedIsaWhenHandlingVmBi
EXPECT_EQ(isaGpuVa, event.info.module.load);
}
TEST_F(DebugApiLinuxMultiDeviceVmBindTest, givenTileInstancedIsaAndZebinModuleWhenHandlingVmBindCreateEventsThenModuleLoadIsTriggeredAfterAllInstancesEventsReceived) {
auto handler = new MockIoctlHandler;
session->ioctlHandler.reset(handler);
uint32_t devices = static_cast<uint32_t>(deviceImp->getNEODevice()->getDeviceBitfield().to_ulong());
DebugSessionLinux::UuidData isaUuidData = {
.handle = isaUUID,
.classHandle = isaClassHandle,
.classIndex = NEO::DrmResourceClass::Isa,
.data = std::make_unique<char[]>(sizeof(devices)),
.dataSize = sizeof(devices)};
memcpy_s(isaUuidData.data.get(), sizeof(devices), &devices, sizeof(devices));
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->uuidMap[isaUUID] = std::move(isaUuidData);
addZebinVmBindEvent(session.get(), vm0, true, true, 0);
addZebinVmBindEvent(session.get(), vm0, true, true, 1);
EXPECT_EQ(2u, session->clientHandleToConnection[session->clientHandle]->isaMap[0].size());
EXPECT_EQ(0u, session->clientHandleToConnection[session->clientHandle]->isaMap[1].size());
EXPECT_EQ(10u, handler->debugEventAcked.seqno);
EXPECT_EQ(0u, session->apiEvents.size());
addZebinVmBindEvent(session.get(), vm1, true, true, 0);
addZebinVmBindEvent(session.get(), vm1, true, true, 1);
EXPECT_EQ(1u, session->apiEvents.size());
zet_debug_event_t event;
auto result = session->readEvent(0, &event);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_MODULE_LOAD, event.type);
EXPECT_EQ(isaGpuVa, event.info.module.load);
}
TEST_F(DebugApiLinuxMultiDeviceVmBindTest, givenTileInstancedIsaAndZebinModuleWhenHandlingVmBindDestroyEventsThenModuleUnloadIsTriggeredAfterAllInstancesEventsReceived) {
auto handler = new MockIoctlHandler;
session->ioctlHandler.reset(handler);
uint32_t devices = static_cast<uint32_t>(deviceImp->getNEODevice()->getDeviceBitfield().to_ulong());
DebugSessionLinux::UuidData isaUuidData = {
.handle = isaUUID,
.classHandle = isaClassHandle,
.classIndex = NEO::DrmResourceClass::Isa,
.data = std::make_unique<char[]>(sizeof(devices)),
.dataSize = sizeof(devices)};
memcpy_s(isaUuidData.data.get(), sizeof(devices), &devices, sizeof(devices));
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->uuidMap[isaUUID] = std::move(isaUuidData);
// VM BIND events for 2 kernels from zebin in vm0 - tile0
addZebinVmBindEvent(session.get(), vm0, true, true, 0);
addZebinVmBindEvent(session.get(), vm0, true, true, 1);
EXPECT_EQ(2u, session->clientHandleToConnection[session->clientHandle]->isaMap[0].size());
EXPECT_EQ(0u, session->clientHandleToConnection[session->clientHandle]->isaMap[1].size());
// VM BIND events for 2 kernels from zebin in vm1 - tile0
addZebinVmBindEvent(session.get(), vm1, true, true, 0);
addZebinVmBindEvent(session.get(), vm1, true, true, 1);
EXPECT_EQ(2u, session->clientHandleToConnection[session->clientHandle]->isaMap[1].size());
auto numberOfEvents = session->apiEvents.size();
// remove all VM BINDs
addZebinVmBindEvent(session.get(), vm1, false, false, 0);
EXPECT_EQ(numberOfEvents, session->apiEvents.size());
addZebinVmBindEvent(session.get(), vm1, false, false, 1);
EXPECT_EQ(numberOfEvents, session->apiEvents.size());
addZebinVmBindEvent(session.get(), vm0, false, false, 0);
EXPECT_EQ(numberOfEvents, session->apiEvents.size());
addZebinVmBindEvent(session.get(), vm0, false, false, 1);
// MODULE UNLOAD after all unbinds
auto numberOfAllEvents = session->apiEvents.size();
EXPECT_EQ(numberOfEvents + 1, numberOfAllEvents);
zet_debug_event_t event;
ze_result_t result = ZE_RESULT_SUCCESS;
while (numberOfAllEvents--) {
result = session->readEvent(0, &event);
if (result != ZE_RESULT_SUCCESS) {
break;
}
}
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD, event.type);
EXPECT_EQ(isaGpuVa, event.info.module.load);
}
TEST_F(DebugApiLinuxMultiDeviceVmBindTest, givenTileInstancedIsaWhenWritingAndReadingIsaMemoryThenOnlyWritesAreMirrored) {
auto handler = new MockIoctlHandler;
session->ioctlHandler.reset(handler);