feature: Implement Xe Eu debug Open and Exec Queue events

Related-To: NEO-8407

Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2024-01-18 18:39:41 +00:00
committed by Compute-Runtime-Automation
parent e949ba7144
commit b34e8646ac
8 changed files with 433 additions and 54 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2023 Intel Corporation
* Copyright (C) 2021-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -116,4 +116,9 @@ std::unique_ptr<uint64_t[]> DebugSessionLinux::getInternalEvent() {
return eventMemory;
}
void DebugSessionLinux::closeAsyncThread() {
asyncThread.close();
internalEventThread.close();
}
} // namespace L0

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 Intel Corporation
* Copyright (C) 2023-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -20,6 +20,7 @@ struct DebugSessionLinux : DebugSessionImp {
DebugSessionLinux(const zet_debug_config_t &config, Device *device, int fd) : DebugSessionImp(config, device), fd(fd){};
static ze_result_t translateDebuggerOpenErrno(int error);
bool closeFd();
void closeAsyncThread();
int fd = 0;
std::atomic<bool> internalThreadHasStarted{false};

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2023 Intel Corporation
* Copyright (C) 2022-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -322,11 +322,6 @@ void DebugSessionLinuxi915::startAsyncThread() {
asyncThread.thread = NEO::Thread::create(asyncThreadFunction, reinterpret_cast<void *>(this));
}
void DebugSessionLinuxi915::closeAsyncThread() {
asyncThread.close();
internalEventThread.close();
}
void DebugSessionLinuxi915::handleEventsAsync() {
auto eventMemory = getInternalEvent();
if (eventMemory != nullptr) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2023 Intel Corporation
* Copyright (C) 2022-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -195,7 +195,6 @@ struct DebugSessionLinuxi915 : DebugSessionLinux {
static void *asyncThreadFunction(void *arg);
void startAsyncThread() override;
void closeAsyncThread();
virtual std::vector<uint64_t> getAllMemoryHandles() {
std::vector<uint64_t> allVms;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 Intel Corporation
* Copyright (C) 2023-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -30,7 +30,7 @@ DebugSessionLinuxXe::DebugSessionLinuxXe(const zet_debug_config_t &config, Devic
};
DebugSessionLinuxXe::~DebugSessionLinuxXe() {
// closeAsyncThread();
closeAsyncThread();
closeInternalEventsThread();
closeFd();
}
@@ -83,6 +83,31 @@ ze_result_t DebugSessionLinuxXe::initialize() {
return ZE_RESULT_SUCCESS;
}
void DebugSessionLinuxXe::handleEventsAsync() {
auto eventMemory = getInternalEvent();
if (eventMemory != nullptr) {
auto debugEvent = reinterpret_cast<drm_xe_eudebug_event *>(eventMemory.get());
handleEvent(debugEvent);
}
}
void *DebugSessionLinuxXe::asyncThreadFunction(void *arg) {
DebugSessionLinuxXe *self = reinterpret_cast<DebugSessionLinuxXe *>(arg);
PRINT_DEBUGGER_INFO_LOG("Debugger async thread start\n", "");
while (self->asyncThread.threadActive) {
self->handleEventsAsync();
}
PRINT_DEBUGGER_INFO_LOG("Debugger async thread closing\n", "");
return nullptr;
}
void DebugSessionLinuxXe::startAsyncThread() {
asyncThread.thread = NEO::Thread::create(asyncThreadFunction, reinterpret_cast<void *>(this));
}
void DebugSessionLinuxXe::readInternalEventsAsync() {
struct pollfd pollFd = {
@@ -159,4 +184,60 @@ bool DebugSessionLinuxXe::closeConnection() {
return closeFd();
}
void DebugSessionLinuxXe::handleEvent(drm_xe_eudebug_event *event) {
auto type = event->type;
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type = %u flags = %u seqno = %llu len = %lu",
(uint16_t)event->type, (uint16_t)event->flags, (uint64_t)event->seqno, (uint32_t)event->len);
switch (type) {
case DRM_XE_EUDEBUG_EVENT_OPEN: {
auto clientEvent = reinterpret_cast<drm_xe_eudebug_event_client *>(event);
if (event->flags & DRM_XE_EUDEBUG_EVENT_CREATE) {
DEBUG_BREAK_IF(clientHandleToConnection.find(clientEvent->client_handle) != clientHandleToConnection.end());
clientHandleToConnection[clientEvent->client_handle].reset(new ClientConnection);
clientHandleToConnection[clientEvent->client_handle]->client = *clientEvent;
}
if (event->flags & DRM_XE_EUDEBUG_EVENT_DESTROY) {
clientHandleClosed = clientEvent->client_handle;
}
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_OPEN flags = %u len = %lu client.handle = %llu\n",
(uint16_t)event->flags, (uint32_t)event->len, (uint64_t)clientEvent->client_handle);
} break;
case DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE: {
drm_xe_eudebug_event_exec_queue *execQueue = reinterpret_cast<drm_xe_eudebug_event_exec_queue *>(event);
if (event->flags & DRM_XE_EUDEBUG_EVENT_CREATE) {
UNRECOVERABLE_IF(clientHandleToConnection.find(execQueue->client_handle) == clientHandleToConnection.end());
clientHandleToConnection[execQueue->client_handle]->execQueues[execQueue->exec_queue_handle].vmHandle = execQueue->vm_handle;
clientHandleToConnection[execQueue->client_handle]->execQueues[execQueue->exec_queue_handle].engineClass = execQueue->engine_class;
for (uint16_t idx = 0; idx < execQueue->width; idx++) {
clientHandleToConnection[execQueue->client_handle]->lrcHandleToVmHandle[execQueue->lrc_handle[idx]] = execQueue->vm_handle;
}
}
if (event->flags & DRM_XE_EUDEBUG_EVENT_DESTROY) {
for (uint16_t idx = 0; idx < execQueue->width; idx++) {
clientHandleToConnection[execQueue->client_handle]->lrcHandleToVmHandle.erase(execQueue->lrc_handle[idx]);
}
clientHandleToConnection[execQueue->client_handle]->execQueues.erase(execQueue->exec_queue_handle);
}
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE flags = %u len = %lu client_handle = %llu\
vm_handle = %llu exec_queue_handle = %llu engine_class = %u\n",
(uint16_t)event->flags, (uint32_t)event->len, (uint64_t)execQueue->client_handle, (uint64_t)execQueue->vm_handle,
(uint64_t)execQueue->exec_queue_handle, (uint16_t)execQueue->engine_class);
} break;
default:
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: UNHANDLED %u flags = %u len = %lu\n", (uint16_t)event->type, (uint16_t)event->flags, (uint32_t)event->len);
break;
}
}
} // namespace L0

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 Intel Corporation
* Copyright (C) 2023-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -42,8 +42,54 @@ struct DebugSessionLinuxXe : DebugSessionLinux {
return ZE_RESULT_SUCCESS;
}
void startAsyncThread() override {
}
struct IoctlHandlerXe : DebugSessionLinux::IoctlHandler {
int ioctl(int fd, unsigned long request, void *arg) override {
int ret = 0;
int error = 0;
bool shouldRetryIoctl = false;
do {
shouldRetryIoctl = false;
ret = NEO::SysCalls::ioctl(fd, request, arg);
error = errno;
if (ret == -1) {
shouldRetryIoctl = (error == EINTR || error == EAGAIN || error == EBUSY);
if (request == DRM_XE_EUDEBUG_IOCTL_EU_CONTROL) {
shouldRetryIoctl = (error == EINTR || error == EAGAIN);
}
}
} while (shouldRetryIoctl);
return ret;
}
};
using ContextHandle = uint64_t;
using ExecQueueHandle = uint64_t;
struct ContextParams {
ContextHandle handle = 0;
uint64_t vm = UINT64_MAX;
std::vector<drm_xe_engine_class_instance> engines;
};
struct ExecQueueParams {
uint64_t vmHandle = 0;
uint16_t engineClass = UINT16_MAX;
};
struct BindInfo {
uint64_t gpuVa = 0;
uint64_t size = 0;
};
std::unique_ptr<IoctlHandlerXe> ioctlHandler;
uint32_t xeDebuggerVersion = 0;
protected:
void startAsyncThread() override;
static void *asyncThreadFunction(void *arg);
void handleEventsAsync();
bool readModuleDebugArea() override {
UNRECOVERABLE_IF(true);
@@ -100,52 +146,18 @@ struct DebugSessionLinuxXe : DebugSessionLinux {
UNRECOVERABLE_IF(true);
}
struct IoctlHandlerXe : DebugSessionLinux::IoctlHandler {
int ioctl(int fd, unsigned long request, void *arg) override {
int ret = 0;
int error = 0;
bool shouldRetryIoctl = false;
do {
shouldRetryIoctl = false;
ret = NEO::SysCalls::ioctl(fd, request, arg);
error = errno;
if (ret == -1) {
shouldRetryIoctl = (error == EINTR || error == EAGAIN || error == EBUSY);
if (request == DRM_XE_EUDEBUG_IOCTL_EU_CONTROL) {
shouldRetryIoctl = (error == EINTR || error == EAGAIN);
}
}
} while (shouldRetryIoctl);
return ret;
}
};
using ContextHandle = uint64_t;
struct ContextParams {
ContextHandle handle = 0;
uint64_t vm = UINT64_MAX;
std::vector<drm_xe_engine_class_instance> engines;
};
struct BindInfo {
uint64_t gpuVa = 0;
uint64_t size = 0;
};
struct ClientConnection {
drm_xe_eudebug_event_client client = {};
std::unordered_map<ExecQueueHandle, ExecQueueParams> execQueues;
std::unordered_map<uint64_t, uint64_t> lrcHandleToVmHandle;
std::unordered_map<uint64_t, BindInfo> vmToModuleDebugAreaBindInfo;
};
std::vector<std::unique_ptr<uint64_t[]>> pendingVmBindEvents;
bool checkAllEventsCollected();
void handleEvent(drm_xe_eudebug_event *event);
MOCKABLE_VIRTUAL void handleEvent(drm_xe_eudebug_event *event);
void readInternalEventsAsync() override;
void pushApiEvent(zet_debug_event_t &debugEvent);
std::unique_ptr<IoctlHandlerXe> ioctlHandler;
uint32_t xeDebuggerVersion = 0;
std::unordered_map<uint64_t, std::unique_ptr<ClientConnection>> clientHandleToConnection;
std::atomic<bool> detached{false};

View File

@@ -33,6 +33,7 @@
namespace L0 {
namespace ult {
using typeOfLrcHandle = std::decay<decltype(drm_xe_eudebug_event_exec_queue::lrc_handle[0])>::type;
struct DebugApiLinuxXeFixture : public DeviceFixture {
void setUp() {
@@ -97,8 +98,17 @@ struct MockIoctlHandlerXe : public L0::DebugSessionLinuxXe::IoctlHandlerXe {
struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe {
using L0::DebugSessionImp::apiEvents;
using L0::DebugSessionLinuxXe::asyncThread;
using L0::DebugSessionLinuxXe::asyncThreadFunction;
using L0::DebugSessionLinuxXe::clientHandleClosed;
using L0::DebugSessionLinuxXe::clientHandleToConnection;
using L0::DebugSessionLinuxXe::handleEvent;
using L0::DebugSessionLinuxXe::internalEventQueue;
using L0::DebugSessionLinuxXe::internalEventThread;
using L0::DebugSessionLinuxXe::invalidClientHandle;
using L0::DebugSessionLinuxXe::readEventImp;
using L0::DebugSessionLinuxXe::readInternalEventsAsync;
using L0::DebugSessionLinuxXe::startAsyncThread;
MockDebugSessionLinuxXe(const zet_debug_config_t &config, L0::Device *device, int debugFd, void *params) : DebugSessionLinuxXe(config, device, debugFd, params) {
clientHandleToConnection[mockClientHandle].reset(new ClientConnection);
@@ -115,9 +125,35 @@ struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe {
}
return DebugSessionLinuxXe::initialize();
}
std::unique_ptr<uint64_t[]> getInternalEvent() override {
getInternalEventCounter++;
if (synchronousInternalEventRead) {
readInternalEventsAsync();
}
return DebugSessionLinuxXe::getInternalEvent();
}
bool synchronousInternalEventRead = false;
std::atomic<int> getInternalEventCounter = 0;
ze_result_t initializeRetVal = ZE_RESULT_FORCE_UINT32;
static constexpr uint64_t mockClientHandle = 1;
};
struct MockAsyncThreadDebugSessionLinuxXe : public MockDebugSessionLinuxXe {
using MockDebugSessionLinuxXe::MockDebugSessionLinuxXe;
static void *mockAsyncThreadFunction(void *arg) {
DebugSessionLinuxXe::asyncThreadFunction(arg);
reinterpret_cast<MockAsyncThreadDebugSessionLinuxXe *>(arg)->asyncThreadFinished = true;
return nullptr;
}
void startAsyncThread() override {
asyncThread.thread = NEO::Thread::create(mockAsyncThreadFunction, reinterpret_cast<void *>(this));
}
std::atomic<bool> asyncThreadFinished{false};
};
} // namespace ult
} // namespace L0

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2023 Intel Corporation
* Copyright (C) 2023-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -412,5 +412,255 @@ TEST_F(DebugApiLinuxTestXe, GivenMoreThan3EventsInQueueThenInternalEventsOnlyRea
EXPECT_EQ(static_cast<decltype(drm_xe_eudebug_event::type)>(DRM_XE_EUDEBUG_EVENT_READ), handler->debugEventInput.type);
}
TEST_F(DebugApiLinuxTestXe, GivenEventInInternalEventQueueWhenAsyncThreadFunctionIsExecutedThenEventIsHandled) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockAsyncThreadDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandleToConnection.clear();
uint8_t eventClientData[sizeof(drm_xe_eudebug_event_client)];
auto client = reinterpret_cast<drm_xe_eudebug_event_client *>(&eventClientData);
client->base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client->base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client->base.len = sizeof(drm_xe_eudebug_event_client);
client->client_handle = 0x123456789;
auto memory = std::make_unique<uint64_t[]>(sizeof(drm_xe_eudebug_event_client) / sizeof(uint64_t));
memcpy(memory.get(), client, sizeof(drm_xe_eudebug_event_client));
// Clear the event queue before using it
while (!session->internalEventQueue.empty()) {
session->internalEventQueue.pop();
}
session->internalEventQueue.push(std::move(memory));
session->startAsyncThread();
while (session->getInternalEventCounter == 0)
;
EXPECT_TRUE(session->asyncThread.threadActive);
EXPECT_FALSE(session->asyncThreadFinished);
session->closeAsyncThread();
EXPECT_FALSE(session->asyncThread.threadActive);
EXPECT_TRUE(session->asyncThreadFinished);
EXPECT_EQ(session->clientHandleToConnection.size(), 1ul);
EXPECT_NE(session->clientHandleToConnection.find(client->client_handle), session->clientHandleToConnection.end());
uint64_t wrongClientHandle = 34;
EXPECT_EQ(session->clientHandleToConnection.find(wrongClientHandle), session->clientHandleToConnection.end());
}
TEST_F(DebugApiLinuxTestXe, GivenNoEventInInternalEventQueueWhenAsyncThreadFunctionIsExecutedThenEventsAreCheckedForAvailability) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockAsyncThreadDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
// Clear the event queue before using it
while (!session->internalEventQueue.empty()) {
session->internalEventQueue.pop();
}
session->startAsyncThread();
while (session->getInternalEventCounter == 0)
;
EXPECT_TRUE(session->asyncThread.threadActive);
EXPECT_FALSE(session->asyncThreadFinished);
session->closeAsyncThread();
EXPECT_FALSE(session->asyncThread.threadActive);
EXPECT_TRUE(session->asyncThreadFinished);
}
TEST_F(DebugApiLinuxTestXe, GivenOneEuDebugOpenEventAndOneIncorrectEventWhenHandleEventThenEventsAreHandled) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = 0x123456789;
drm_xe_eudebug_event client2;
client2.type = DRM_XE_EUDEBUG_EVENT_NONE;
client2.flags = 0;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client2));
EXPECT_EQ(session->clientHandleToConnection.size(), 1ul);
EXPECT_NE(session->clientHandleToConnection.find(client1.client_handle), session->clientHandleToConnection.end());
uint64_t wrongClientHandle = 34;
EXPECT_EQ(session->clientHandleToConnection.find(wrongClientHandle), session->clientHandleToConnection.end());
}
TEST_F(DebugApiLinuxTestXe, GivenEuDebugOpenEventWithEventCreateFlagWhenHandleEventThenNewClientConnectionIsCreated) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = 0x123456789;
drm_xe_eudebug_event_client client2;
client2.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client2.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client2.client_handle = 0x123456788;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client2));
EXPECT_EQ(session->clientHandleToConnection.size(), 2ul);
EXPECT_NE(session->clientHandleToConnection.find(client1.client_handle), session->clientHandleToConnection.end());
EXPECT_NE(session->clientHandleToConnection.find(client2.client_handle), session->clientHandleToConnection.end());
uint64_t wrongClientHandle = 34;
EXPECT_EQ(session->clientHandleToConnection.find(wrongClientHandle), session->clientHandleToConnection.end());
}
TEST_F(DebugApiLinuxTestXe, GivenEuDebugOpenEventWithEventDestroyFlagWhenHandleEventThenClientConnectionIsDestroyed) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = 0x123456789;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
EXPECT_EQ(session->clientHandleToConnection.size(), 1ul);
EXPECT_NE(session->clientHandleToConnection.find(client1.client_handle), session->clientHandleToConnection.end());
drm_xe_eudebug_event_client client2;
client2.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client2.base.flags = DRM_XE_EUDEBUG_EVENT_DESTROY;
client2.client_handle = client1.client_handle;
EXPECT_EQ(session->clientHandleClosed, session->invalidClientHandle);
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client2));
EXPECT_EQ(session->clientHandleClosed, client2.client_handle);
}
TEST_F(DebugApiLinuxTestXe, GivenEuDebugExecQueueEventWithEventCreateFlagWhenHandleEventThenExecQueueIsCreated) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = 0x123456789;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
uint64_t execQueueData[sizeof(drm_xe_eudebug_event_exec_queue) / sizeof(uint64_t) + 3 * sizeof(typeOfLrcHandle)];
auto *lrcHandle = reinterpret_cast<typeOfLrcHandle *>(ptrOffset(execQueueData, sizeof(drm_xe_eudebug_event_exec_queue)));
typeOfLrcHandle lrcHandleTemp[3];
const uint64_t lrcHandle0 = 2;
const uint64_t lrcHandle1 = 3;
const uint64_t lrcHandle2 = 5;
lrcHandleTemp[0] = static_cast<typeOfLrcHandle>(lrcHandle0);
lrcHandleTemp[1] = static_cast<typeOfLrcHandle>(lrcHandle1);
lrcHandleTemp[2] = static_cast<typeOfLrcHandle>(lrcHandle2);
drm_xe_eudebug_event_exec_queue *execQueue = reinterpret_cast<drm_xe_eudebug_event_exec_queue *>(&execQueueData);
execQueue->base.type = DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE;
execQueue->base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
execQueue->client_handle = client1.client_handle;
execQueue->vm_handle = 0x1234;
execQueue->exec_queue_handle = 0x100;
execQueue->engine_class = DRM_XE_ENGINE_CLASS_COMPUTE;
execQueue->width = 3;
memcpy(lrcHandle, lrcHandleTemp, sizeof(lrcHandleTemp));
session->handleEvent(&execQueue->base);
EXPECT_NE(session->clientHandleToConnection.find(execQueue->client_handle), session->clientHandleToConnection.end());
EXPECT_EQ(session->clientHandleToConnection[execQueue->client_handle]->execQueues[execQueue->exec_queue_handle].vmHandle,
execQueue->vm_handle);
EXPECT_EQ(session->clientHandleToConnection[execQueue->client_handle]->execQueues[execQueue->exec_queue_handle].engineClass,
DRM_XE_ENGINE_CLASS_COMPUTE);
for (uint16_t idx = 0; idx < execQueue->width; idx++) {
EXPECT_EQ(session->clientHandleToConnection[execQueue->client_handle]->lrcHandleToVmHandle[execQueue->lrc_handle[idx]],
execQueue->vm_handle);
}
}
TEST_F(DebugApiLinuxTestXe, GivenEuDebugExecQueueEventWithEventDestroyFlagWhenHandleEventThenExecQueueIsDestroyed) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = 0x123456789;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
uint64_t execQueueData[sizeof(drm_xe_eudebug_event_exec_queue) / sizeof(uint64_t) + 3 * sizeof(typeOfLrcHandle)];
auto *lrcHandle = reinterpret_cast<typeOfLrcHandle *>(ptrOffset(execQueueData, sizeof(drm_xe_eudebug_event_exec_queue)));
typeOfLrcHandle lrcHandleTemp[3];
const uint64_t lrcHandle0 = 2;
const uint64_t lrcHandle1 = 3;
const uint64_t lrcHandle2 = 5;
lrcHandleTemp[0] = static_cast<typeOfLrcHandle>(lrcHandle0);
lrcHandleTemp[1] = static_cast<typeOfLrcHandle>(lrcHandle1);
lrcHandleTemp[2] = static_cast<typeOfLrcHandle>(lrcHandle2);
// ExecQueue create event handle
drm_xe_eudebug_event_exec_queue *execQueue = reinterpret_cast<drm_xe_eudebug_event_exec_queue *>(&execQueueData);
execQueue->base.type = DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE;
execQueue->base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
execQueue->client_handle = client1.client_handle;
execQueue->vm_handle = 0x1234;
execQueue->exec_queue_handle = 0x100;
execQueue->engine_class = DRM_XE_ENGINE_CLASS_COMPUTE;
execQueue->width = 3;
memcpy(lrcHandle, lrcHandleTemp, sizeof(lrcHandleTemp));
session->handleEvent(&execQueue->base);
EXPECT_NE(session->clientHandleToConnection.find(execQueue->client_handle), session->clientHandleToConnection.end());
EXPECT_EQ(session->clientHandleToConnection[execQueue->client_handle]->execQueues[execQueue->exec_queue_handle].vmHandle,
execQueue->vm_handle);
EXPECT_EQ(session->clientHandleToConnection[execQueue->client_handle]->execQueues[execQueue->exec_queue_handle].engineClass,
DRM_XE_ENGINE_CLASS_COMPUTE);
for (uint16_t idx = 0; idx < execQueue->width; idx++) {
EXPECT_EQ(session->clientHandleToConnection[execQueue->client_handle]->lrcHandleToVmHandle[execQueue->lrc_handle[idx]],
execQueue->vm_handle);
}
// ExecQueue Destroy event handle
execQueue->base.type = DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE;
execQueue->base.flags = DRM_XE_EUDEBUG_EVENT_DESTROY;
execQueue->client_handle = client1.client_handle;
execQueue->vm_handle = 0x1234;
execQueue->exec_queue_handle = 0x100;
execQueue->engine_class = DRM_XE_ENGINE_CLASS_COMPUTE;
execQueue->width = 3;
session->handleEvent(&execQueue->base);
EXPECT_TRUE(session->clientHandleToConnection[execQueue->client_handle]->execQueues.empty());
EXPECT_TRUE(session->clientHandleToConnection[execQueue->client_handle]->lrcHandleToVmHandle.empty());
}
} // namespace ult
} // namespace L0