L0 Debugger Win - add initial event handling

Related-To: NEO-6723

Signed-off-by: Igor Venevtsev <igor.venevtsev@intel.com>
This commit is contained in:
Igor Venevtsev
2022-05-28 20:23:42 +00:00
committed by Compute-Runtime-Automation
parent afceaa6e19
commit dc2e1dfdb0
4 changed files with 180 additions and 4 deletions

View File

@@ -38,14 +38,24 @@ ze_result_t DebugSessionWindows::initialize() {
escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.ProcessId = processId; escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.ProcessId = processId;
auto status = runEscape(escapeInfo); auto status = runEscape(escapeInfo);
if (STATUS_SUCCESS != status) { if (STATUS_SUCCESS != status || DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: Failed - ProcessId: %d Status: %d EscapeReturnStatus: %d\n", processId, status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus); PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: Failed - ProcessId: %d Status: %d EscapeReturnStatus: %d\n", processId, status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus); return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
} }
debugHandle = escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.hDebugHandle; debugHandle = escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.hDebugHandle;
PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: SUCCESS - ProcessId: %d DebugHandle: 0x%ullx\n", processId, debugHandle); PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: SUCCESS - ProcessId: %d DebugHandle: 0x%ullx\n", processId, debugHandle);
return ZE_RESULT_SUCCESS;
auto result = ZE_RESULT_SUCCESS;
do {
result = readAndHandleEvent(100);
} while (result == ZE_RESULT_SUCCESS && !moduleDebugAreaCaptured);
if (moduleDebugAreaCaptured) {
return ZE_RESULT_SUCCESS;
}
return result;
} }
bool DebugSessionWindows::closeConnection() { bool DebugSessionWindows::closeConnection() {
@@ -86,6 +96,77 @@ NTSTATUS DebugSessionWindows::runEscape(KM_ESCAPE_INFO &escapeInfo) {
return wddm->escape(escapeCommand); return wddm->escape(escapeCommand);
} }
ze_result_t DebugSessionWindows::readAndHandleEvent(uint64_t timeoutMs) {
KM_ESCAPE_INFO escapeInfo = {0};
union {
READ_EVENT_PARAMS_BUFFER eventParamsBuffer;
uint8_t rawBytes[READ_EVENT_PARAMS_BUFFER_MIN_SIZE_BYTES] = {0};
} eventParamsBuffer;
escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_READ_EVENT;
escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.TimeoutMs = timeoutMs;
escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.EventParamsBufferSize = sizeof(eventParamsBuffer);
escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.EventParamBufferPtr = reinterpret_cast<uint64_t>(&eventParamsBuffer);
auto status = runEscape(escapeInfo);
if (STATUS_SUCCESS != status || DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_EVENT: Failed - Status: %d EscapeReturnStatus: %d\n", status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
}
switch (escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.ReadEventType) {
case DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION:
return handleModuleCreateEvent(eventParamsBuffer.eventParamsBuffer.ModuleCreateEventParams);
case DBGUMD_READ_EVENT_EU_ATTN_BIT_SET:
return handleEuAttentionBitsEvent(eventParamsBuffer.eventParamsBuffer.EuBitSetEventParams);
case DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO:
return handleAllocationDataEvent(eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams);
case DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY:
return handleContextCreateDestroyEvent(eventParamsBuffer.eventParamsBuffer.ContextCreateDestroyEventParams);
case DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY:
return handleDeviceCreateDestroyEvent(eventParamsBuffer.eventParamsBuffer.DeviceCreateDestroyEventParams);
case DBGUMD_READ_EVENT_CREATE_DEBUG_DATA:
return handleCreateDebugDataEvent(eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams);
default:
break;
}
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_EVENT: Unknown ReadEventType returned: %d\n", escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.ReadEventType);
return ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t DebugSessionWindows::handleModuleCreateEvent(DBGUMD_READ_EVENT_MODULE_CREATE_EVENT_PARAMS &moduleCreateParams) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t DebugSessionWindows::handleEuAttentionBitsEvent(DBGUMD_READ_EVENT_EU_ATTN_BIT_SET_PARAMS &euAttentionBitsParams) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t DebugSessionWindows::handleAllocationDataEvent(DBGUMD_READ_EVENT_READ_ALLOCATION_DATA_PARAMS &allocationDataParams) {
auto allocationDebugData = reinterpret_cast<GFX_ALLOCATION_DEBUG_DATA_INFO *>(allocationDataParams.DebugDataBufferPtr);
UNRECOVERABLE_IF(nullptr == allocationDebugData);
if (allocationDebugData->DataType == MODULE_HEAP_DEBUG_AREA) {
moduleDebugAreaCaptured = true;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t DebugSessionWindows::handleContextCreateDestroyEvent(DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY_EVENT_PARAMS &contextCreateDestroyParams) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t DebugSessionWindows::handleDeviceCreateDestroyEvent(DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY_EVENT_PARAMS &deviceCreateDestroyParams) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t DebugSessionWindows::handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CREATE_DEBUG_DATA_PARAMS &createDebugDataParams) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t DebugSessionWindows::translateEscapeReturnStatusToZeResult(uint32_t escapeReturnStatus) { ze_result_t DebugSessionWindows::translateEscapeReturnStatusToZeResult(uint32_t escapeReturnStatus) {
switch (escapeReturnStatus) { switch (escapeReturnStatus) {
case DBGUMD_RETURN_ESCAPE_SUCCESS: case DBGUMD_RETURN_ESCAPE_SUCCESS:

View File

@@ -39,6 +39,14 @@ struct DebugSessionWindows : DebugSessionImp {
ze_result_t readSbaBuffer(EuThread::ThreadId, SbaTrackedAddresses &sbaBuffer) override; ze_result_t readSbaBuffer(EuThread::ThreadId, SbaTrackedAddresses &sbaBuffer) override;
MOCKABLE_VIRTUAL ze_result_t readAndHandleEvent(uint64_t timeoutMs);
ze_result_t handleModuleCreateEvent(DBGUMD_READ_EVENT_MODULE_CREATE_EVENT_PARAMS &moduleCreateParams);
ze_result_t handleEuAttentionBitsEvent(DBGUMD_READ_EVENT_EU_ATTN_BIT_SET_PARAMS &euAttentionBitsParams);
ze_result_t handleAllocationDataEvent(DBGUMD_READ_EVENT_READ_ALLOCATION_DATA_PARAMS &allocationDataParams);
ze_result_t handleContextCreateDestroyEvent(DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY_EVENT_PARAMS &contextCreateDestroyParams);
ze_result_t handleDeviceCreateDestroyEvent(DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY_EVENT_PARAMS &deviceCreateDestroyParams);
ze_result_t handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CREATE_DEBUG_DATA_PARAMS &createDebugDataParams);
void enqueueApiEvent(zet_debug_event_t &debugEvent) override; void enqueueApiEvent(zet_debug_event_t &debugEvent) override;
bool readSystemRoutineIdent(EuThread *thread, uint64_t vmHandle, SIP::sr_ident &srMagic) override; bool readSystemRoutineIdent(EuThread *thread, uint64_t vmHandle, SIP::sr_ident &srMagic) override;
bool readModuleDebugArea() override; bool readModuleDebugArea() override;
@@ -46,9 +54,10 @@ struct DebugSessionWindows : DebugSessionImp {
NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo); NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo);
NEO::Wddm *wddm = nullptr; bool moduleDebugAreaCaptured = false;
uint32_t processId = 0; uint32_t processId = 0;
uint64_t debugHandle = 0; uint64_t debugHandle = 0;
NEO::Wddm *wddm = nullptr;
}; };
} // namespace L0 } // namespace L0

View File

@@ -17,7 +17,10 @@ namespace ult {
struct MockDebugSessionWindows : DebugSessionWindows { struct MockDebugSessionWindows : DebugSessionWindows {
using DebugSessionWindows::debugHandle; using DebugSessionWindows::debugHandle;
using DebugSessionWindows::initialize; using DebugSessionWindows::initialize;
using DebugSessionWindows::moduleDebugAreaCaptured;
using DebugSessionWindows::processId; using DebugSessionWindows::processId;
using DebugSessionWindows::readAndHandleEvent;
using DebugSessionWindows::wddm;
MockDebugSessionWindows(const zet_debug_config_t &config, L0::Device *device) : DebugSessionWindows(config, device) {} MockDebugSessionWindows(const zet_debug_config_t &config, L0::Device *device) : DebugSessionWindows(config, device) {}
@@ -28,7 +31,15 @@ struct MockDebugSessionWindows : DebugSessionWindows {
return DebugSessionWindows::initialize(); return DebugSessionWindows::initialize();
} }
ze_result_t readAndHandleEvent(uint64_t timeoutMs) override {
if (resultReadAndHandleEvent != ZE_RESULT_FORCE_UINT32) {
return resultReadAndHandleEvent;
}
return DebugSessionWindows::readAndHandleEvent(timeoutMs);
}
ze_result_t resultInitialize = ZE_RESULT_FORCE_UINT32; ze_result_t resultInitialize = ZE_RESULT_FORCE_UINT32;
ze_result_t resultReadAndHandleEvent = ZE_RESULT_FORCE_UINT32;
}; };
struct DebugApiWindowsFixture : public DeviceFixture { struct DebugApiWindowsFixture : public DeviceFixture {
@@ -93,15 +104,39 @@ TEST_F(DebugApiWindowsTest, givenDebugAttachAvailableAndInitializationFailedWhen
EXPECT_EQ(nullptr, debugSession); EXPECT_EQ(nullptr, debugSession);
} }
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledThenAttachDebuggerEscapeIsInvoked) { TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndModuleDebugAreaNotCapturedThenAttachDebuggerAndReadEventEscapesAreInvokedAndErrorNotAvailableReturned) {
zet_debug_config_t config = {}; zet_debug_config_t config = {};
config.pid = 0x1234; config.pid = 0x1234;
// KMD event queue is empty
mockWddm->readEventOutParams.escapeReturnStatus = DBGUMD_RETURN_READ_EVENT_TIMEOUT_EXPIRED;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize();
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
EXPECT_FALSE(session->moduleDebugAreaCaptured);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
}
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndModuleDebugAreaCapturedThenAttachDebuggerAndReadEventEscapesAreInvokedAndResultSuccessReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
GFX_ALLOCATION_DEBUG_DATA_INFO allocDebugDataInfo = {0};
allocDebugDataInfo.DataType = MODULE_HEAP_DEBUG_AREA;
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
mockWddm->readEventOutParams.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
mockWddm->readEventOutParams.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr = reinterpret_cast<uint64_t>(&allocDebugDataInfo);
auto session = std::make_unique<MockDebugSessionWindows>(config, device); auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize(); auto result = session->initialize();
EXPECT_EQ(ZE_RESULT_SUCCESS, result); EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(session->moduleDebugAreaCaptured);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]); EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
EXPECT_EQ(session->processId, config.pid); EXPECT_EQ(session->processId, config.pid);
EXPECT_EQ(session->debugHandle, mockWddm->debugHandle); EXPECT_EQ(session->debugHandle, mockWddm->debugHandle);
} }
@@ -118,11 +153,18 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializedAndCloseConnectionCalled
zet_debug_config_t config = {}; zet_debug_config_t config = {};
config.pid = 0x1234; config.pid = 0x1234;
GFX_ALLOCATION_DEBUG_DATA_INFO allocDebugDataInfo = {0};
allocDebugDataInfo.DataType = MODULE_HEAP_DEBUG_AREA;
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
mockWddm->readEventOutParams.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
mockWddm->readEventOutParams.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr = reinterpret_cast<uint64_t>(&allocDebugDataInfo);
auto session = std::make_unique<MockDebugSessionWindows>(config, device); auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize(); auto result = session->initialize();
EXPECT_EQ(ZE_RESULT_SUCCESS, result); EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]); EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
EXPECT_EQ(session->processId, config.pid); EXPECT_EQ(session->processId, config.pid);
EXPECT_EQ(session->debugHandle, mockWddm->debugHandle); EXPECT_EQ(session->debugHandle, mockWddm->debugHandle);
@@ -130,6 +172,33 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializedAndCloseConnectionCalled
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_DETACH_DEBUGGER]); EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_DETACH_DEBUGGER]);
} }
TEST_F(DebugApiWindowsTest, givenUnsupportedEventTypeWhenReadAndHandleEventCalledThenResultUnsupportedFeatureIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
for (auto unsupportedEventType : {DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION,
DBGUMD_READ_EVENT_EU_ATTN_BIT_SET,
DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY,
DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY,
DBGUMD_READ_EVENT_CREATE_DEBUG_DATA}) {
mockWddm->readEventOutParams.readEventType = unsupportedEventType;
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, session->readAndHandleEvent(100));
}
}
TEST_F(DebugApiWindowsTest, givenUnknownEventTypeWhenReadAndHandleEventCalledThenResultUnknownIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_MAX;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->readAndHandleEvent(100));
}
TEST(DebugSessionWindowsTest, whenTranslateEscapeErrorStatusCalledThenCorrectZeResultReturned) { TEST(DebugSessionWindowsTest, whenTranslateEscapeErrorStatusCalledThenCorrectZeResultReturned) {
EXPECT_EQ(ZE_RESULT_SUCCESS, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_ESCAPE_SUCCESS)); EXPECT_EQ(ZE_RESULT_SUCCESS, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_ESCAPE_SUCCESS));
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_DEBUGGER_ATTACH_DEVICE_BUSY)); EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_DEBUGGER_ATTACH_DEVICE_BUSY));

