Skip to content

Commit dc2e1df

Browse files
L0 Debugger Win - add initial event handling
Related-To: NEO-6723 Signed-off-by: Igor Venevtsev <igor.venevtsev@intel.com>
1 parent afceaa6 commit dc2e1df

File tree

4 files changed

+180
-4
lines changed

4 files changed

+180
-4
lines changed

level_zero/tools/source/debug/windows/debug_session.cpp

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,24 @@ ze_result_t DebugSessionWindows::initialize() {
3838
escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.ProcessId = processId;
3939

4040
auto status = runEscape(escapeInfo);
41-
if (STATUS_SUCCESS != status) {
41+
if (STATUS_SUCCESS != status || DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
4242
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: Failed - ProcessId: %d Status: %d EscapeReturnStatus: %d\n", processId, status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
4343
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
4444
}
4545

4646
debugHandle = escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.hDebugHandle;
4747
PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: SUCCESS - ProcessId: %d DebugHandle: 0x%ullx\n", processId, debugHandle);
48-
return ZE_RESULT_SUCCESS;
48+
49+
auto result = ZE_RESULT_SUCCESS;
50+
do {
51+
result = readAndHandleEvent(100);
52+
} while (result == ZE_RESULT_SUCCESS && !moduleDebugAreaCaptured);
53+
54+
if (moduleDebugAreaCaptured) {
55+
return ZE_RESULT_SUCCESS;
56+
}
57+
58+
return result;
4959
}
5060

5161
bool DebugSessionWindows::closeConnection() {
@@ -86,6 +96,77 @@ NTSTATUS DebugSessionWindows::runEscape(KM_ESCAPE_INFO &escapeInfo) {
8696
return wddm->escape(escapeCommand);
8797
}
8898

99+
ze_result_t DebugSessionWindows::readAndHandleEvent(uint64_t timeoutMs) {
100+
KM_ESCAPE_INFO escapeInfo = {0};
101+
102+
union {
103+
READ_EVENT_PARAMS_BUFFER eventParamsBuffer;
104+
uint8_t rawBytes[READ_EVENT_PARAMS_BUFFER_MIN_SIZE_BYTES] = {0};
105+
} eventParamsBuffer;
106+
107+
escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_READ_EVENT;
108+
escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.TimeoutMs = timeoutMs;
109+
escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.EventParamsBufferSize = sizeof(eventParamsBuffer);
110+
escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.EventParamBufferPtr = reinterpret_cast<uint64_t>(&eventParamsBuffer);
111+
112+
auto status = runEscape(escapeInfo);
113+
if (STATUS_SUCCESS != status || DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
114+
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_EVENT: Failed - Status: %d EscapeReturnStatus: %d\n", status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
115+
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
116+
}
117+
118+
switch (escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.ReadEventType) {
119+
case DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION:
120+
return handleModuleCreateEvent(eventParamsBuffer.eventParamsBuffer.ModuleCreateEventParams);
121+
case DBGUMD_READ_EVENT_EU_ATTN_BIT_SET:
122+
return handleEuAttentionBitsEvent(eventParamsBuffer.eventParamsBuffer.EuBitSetEventParams);
123+
case DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO:
124+
return handleAllocationDataEvent(eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams);
125+
case DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY:
126+
return handleContextCreateDestroyEvent(eventParamsBuffer.eventParamsBuffer.ContextCreateDestroyEventParams);
127+
case DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY:
128+
return handleDeviceCreateDestroyEvent(eventParamsBuffer.eventParamsBuffer.DeviceCreateDestroyEventParams);
129+
case DBGUMD_READ_EVENT_CREATE_DEBUG_DATA:
130+
return handleCreateDebugDataEvent(eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams);
131+
default:
132+
break;
133+
}
134+
135+
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_EVENT: Unknown ReadEventType returned: %d\n", escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.ReadEventType);
136+
return ZE_RESULT_ERROR_UNKNOWN;
137+
}
138+
139+
ze_result_t DebugSessionWindows::handleModuleCreateEvent(DBGUMD_READ_EVENT_MODULE_CREATE_EVENT_PARAMS &moduleCreateParams) {
140+
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
141+
}
142+
143+
ze_result_t DebugSessionWindows::handleEuAttentionBitsEvent(DBGUMD_READ_EVENT_EU_ATTN_BIT_SET_PARAMS &euAttentionBitsParams) {
144+
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
145+
}
146+
147+
ze_result_t DebugSessionWindows::handleAllocationDataEvent(DBGUMD_READ_EVENT_READ_ALLOCATION_DATA_PARAMS &allocationDataParams) {
148+
auto allocationDebugData = reinterpret_cast<GFX_ALLOCATION_DEBUG_DATA_INFO *>(allocationDataParams.DebugDataBufferPtr);
149+
UNRECOVERABLE_IF(nullptr == allocationDebugData);
150+
151+
if (allocationDebugData->DataType == MODULE_HEAP_DEBUG_AREA) {
152+
moduleDebugAreaCaptured = true;
153+
}
154+
155+
return ZE_RESULT_SUCCESS;
156+
}
157+
158+
ze_result_t DebugSessionWindows::handleContextCreateDestroyEvent(DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY_EVENT_PARAMS &contextCreateDestroyParams) {
159+
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
160+
}
161+
162+
ze_result_t DebugSessionWindows::handleDeviceCreateDestroyEvent(DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY_EVENT_PARAMS &deviceCreateDestroyParams) {
163+
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
164+
}
165+
166+
ze_result_t DebugSessionWindows::handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CREATE_DEBUG_DATA_PARAMS &createDebugDataParams) {
167+
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
168+
}
169+
89170
ze_result_t DebugSessionWindows::translateEscapeReturnStatusToZeResult(uint32_t escapeReturnStatus) {
90171
switch (escapeReturnStatus) {
91172
case DBGUMD_RETURN_ESCAPE_SUCCESS:

level_zero/tools/source/debug/windows/debug_session.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,25 @@ struct DebugSessionWindows : DebugSessionImp {
3939

4040
ze_result_t readSbaBuffer(EuThread::ThreadId, SbaTrackedAddresses &sbaBuffer) override;
4141

42+
MOCKABLE_VIRTUAL ze_result_t readAndHandleEvent(uint64_t timeoutMs);
43+
ze_result_t handleModuleCreateEvent(DBGUMD_READ_EVENT_MODULE_CREATE_EVENT_PARAMS &moduleCreateParams);
44+
ze_result_t handleEuAttentionBitsEvent(DBGUMD_READ_EVENT_EU_ATTN_BIT_SET_PARAMS &euAttentionBitsParams);
45+
ze_result_t handleAllocationDataEvent(DBGUMD_READ_EVENT_READ_ALLOCATION_DATA_PARAMS &allocationDataParams);
46+
ze_result_t handleContextCreateDestroyEvent(DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY_EVENT_PARAMS &contextCreateDestroyParams);
47+
ze_result_t handleDeviceCreateDestroyEvent(DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY_EVENT_PARAMS &deviceCreateDestroyParams);
48+
ze_result_t handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CREATE_DEBUG_DATA_PARAMS &createDebugDataParams);
49+
4250
void enqueueApiEvent(zet_debug_event_t &debugEvent) override;
4351
bool readSystemRoutineIdent(EuThread *thread, uint64_t vmHandle, SIP::sr_ident &srMagic) override;
4452
bool readModuleDebugArea() override;
4553
void startAsyncThread() override;
4654

4755
NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo);
4856

49-
NEO::Wddm *wddm = nullptr;
57+
bool moduleDebugAreaCaptured = false;
5058
uint32_t processId = 0;
5159
uint64_t debugHandle = 0;
60+
NEO::Wddm *wddm = nullptr;
5261
};
5362

5463
} // namespace L0

