L0Debug - support for out of order debug events

Related-To: NEO-7366
- if VM BIND comes with VM that cannot be mapped to tile,
push the event to pending events and process next events
until context params event with comes
- when pending event is handled - remove it from queue

Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
Mateusz Hoppe
2022-09-29 16:07:22 +00:00
committed by Compute-Runtime-Automation
parent 0d6ad522cb
commit 6811b1079f
4 changed files with 485 additions and 22 deletions

View File

@@ -257,8 +257,12 @@ ze_result_t DebugSessionLinux::initialize() {
bool eventAvailable = false;
do {
auto eventMemory = getInternalEvent();
auto debugEvent = reinterpret_cast<prelim_drm_i915_debug_event *>(eventMemory.get());
if (eventMemory != nullptr) {
handleEvent(reinterpret_cast<prelim_drm_i915_debug_event *>(eventMemory.get()));
handleEvent(debugEvent);
if (debugEvent->type != PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND && pendingVmBindEvents.size() > 0) {
processPendingVmBindEvents();
}
eventAvailable = true;
} else {
eventAvailable = false;
@@ -385,7 +389,12 @@ std::unique_ptr<uint64_t[]> DebugSessionLinux::getInternalEvent() {
void DebugSessionLinux::handleEventsAsync() {
auto eventMemory = getInternalEvent();
if (eventMemory != nullptr) {
handleEvent(reinterpret_cast<prelim_drm_i915_debug_event *>(eventMemory.get()));
auto debugEvent = reinterpret_cast<prelim_drm_i915_debug_event *>(eventMemory.get());
handleEvent(debugEvent);
if (debugEvent->type != PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND && pendingVmBindEvents.size() > 0) {
processPendingVmBindEvents();
}
}
}
@@ -645,7 +654,21 @@ void DebugSessionLinux::handleEvent(prelim_drm_i915_debug_event *event) {
case PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND: {
prelim_drm_i915_debug_event_vm_bind *vmBind = reinterpret_cast<prelim_drm_i915_debug_event_vm_bind *>(event);
handleVmBindEvent(vmBind);
if (!handleVmBindEvent(vmBind)) {
if (event->flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK) {
prelim_drm_i915_debug_event_ack eventToAck = {};
eventToAck.type = vmBind->base.type;
eventToAck.seqno = vmBind->base.seqno;
eventToAck.flags = 0;
auto ret = ioctl(PRELIM_I915_DEBUG_IOCTL_ACK_EVENT, &eventToAck);
PRINT_DEBUGGER_INFO_LOG("PRELIM_I915_DEBUG_IOCTL_ACK_EVENT seqno = %llu ret = %d errno = %d\n", (uint64_t)eventToAck.seqno, ret, ret != 0 ? errno : 0);
} else {
auto sizeAligned = alignUp(event->size, sizeof(uint64_t));
auto pendingEvent = std::make_unique<uint64_t[]>(sizeAligned / sizeof(uint64_t));
memcpy_s(pendingEvent.get(), sizeAligned, event, event->size);
pendingVmBindEvents.push_back(std::move(pendingEvent));
}
}
} break;
@@ -676,6 +699,20 @@ void DebugSessionLinux::handleEvent(prelim_drm_i915_debug_event *event) {
}
}
void DebugSessionLinux::processPendingVmBindEvents() {
size_t processedEvents = 0;
for (size_t index = 0; index < pendingVmBindEvents.size(); index++) {
auto debugEvent = reinterpret_cast<prelim_drm_i915_debug_event_vm_bind *>(pendingVmBindEvents[index].get());
if (handleVmBindEvent(debugEvent) == false) {
break;
}
processedEvents++;
}
if (processedEvents > 0) {
pendingVmBindEvents.erase(pendingVmBindEvents.begin(), pendingVmBindEvents.begin() + processedEvents);
}
}
bool DebugSessionLinux::checkAllEventsCollected() {
bool allEventsCollected = false;
bool clientConnected = (this->clientHandle != invalidClientHandle);
@@ -756,7 +793,7 @@ ze_result_t DebugSessionLinux::readEventImp(prelim_drm_i915_debug_event *drmDebu
return ZE_RESULT_NOT_READY;
}
void DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *vmBind) {
bool DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *vmBind) {
PRINT_DEBUGGER_INFO_LOG("PRELIM_I915_DEBUG_IOCTL_READ_EVENT type: PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND flags = %d size = %llu client_handle = %llu vm_handle = %llu va_start = %p va_lenght = %llu num_uuids = %lu\n",
(int)vmBind->base.flags, (uint64_t)vmBind->base.size, (uint64_t)vmBind->client_handle, (uint64_t)vmBind->vm_handle, (void *)vmBind->va_start, (uint64_t)vmBind->va_length, (uint32_t)vmBind->num_uuids);
@@ -774,10 +811,15 @@ void DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *v
if (connection->uuidMap.find(uuid) == connection->uuidMap.end()) {
PRINT_DEBUGGER_ERROR_LOG("Unknown UUID handle = %llu\n", (uint64_t)uuid);
return;
return false;
}
if (connection->vmToTile.find(vmHandle) == connection->vmToTile.end()) {
DEBUG_BREAK_IF(connection->vmToTile.find(vmHandle) == connection->vmToTile.end() &&
(connection->uuidMap[uuid].classIndex == NEO::DrmResourceClass::Isa || connection->uuidMap[uuid].classIndex == NEO::DrmResourceClass::ModuleHeapDebugArea));
return false;
}
DEBUG_BREAK_IF(connection->vmToTile.find(vmHandle) == connection->vmToTile.end() && connection->uuidMap[uuid].classIndex == NEO::DrmResourceClass::Isa);
const auto tileIndex = connection->vmToTile[vmHandle];
PRINT_DEBUGGER_INFO_LOG("UUID handle = %llu class index = %d\n", (uint64_t)vmBind->uuids[index], (int)clientHandleToConnection[vmBind->client_handle]->uuidMap[vmBind->uuids[index]].classIndex);
@@ -1051,16 +1093,18 @@ void DebugSessionLinux::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *v
}
}
}
}
if (shouldAckEvent && (vmBind->base.flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK)) {
prelim_drm_i915_debug_event_ack eventToAck = {};
eventToAck.type = vmBind->base.type;
eventToAck.seqno = vmBind->base.seqno;
eventToAck.flags = 0;
auto ret = ioctl(PRELIM_I915_DEBUG_IOCTL_ACK_EVENT, &eventToAck);
PRINT_DEBUGGER_INFO_LOG("PRELIM_I915_DEBUG_IOCTL_ACK_EVENT seqno = %llu ret = %d errno = %d\n", (uint64_t)eventToAck.seqno, ret, ret != 0 ? errno : 0);
if (shouldAckEvent && (vmBind->base.flags & PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK)) {
prelim_drm_i915_debug_event_ack eventToAck = {};
eventToAck.type = vmBind->base.type;
eventToAck.seqno = vmBind->base.seqno;
eventToAck.flags = 0;
auto ret = ioctl(PRELIM_I915_DEBUG_IOCTL_ACK_EVENT, &eventToAck);
PRINT_DEBUGGER_INFO_LOG("PRELIM_I915_DEBUG_IOCTL_ACK_EVENT seqno = %llu ret = %d errno = %d\n", (uint64_t)eventToAck.seqno, ret, ret != 0 ? errno : 0);
}
return true;
}
return false;
}
void DebugSessionLinux::handleContextParamEvent(prelim_drm_i915_debug_event_context_param *contextParam) {

View File

@@ -206,7 +206,7 @@ struct DebugSessionLinux : DebugSessionImp {
void startAsyncThread() override;
void closeAsyncThread();
void startInternalEventsThread() {
MOCKABLE_VIRTUAL void startInternalEventsThread() {
internalEventThread.thread = NEO::Thread::create(readInternalEventsThreadFunction, reinterpret_cast<void *>(this));
}
void closeInternalEventsThread() {
@@ -229,11 +229,12 @@ struct DebugSessionLinux : DebugSessionImp {
void readInternalEventsAsync();
MOCKABLE_VIRTUAL std::unique_ptr<uint64_t[]> getInternalEvent();
void handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *vmBind);
bool handleVmBindEvent(prelim_drm_i915_debug_event_vm_bind *vmBind);
void handleContextParamEvent(prelim_drm_i915_debug_event_context_param *contextParam);
void handleAttentionEvent(prelim_drm_i915_debug_event_eu_attention *attention);
void handleEnginesEvent(prelim_drm_i915_debug_event_engines *engines);
virtual bool ackIsaEvents(uint32_t deviceIndex, uint64_t isaVa);
MOCKABLE_VIRTUAL void processPendingVmBindEvents();
void attachTile() override {
UNRECOVERABLE_IF(true);
@@ -332,6 +333,7 @@ struct DebugSessionLinux : DebugSessionImp {
std::condition_variable internalEventCondition;
std::queue<std::unique_ptr<uint64_t[]>> internalEventQueue;
std::vector<std::pair<zet_debug_event_t, prelim_drm_i915_debug_event_ack>> eventsToAck;
std::vector<std::unique_ptr<uint64_t[]>> pendingVmBindEvents;
int fd = 0;
virtual int ioctl(unsigned long request, void *arg);

View File

@@ -275,6 +275,7 @@ struct MockDebugSessionLinux : public L0::DebugSessionLinux {
using L0::DebugSessionLinux::ioctlHandler;
using L0::DebugSessionLinux::newlyStoppedThreads;
using L0::DebugSessionLinux::pendingInterrupts;
using L0::DebugSessionLinux::pendingVmBindEvents;
using L0::DebugSessionLinux::printContextVms;
using L0::DebugSessionLinux::pushApiEvent;
using L0::DebugSessionLinux::readEventImp;
@@ -397,6 +398,13 @@ struct MockDebugSessionLinux : public L0::DebugSessionLinux {
return L0::DebugSessionLinux::checkThreadIsResumed(threadID);
}
void startInternalEventsThread() override {
if (synchronousInternalEventRead) {
return;
}
return DebugSessionLinux::startInternalEventsThread();
}
std::unique_ptr<uint64_t[]> getInternalEvent() override {
getInternalEventCounter++;
if (synchronousInternalEventRead) {
@@ -405,6 +413,11 @@ struct MockDebugSessionLinux : public L0::DebugSessionLinux {
return DebugSessionLinux::getInternalEvent();
}
void processPendingVmBindEvents() override {
processPendingVmBindEventsCalled++;
return DebugSessionLinux::processPendingVmBindEvents();
}
TileDebugSessionLinux *createTileSession(const zet_debug_config_t &config, L0::Device *device, L0::DebugSessionImp *rootDebugSession) override;
ze_result_t initializeRetVal = ZE_RESULT_FORCE_UINT32;
@@ -422,6 +435,7 @@ struct MockDebugSessionLinux : public L0::DebugSessionLinux {
bool skipcheckThreadIsResumed = true;
uint32_t checkThreadIsResumedCalled = 0;
uint32_t interruptedDevice = std::numeric_limits<uint32_t>::max();
uint32_t processPendingVmBindEventsCalled = 0;
std::vector<uint32_t> resumedDevices;
std::vector<std::vector<EuThread::ThreadId>> resumedThreads;

View File

@@ -2376,13 +2376,15 @@ TEST_F(DebugApiLinuxTest, GivenErrorInVmOpenWhenReadingModuleDebugAreaThenGpuMem
EXPECT_STRNE("dbgarea", session->debugArea.magic);
}
TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenInitializingThenSuccessIsReturned) {
TEST_F(DebugApiLinuxTest, GivenInOrderClientVmContextUuidAndModuleDebugAreaEventsWhenInitializingThenSuccessIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinux>(config, device, 10);
ASSERT_NE(nullptr, session);
session->synchronousInternalEventRead = true;
const uint64_t vmId = 50;
prelim_drm_i915_debug_event_client client = {};
client.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CLIENT;
@@ -2390,6 +2392,15 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenInitiali
client.base.size = sizeof(prelim_drm_i915_debug_event_client);
client.handle = 1;
uint64_t vmData[(sizeof(prelim_drm_i915_debug_event_vm) + sizeof(uint64_t)) / sizeof(uint64_t)];
prelim_drm_i915_debug_event_vm *vm = reinterpret_cast<prelim_drm_i915_debug_event_vm *>(&vmData);
vm->base.type = PRELIM_DRM_I915_DEBUG_EVENT_VM;
vm->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
vm->base.size = sizeof(prelim_drm_i915_debug_event_vm);
vm->client_handle = MockDebugSessionLinux::mockClientHandle;
vm->handle = vmId;
prelim_drm_i915_debug_event_context context = {};
context.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT;
@@ -2398,6 +2409,43 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenInitiali
context.client_handle = MockDebugSessionLinux::mockClientHandle;
context.handle = 3;
prelim_drm_i915_debug_event_context_param contextParamEvent = {};
contextParamEvent.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM;
contextParamEvent.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
contextParamEvent.base.size = sizeof(prelim_drm_i915_debug_event_context_param);
contextParamEvent.client_handle = MockDebugSessionLinux::mockClientHandle;
contextParamEvent.ctx_handle = context.handle;
contextParamEvent.param = {.ctx_id = static_cast<uint32_t>(context.handle), .size = 8, .param = I915_CONTEXT_PARAM_VM, .value = vmId};
constexpr auto size = sizeof(prelim_drm_i915_debug_event_context_param) + sizeof(i915_context_param_engines) + sizeof(i915_engine_class_instance) + sizeof(uint64_t);
uint64_t contextParamData[size / sizeof(uint64_t)];
auto *contextParamEvent2 = reinterpret_cast<prelim_drm_i915_debug_event_context_param *>(contextParamData);
contextParamEvent2->base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM;
contextParamEvent2->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
contextParamEvent2->base.size = size;
contextParamEvent2->client_handle = MockDebugSessionLinux::mockClientHandle;
contextParamEvent2->ctx_handle = context.handle;
auto offset = offsetof(prelim_drm_i915_debug_event_context_param, param);
GemContextParam paramToCopy = {};
paramToCopy.contextId = static_cast<uint32_t>(context.handle);
paramToCopy.size = sizeof(i915_context_param_engines) + sizeof(i915_engine_class_instance);
paramToCopy.param = I915_CONTEXT_PARAM_ENGINES;
paramToCopy.value = 0;
memcpy(ptrOffset(contextParamData, offset), &paramToCopy, sizeof(GemContextParam));
auto valueOffset = offsetof(GemContextParam, value);
auto *engines = ptrOffset(contextParamData, offset + valueOffset);
i915_context_param_engines enginesParam;
enginesParam.extensions = 0;
memcpy(engines, &enginesParam, sizeof(i915_context_param_engines));
auto enginesOffset = offsetof(i915_context_param_engines, engines);
auto *classInstance = ptrOffset(contextParamData, offset + valueOffset + enginesOffset);
i915_engine_class_instance ci = {drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER, 1};
memcpy(classInstance, &ci, sizeof(i915_engine_class_instance));
auto uuidName = NEO::classNamesToUuid[2].first;
auto uuidNameSize = strlen(uuidName);
auto uuidHash = NEO::classNamesToUuid[2].second;
@@ -2437,7 +2485,7 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenInitiali
vmBindDebugArea->client_handle = MockDebugSessionLinux::mockClientHandle;
vmBindDebugArea->va_start = moduleDebugAddress;
vmBindDebugArea->va_length = 0x1000;
vmBindDebugArea->vm_handle = 50;
vmBindDebugArea->vm_handle = vmId;
vmBindDebugArea->num_uuids = 1;
auto uuids = reinterpret_cast<typeOfUUID *>(ptrOffset(vmBindDebugAreaData, sizeof(prelim_drm_i915_debug_event_vm_bind)));
typeOfUUID uuidTemp = 3;
@@ -2445,7 +2493,10 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenInitiali
auto handler = new MockIoctlHandler;
handler->eventQueue.push({reinterpret_cast<char *>(&client), static_cast<uint64_t>(client.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(vm), static_cast<uint64_t>(vm->base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&context), static_cast<uint64_t>(context.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&contextParamEvent), static_cast<uint64_t>(contextParamEvent.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(contextParamEvent2), static_cast<uint64_t>(contextParamEvent2->base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&uuid), static_cast<uint64_t>(uuid.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&uuidDebugArea), static_cast<uint64_t>(uuidDebugArea.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(vmBindDebugArea), static_cast<uint64_t>(vmBindDebugArea->base.size)});
@@ -2471,16 +2522,19 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenInitiali
EXPECT_EQ(eventsCount, static_cast<size_t>(session->getInternalEventCounter.load()));
// Expect VM OPEN called
EXPECT_EQ(50u, handler->vmOpen.handle);
EXPECT_EQ(vmId, handler->vmOpen.handle);
EXPECT_EQ(0u, session->processPendingVmBindEventsCalled);
}
TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenIncorrectModuleDebugAreaReadThenErrorIsReturned) {
TEST_F(DebugApiLinuxTest, GivenOutOfOrderClientVmContextUuidAndModuleDebugAreaEventsWhenInitializingThenPendingVmBindIsProcessedAndSuccessReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinux>(config, device, 10);
ASSERT_NE(nullptr, session);
session->synchronousInternalEventRead = true;
const uint64_t vmId = 50;
prelim_drm_i915_debug_event_client client = {};
client.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CLIENT;
@@ -2488,6 +2542,15 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenIncorrec
client.base.size = sizeof(prelim_drm_i915_debug_event_client);
client.handle = 1;
uint64_t vmData[(sizeof(prelim_drm_i915_debug_event_vm) + sizeof(uint64_t)) / sizeof(uint64_t)];
prelim_drm_i915_debug_event_vm *vm = reinterpret_cast<prelim_drm_i915_debug_event_vm *>(&vmData);
vm->base.type = PRELIM_DRM_I915_DEBUG_EVENT_VM;
vm->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
vm->base.size = sizeof(prelim_drm_i915_debug_event_vm);
vm->client_handle = MockDebugSessionLinux::mockClientHandle;
vm->handle = vmId;
prelim_drm_i915_debug_event_context context = {};
context.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT;
@@ -2496,6 +2559,43 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenIncorrec
context.client_handle = MockDebugSessionLinux::mockClientHandle;
context.handle = 3;
prelim_drm_i915_debug_event_context_param contextParamEvent = {};
contextParamEvent.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM;
contextParamEvent.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
contextParamEvent.base.size = sizeof(prelim_drm_i915_debug_event_context_param);
contextParamEvent.client_handle = MockDebugSessionLinux::mockClientHandle;
contextParamEvent.ctx_handle = context.handle;
contextParamEvent.param = {.ctx_id = static_cast<uint32_t>(context.handle), .size = 8, .param = I915_CONTEXT_PARAM_VM, .value = vmId};
constexpr auto size = sizeof(prelim_drm_i915_debug_event_context_param) + sizeof(i915_context_param_engines) + sizeof(i915_engine_class_instance) + sizeof(uint64_t);
uint64_t contextParamData[size / sizeof(uint64_t)];
auto *contextParamEvent2 = reinterpret_cast<prelim_drm_i915_debug_event_context_param *>(contextParamData);
contextParamEvent2->base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM;
contextParamEvent2->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
contextParamEvent2->base.size = size;
contextParamEvent2->client_handle = MockDebugSessionLinux::mockClientHandle;
contextParamEvent2->ctx_handle = context.handle;
auto offset = offsetof(prelim_drm_i915_debug_event_context_param, param);
GemContextParam paramToCopy = {};
paramToCopy.contextId = static_cast<uint32_t>(context.handle);
paramToCopy.size = sizeof(i915_context_param_engines) + sizeof(i915_engine_class_instance);
paramToCopy.param = I915_CONTEXT_PARAM_ENGINES;
paramToCopy.value = 0;
memcpy(ptrOffset(contextParamData, offset), &paramToCopy, sizeof(GemContextParam));
auto valueOffset = offsetof(GemContextParam, value);
auto *engines = ptrOffset(contextParamData, offset + valueOffset);
i915_context_param_engines enginesParam;
enginesParam.extensions = 0;
memcpy(engines, &enginesParam, sizeof(i915_context_param_engines));
auto enginesOffset = offsetof(i915_context_param_engines, engines);
auto *classInstance = ptrOffset(contextParamData, offset + valueOffset + enginesOffset);
i915_engine_class_instance ci = {drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER, 1};
memcpy(classInstance, &ci, sizeof(i915_engine_class_instance));
auto uuidName = NEO::classNamesToUuid[2].first;
auto uuidNameSize = strlen(uuidName);
auto uuidHash = NEO::classNamesToUuid[2].second;
@@ -2535,7 +2635,7 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenIncorrec
vmBindDebugArea->client_handle = MockDebugSessionLinux::mockClientHandle;
vmBindDebugArea->va_start = moduleDebugAddress;
vmBindDebugArea->va_length = 0x1000;
vmBindDebugArea->vm_handle = 0;
vmBindDebugArea->vm_handle = vmId;
vmBindDebugArea->num_uuids = 1;
auto uuids = reinterpret_cast<typeOfUUID *>(ptrOffset(vmBindDebugAreaData, sizeof(prelim_drm_i915_debug_event_vm_bind)));
typeOfUUID uuidTemp = 3;
@@ -2543,15 +2643,173 @@ TEST_F(DebugApiLinuxTest, GivenClientContextAndModuleDebugAreaEventsWhenIncorrec
auto handler = new MockIoctlHandler;
handler->eventQueue.push({reinterpret_cast<char *>(&client), static_cast<uint64_t>(client.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(vm), static_cast<uint64_t>(vm->base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&context), static_cast<uint64_t>(context.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&uuid), static_cast<uint64_t>(uuid.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&uuidDebugArea), static_cast<uint64_t>(uuidDebugArea.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(vmBindDebugArea), static_cast<uint64_t>(vmBindDebugArea->base.size)});
// context params allowing to map VM to TILE after VM BIND
handler->eventQueue.push({reinterpret_cast<char *>(&contextParamEvent), static_cast<uint64_t>(contextParamEvent.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(contextParamEvent2), static_cast<uint64_t>(contextParamEvent2->base.size)});
handler->returnUuid = &readUuid;
auto eventsCount = handler->eventQueue.size();
handler->pollRetVal = 1;
DebugAreaHeader debugArea;
debugArea.reserved1 = 1;
debugArea.pgsize = uint8_t(4);
debugArea.version = 1;
handler->mmapRet = reinterpret_cast<char *>(&debugArea);
handler->setPreadMemory(reinterpret_cast<char *>(&debugArea), sizeof(session->debugArea), moduleDebugAddress);
handler->preadRetVal = sizeof(session->debugArea);
session->ioctlHandler.reset(handler);
ze_result_t result = session->initialize();
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(eventsCount, static_cast<size_t>(session->getInternalEventCounter.load()));
// Expect VM OPEN called
EXPECT_EQ(vmId, handler->vmOpen.handle);
EXPECT_EQ(2u, session->processPendingVmBindEventsCalled);
EXPECT_EQ(0u, session->pendingVmBindEvents.size());
}
TEST_F(DebugApiLinuxTest, GivenAllNecessaryEventsWhenIncorrectModuleDebugAreaReadThenErrorIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinux>(config, device, 10);
ASSERT_NE(nullptr, session);
session->synchronousInternalEventRead = true;
const uint64_t vmId = 50;
prelim_drm_i915_debug_event_client client = {};
client.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CLIENT;
client.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
client.base.size = sizeof(prelim_drm_i915_debug_event_client);
client.handle = 1;
uint64_t vmData[(sizeof(prelim_drm_i915_debug_event_vm) + sizeof(uint64_t)) / sizeof(uint64_t)];
prelim_drm_i915_debug_event_vm *vm = reinterpret_cast<prelim_drm_i915_debug_event_vm *>(&vmData);
vm->base.type = PRELIM_DRM_I915_DEBUG_EVENT_VM;
vm->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
vm->base.size = sizeof(prelim_drm_i915_debug_event_vm);
vm->client_handle = MockDebugSessionLinux::mockClientHandle;
vm->handle = vmId;
prelim_drm_i915_debug_event_context context = {};
context.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT;
context.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
context.base.size = sizeof(prelim_drm_i915_debug_event_context);
context.client_handle = MockDebugSessionLinux::mockClientHandle;
context.handle = 3;
prelim_drm_i915_debug_event_context_param contextParamEvent = {};
contextParamEvent.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM;
contextParamEvent.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
contextParamEvent.base.size = sizeof(prelim_drm_i915_debug_event_context_param);
contextParamEvent.client_handle = MockDebugSessionLinux::mockClientHandle;
contextParamEvent.ctx_handle = context.handle;
contextParamEvent.param = {.ctx_id = static_cast<uint32_t>(context.handle), .size = 8, .param = I915_CONTEXT_PARAM_VM, .value = vmId};
constexpr auto size = sizeof(prelim_drm_i915_debug_event_context_param) + sizeof(i915_context_param_engines) + sizeof(i915_engine_class_instance) + sizeof(uint64_t);
uint64_t contextParamData[size / sizeof(uint64_t)];
auto *contextParamEvent2 = reinterpret_cast<prelim_drm_i915_debug_event_context_param *>(contextParamData);
contextParamEvent2->base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM;
contextParamEvent2->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
contextParamEvent2->base.size = size;
contextParamEvent2->client_handle = MockDebugSessionLinux::mockClientHandle;
contextParamEvent2->ctx_handle = context.handle;
auto offset = offsetof(prelim_drm_i915_debug_event_context_param, param);
GemContextParam paramToCopy = {};
paramToCopy.contextId = static_cast<uint32_t>(context.handle);
paramToCopy.size = sizeof(i915_context_param_engines) + sizeof(i915_engine_class_instance);
paramToCopy.param = I915_CONTEXT_PARAM_ENGINES;
paramToCopy.value = 0;
memcpy(ptrOffset(contextParamData, offset), &paramToCopy, sizeof(GemContextParam));
auto valueOffset = offsetof(GemContextParam, value);
auto *engines = ptrOffset(contextParamData, offset + valueOffset);
i915_context_param_engines enginesParam;
enginesParam.extensions = 0;
memcpy(engines, &enginesParam, sizeof(i915_context_param_engines));
auto enginesOffset = offsetof(i915_context_param_engines, engines);
auto *classInstance = ptrOffset(contextParamData, offset + valueOffset + enginesOffset);
i915_engine_class_instance ci = {drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER, 1};
memcpy(classInstance, &ci, sizeof(i915_engine_class_instance));
auto uuidName = NEO::classNamesToUuid[2].first;
auto uuidNameSize = strlen(uuidName);
auto uuidHash = NEO::classNamesToUuid[2].second;
prelim_drm_i915_debug_event_uuid uuid = {};
uuid.base.type = PRELIM_DRM_I915_DEBUG_EVENT_UUID;
uuid.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
uuid.base.size = sizeof(prelim_drm_i915_debug_event_uuid);
uuid.client_handle = MockDebugSessionLinux::mockClientHandle;
uuid.handle = 2;
uuid.class_handle = PRELIM_I915_UUID_CLASS_STRING;
uuid.payload_size = uuidNameSize;
prelim_drm_i915_debug_read_uuid readUuid = {};
readUuid.client_handle = MockDebugSessionLinux::mockClientHandle;
memcpy(readUuid.uuid, uuidHash.data(), uuidHash.size());
readUuid.payload_ptr = reinterpret_cast<uint64_t>(uuidName);
readUuid.payload_size = uuid.payload_size;
readUuid.handle = 3;
prelim_drm_i915_debug_event_uuid uuidDebugArea = {};
uuidDebugArea.base.type = PRELIM_DRM_I915_DEBUG_EVENT_UUID;
uuidDebugArea.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
uuidDebugArea.base.size = sizeof(prelim_drm_i915_debug_event_uuid);
uuidDebugArea.client_handle = MockDebugSessionLinux::mockClientHandle;
uuidDebugArea.handle = 3;
uuidDebugArea.class_handle = 2;
uint64_t moduleDebugAddress = 0x34567000;
uint64_t vmBindDebugAreaData[sizeof(prelim_drm_i915_debug_event_vm_bind) / sizeof(uint64_t) + sizeof(typeOfUUID)];
prelim_drm_i915_debug_event_vm_bind *vmBindDebugArea = reinterpret_cast<prelim_drm_i915_debug_event_vm_bind *>(&vmBindDebugAreaData);
vmBindDebugArea->base.type = PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND;
vmBindDebugArea->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
vmBindDebugArea->base.size = sizeof(prelim_drm_i915_debug_event_vm_bind) + sizeof(typeOfUUID);
vmBindDebugArea->client_handle = MockDebugSessionLinux::mockClientHandle;
vmBindDebugArea->va_start = moduleDebugAddress;
vmBindDebugArea->va_length = 0x1000;
vmBindDebugArea->vm_handle = vmId;
vmBindDebugArea->num_uuids = 1;
auto uuids = reinterpret_cast<typeOfUUID *>(ptrOffset(vmBindDebugAreaData, sizeof(prelim_drm_i915_debug_event_vm_bind)));
typeOfUUID uuidTemp = 3;
memcpy(uuids, &uuidTemp, sizeof(typeOfUUID));
auto handler = new MockIoctlHandler;
handler->eventQueue.push({reinterpret_cast<char *>(&client), static_cast<uint64_t>(client.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(vm), static_cast<uint64_t>(vm->base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&context), static_cast<uint64_t>(context.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&contextParamEvent), static_cast<uint64_t>(contextParamEvent.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(contextParamEvent2), static_cast<uint64_t>(contextParamEvent2->base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&uuid), static_cast<uint64_t>(uuid.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&uuidDebugArea), static_cast<uint64_t>(uuidDebugArea.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(vmBindDebugArea), static_cast<uint64_t>(vmBindDebugArea->base.size)});
handler->returnUuid = &readUuid;
handler->pollRetVal = 1;
session->ioctlHandler.reset(handler);
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->vmToTile[0] = 0;
ze_result_t result = session->initialize();
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, result);
@@ -3246,6 +3504,7 @@ struct DebugApiLinuxVmBindFixture : public DebugApiLinuxFixture, public MockDebu
handler = new MockIoctlHandler;
session->ioctlHandler.reset(handler);
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->vmToTile[vmHandleForVmBind] = 0;
setupSessionClassHandlesAndUuidMap(session.get());
}
@@ -3313,6 +3572,9 @@ TEST_F(DebugApiLinuxVmBindTest, GivenVmBindEventWithKnownUuidClassWhenHandlingEv
temp = static_cast<typeOfUUID>(stateSaveUUID);
memcpy(uuids, &temp, sizeof(typeOfUUID));
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->vmToTile[4] = 0;
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->vmToTile[5] = 0;
session->handleEvent(&vmBindSba->base);
session->handleEvent(&vmBindDebugArea->base);
session->handleEvent(&vmBindContextArea->base);
@@ -3363,7 +3625,7 @@ TEST_F(DebugApiLinuxVmBindTest, GivenNeedsAckFlagWhenHandlingVmBindEventThenAckI
vmBind.va_length = 0x1000;
vmBind.num_uuids = 0;
session->handleVmBindEvent(&vmBind);
session->handleEvent(&vmBind.base);
EXPECT_EQ(1, handler->ioctlCalled);
EXPECT_EQ(vmBind.base.seqno, handler->debugEventAcked.seqno);
@@ -3417,6 +3679,44 @@ TEST_F(DebugApiLinuxVmBindTest, GivenEventWithAckFlagWhenHandlingEventForISAThen
EXPECT_EQ(vmBindIsa->base.type, ackedEvent.type);
}
TEST_F(DebugApiLinuxVmBindTest, GivenUnknownVmAndEventWithAckFlagForIsaWhenHandlingVmBindEventThenEventIsAutoAckedAndNotPushedToPendingEvents) {
uint64_t isaGpuVa = 0x345000;
uint64_t isaSize = 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);
vmBindIsa->base.type = PRELIM_DRM_I915_DEBUG_EVENT_VM_BIND;
vmBindIsa->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE | PRELIM_DRM_I915_DEBUG_EVENT_NEED_ACK;
vmBindIsa->base.size = sizeof(prelim_drm_i915_debug_event_vm_bind) + 3 * sizeof(typeOfUUID);
vmBindIsa->base.seqno = 20u;
vmBindIsa->client_handle = MockDebugSessionLinux::mockClientHandle;
vmBindIsa->va_start = isaGpuVa;
vmBindIsa->va_length = isaSize;
vmBindIsa->vm_handle = 5678;
vmBindIsa->num_uuids = 3;
auto *uuids = reinterpret_cast<typeOfUUID *>(ptrOffset(vmBindIsaData, sizeof(prelim_drm_i915_debug_event_vm_bind)));
typeOfUUID uuidsTemp[3];
uuidsTemp[0] = static_cast<typeOfUUID>(isaUUID);
uuidsTemp[1] = static_cast<typeOfUUID>(cookieUUID);
uuidsTemp[2] = static_cast<typeOfUUID>(elfUUID);
memcpy(uuids, uuidsTemp, sizeof(uuidsTemp));
session->handleEvent(&vmBindIsa->base);
EXPECT_EQ(0u, session->apiEvents.size());
EXPECT_EQ(0u, session->eventsToAck.size());
auto isaIter = session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->isaMap[0].find(isaGpuVa);
ASSERT_EQ(session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->isaMap[0].end(), isaIter);
EXPECT_EQ(0u, session->processPendingVmBindEventsCalled);
EXPECT_EQ(20u, handler->debugEventAcked.seqno);
EXPECT_EQ(1u, handler->ackCount);
}
TEST_F(DebugApiLinuxVmBindTest, GivenEventForISAWhenModuleLoadEventAlreadyAckedThenEventIsAckedImmediatelyAndNotPushed) {
uint64_t isaGpuVa = 0x345000;
uint64_t isaSize = 0x2000;
@@ -5503,6 +5803,109 @@ TEST_F(DebugApiLinuxAsyncThreadTest, GivenEventsAvailableWhenHandlingEventsAsync
EXPECT_NE(nullptr, session->clientHandleToConnection[clientHandle]);
}
TEST_F(DebugApiLinuxAsyncThreadTest, GivenOutOfOrderEventsForIsaWithoutAckNeededFlagWhenHandleEventsAsyncCalledThenPendingVmBindEventsAreHandled) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinux>(config, device, 10);
ASSERT_NE(nullptr, session);
auto handler = new MockIoctlHandler;
handler->pollRetVal = 1;
session->ioctlHandler.reset(handler);
session->clientHandle = MockDebugSessionLinux::mockClientHandle;
session->synchronousInternalEventRead = true;
uint64_t isaUUID = 10;
uint64_t isaClassHandle = 64;
uint32_t devices = static_cast<uint32_t>(device->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);
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->classHandleToIndex[isaClassHandle] = {"ISA", static_cast<uint32_t>(NEO::DrmResourceClass::Isa)};
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);
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) + 1 * sizeof(typeOfUUID);
vmBindIsa->base.seqno = 20u;
vmBindIsa->client_handle = MockDebugSessionLinux::mockClientHandle;
vmBindIsa->va_start = 0x1234000;
vmBindIsa->va_length = 0x1000;
vmBindIsa->vm_handle = 10;
vmBindIsa->num_uuids = 1;
auto *uuids = reinterpret_cast<typeOfUUID *>(ptrOffset(vmBindIsaData, sizeof(prelim_drm_i915_debug_event_vm_bind)));
typeOfUUID uuidsTemp[1];
uuidsTemp[0] = static_cast<typeOfUUID>(isaUUID);
memcpy(uuids, uuidsTemp, sizeof(uuidsTemp));
uint64_t contextHandle = 12;
session->clientHandleToConnection[MockDebugSessionLinux::mockClientHandle]->contextsCreated[contextHandle];
prelim_drm_i915_debug_event_context_param contextParamEvent = {};
contextParamEvent.base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM;
contextParamEvent.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
contextParamEvent.base.size = sizeof(prelim_drm_i915_debug_event_context_param);
contextParamEvent.client_handle = MockDebugSessionLinux::mockClientHandle;
contextParamEvent.ctx_handle = contextHandle;
contextParamEvent.param = {.ctx_id = static_cast<uint32_t>(contextHandle), .size = 8, .param = I915_CONTEXT_PARAM_VM, .value = 10};
constexpr auto size = sizeof(prelim_drm_i915_debug_event_context_param) + sizeof(i915_context_param_engines) + sizeof(i915_engine_class_instance) + sizeof(uint64_t);
uint64_t contextParamData[size / sizeof(uint64_t)];
auto *contextParamEvent2 = reinterpret_cast<prelim_drm_i915_debug_event_context_param *>(contextParamData);
contextParamEvent2->base.type = PRELIM_DRM_I915_DEBUG_EVENT_CONTEXT_PARAM;
contextParamEvent2->base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
contextParamEvent2->base.size = size;
contextParamEvent2->client_handle = MockDebugSessionLinux::mockClientHandle;
contextParamEvent2->ctx_handle = contextHandle;
auto offset = offsetof(prelim_drm_i915_debug_event_context_param, param);
GemContextParam paramToCopy = {};
paramToCopy.contextId = static_cast<uint32_t>(contextHandle);
paramToCopy.size = sizeof(i915_context_param_engines) + sizeof(i915_engine_class_instance);
paramToCopy.param = I915_CONTEXT_PARAM_ENGINES;
paramToCopy.value = 0;
memcpy(ptrOffset(contextParamData, offset), &paramToCopy, sizeof(GemContextParam));
auto valueOffset = offsetof(GemContextParam, value);
auto *engines = ptrOffset(contextParamData, offset + valueOffset);
i915_context_param_engines enginesParam;
enginesParam.extensions = 0;
memcpy(engines, &enginesParam, sizeof(i915_context_param_engines));
auto enginesOffset = offsetof(i915_context_param_engines, engines);
auto *classInstance = ptrOffset(contextParamData, offset + valueOffset + enginesOffset);
i915_engine_class_instance ci = {drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER, 1};
memcpy(classInstance, &ci, sizeof(i915_engine_class_instance));
handler->eventQueue.push({reinterpret_cast<char *>(vmBindIsa), static_cast<uint64_t>(vmBindIsa->base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(&contextParamEvent), static_cast<uint64_t>(contextParamEvent.base.size)});
handler->eventQueue.push({reinterpret_cast<char *>(contextParamEvent2), static_cast<uint64_t>(contextParamEvent2->base.size)});
handler->pollRetVal = 1;
auto eventsCount = handler->eventQueue.size();
for (size_t i = 0; i < eventsCount; i++) {
session->handleEventsAsync();
}
EXPECT_EQ(1u, session->clientHandleToConnection[session->clientHandle]->isaMap[0].size());
EXPECT_EQ(2u, session->processPendingVmBindEventsCalled);
EXPECT_EQ(0u, session->pendingVmBindEvents.size());
}
TEST_F(DebugApiLinuxAsyncThreadTest, GivenPollReturnsNonZeroWhenReadingEventsAsyncThenEventReadIsCalledForAtMost3Times) {
zet_debug_config_t config = {};
config.pid = 0x1234;