View File

@@ -36,10 +36,27 @@ struct WddmEuDebugInterfaceMock : public WddmMock {
} }
case DBGUMD_ACTION_DETACH_DEBUGGER: case DBGUMD_ACTION_DETACH_DEBUGGER:
break; break;
case DBGUMD_ACTION_READ_EVENT: {
pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = readEventOutParams.escapeReturnStatus;
if (DBGUMD_RETURN_READ_EVENT_TIMEOUT_EXPIRED == pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
// KMD event queue is empty
break;
}
pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.ReadEventType = readEventOutParams.readEventType;
auto paramBuffer = reinterpret_cast<uint8_t *>(pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.EventParamBufferPtr);
memcpy_s(paramBuffer, pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.EventParamsBufferSize, &readEventOutParams.eventParamsBuffer, sizeof(READ_EVENT_PARAMS_BUFFER));
break;
}
} }
return escapeStatus; return escapeStatus;
}; };
struct {
EUDBG_L0DBGUMD_ESCAPE_RETURN_TYPE escapeReturnStatus = DBGUMD_RETURN_ESCAPE_SUCCESS;
EUDBG_DBGUMD_READ_EVENT_TYPE readEventType = DBGUMD_READ_EVENT_MAX;
READ_EVENT_PARAMS_BUFFER eventParamsBuffer = {0};
} readEventOutParams;
bool debugAttachAvailable = true; bool debugAttachAvailable = true;
NTSTATUS escapeStatus = STATUS_SUCCESS; NTSTATUS escapeStatus = STATUS_SUCCESS;
uint64_t debugHandle = 0x0DEB0DEB; uint64_t debugHandle = 0x0DEB0DEB;