level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ namespace ult {
1717
struct MockDebugSessionWindows : DebugSessionWindows {
1818
using DebugSessionWindows::debugHandle;
1919
using DebugSessionWindows::initialize;
20+
using DebugSessionWindows::moduleDebugAreaCaptured;
2021
using DebugSessionWindows::processId;
22+
using DebugSessionWindows::readAndHandleEvent;
23+
using DebugSessionWindows::wddm;
2124

2225
MockDebugSessionWindows(const zet_debug_config_t &config, L0::Device *device) : DebugSessionWindows(config, device) {}
2326

@@ -28,7 +31,15 @@ struct MockDebugSessionWindows : DebugSessionWindows {
2831
return DebugSessionWindows::initialize();
2932
}
3033

34+
ze_result_t readAndHandleEvent(uint64_t timeoutMs) override {
35+
if (resultReadAndHandleEvent != ZE_RESULT_FORCE_UINT32) {
36+
return resultReadAndHandleEvent;
37+
}
38+
return DebugSessionWindows::readAndHandleEvent(timeoutMs);
39+
}
40+
3141
ze_result_t resultInitialize = ZE_RESULT_FORCE_UINT32;
42+
ze_result_t resultReadAndHandleEvent = ZE_RESULT_FORCE_UINT32;
3243
};
3344

3445
struct DebugApiWindowsFixture : public DeviceFixture {
@@ -93,15 +104,39 @@ TEST_F(DebugApiWindowsTest, givenDebugAttachAvailableAndInitializationFailedWhen
93104
EXPECT_EQ(nullptr, debugSession);
94105
}
95106

96-
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledThenAttachDebuggerEscapeIsInvoked) {
107+
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndModuleDebugAreaNotCapturedThenAttachDebuggerAndReadEventEscapesAreInvokedAndErrorNotAvailableReturned) {
108+
zet_debug_config_t config = {};
109+
config.pid = 0x1234;
110+
111+
// KMD event queue is empty
112+
mockWddm->readEventOutParams.escapeReturnStatus = DBGUMD_RETURN_READ_EVENT_TIMEOUT_EXPIRED;
113+
114+
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
115+
auto result = session->initialize();
116+
117+
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
118+
EXPECT_FALSE(session->moduleDebugAreaCaptured);
119+
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
120+
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
121+
}
122+
123+
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndModuleDebugAreaCapturedThenAttachDebuggerAndReadEventEscapesAreInvokedAndResultSuccessReturned) {
97124
zet_debug_config_t config = {};
98125
config.pid = 0x1234;
99126

127+
GFX_ALLOCATION_DEBUG_DATA_INFO allocDebugDataInfo = {0};
128+
allocDebugDataInfo.DataType = MODULE_HEAP_DEBUG_AREA;
129+
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
130+
mockWddm->readEventOutParams.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
131+
mockWddm->readEventOutParams.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr = reinterpret_cast<uint64_t>(&allocDebugDataInfo);
132+
100133
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
101134
auto result = session->initialize();
102135

103136
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
137+
EXPECT_TRUE(session->moduleDebugAreaCaptured);
104138
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
139+
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
105140
EXPECT_EQ(session->processId, config.pid);
106141
EXPECT_EQ(session->debugHandle, mockWddm->debugHandle);
107142
}
@@ -118,18 +153,52 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializedAndCloseConnectionCalled
118153
zet_debug_config_t config = {};
119154
config.pid = 0x1234;
120155

156+
GFX_ALLOCATION_DEBUG_DATA_INFO allocDebugDataInfo = {0};
157+
allocDebugDataInfo.DataType = MODULE_HEAP_DEBUG_AREA;
158+
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
159+
mockWddm->readEventOutParams.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
160+
mockWddm->readEventOutParams.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr = reinterpret_cast<uint64_t>(&allocDebugDataInfo);
161+
121162
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
122163
auto result = session->initialize();
123164

124165
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
125166
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
167+
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
126168
EXPECT_EQ(session->processId, config.pid);
127169
EXPECT_EQ(session->debugHandle, mockWddm->debugHandle);
128170

129171
EXPECT_TRUE(session->closeConnection());
130172
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_DETACH_DEBUGGER]);
131173
}
132174

175+
TEST_F(DebugApiWindowsTest, givenUnsupportedEventTypeWhenReadAndHandleEventCalledThenResultUnsupportedFeatureIsReturned) {
176+
zet_debug_config_t config = {};
177+
config.pid = 0x1234;
178+
179+
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
180+
session->wddm = mockWddm;
181+
182+
for (auto unsupportedEventType : {DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION,
183+
DBGUMD_READ_EVENT_EU_ATTN_BIT_SET,
184+
DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY,
185+
DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY,
186+
DBGUMD_READ_EVENT_CREATE_DEBUG_DATA}) {
187+
mockWddm->readEventOutParams.readEventType = unsupportedEventType;
188+
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, session->readAndHandleEvent(100));
189+
}
190+
}
191+
192+
TEST_F(DebugApiWindowsTest, givenUnknownEventTypeWhenReadAndHandleEventCalledThenResultUnknownIsReturned) {
193+
zet_debug_config_t config = {};
194+
config.pid = 0x1234;
195+
196+
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
197+
session->wddm = mockWddm;
198+
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_MAX;
199+
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->readAndHandleEvent(100));
200+
}
201+
133202
TEST(DebugSessionWindowsTest, whenTranslateEscapeErrorStatusCalledThenCorrectZeResultReturned) {
134203
EXPECT_EQ(ZE_RESULT_SUCCESS, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_ESCAPE_SUCCESS));
135204
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_DEBUGGER_ATTACH_DEVICE_BUSY));

shared/test/common/mocks/windows/mock_wddm_eudebug.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,27 @@ struct WddmEuDebugInterfaceMock : public WddmMock {
3636
}
3737
case DBGUMD_ACTION_DETACH_DEBUGGER:
3838
break;
39+
case DBGUMD_ACTION_READ_EVENT: {
40+
pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = readEventOutParams.escapeReturnStatus;
41+
if (DBGUMD_RETURN_READ_EVENT_TIMEOUT_EXPIRED == pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
42+
// KMD event queue is empty
43+
break;
44+
}
45+
pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.ReadEventType = readEventOutParams.readEventType;
46+
auto paramBuffer = reinterpret_cast<uint8_t *>(pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.EventParamBufferPtr);
47+
memcpy_s(paramBuffer, pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.EventParamsBufferSize, &readEventOutParams.eventParamsBuffer, sizeof(READ_EVENT_PARAMS_BUFFER));
48+
break;
49+
}
3950
}
4051
return escapeStatus;
4152
};
4253

54+
struct {
55+
EUDBG_L0DBGUMD_ESCAPE_RETURN_TYPE escapeReturnStatus = DBGUMD_RETURN_ESCAPE_SUCCESS;
56+
EUDBG_DBGUMD_READ_EVENT_TYPE readEventType = DBGUMD_READ_EVENT_MAX;
57+
READ_EVENT_PARAMS_BUFFER eventParamsBuffer = {0};
58+
} readEventOutParams;
59+
4360
bool debugAttachAvailable = true;
4461
NTSTATUS escapeStatus = STATUS_SUCCESS;
4562
uint64_t debugHandle = 0x0DEB0DEB;

0 commit comments

Comments
 (0)