Skip to content

Commit 481ac32

Browse files
bmyatesCompute-Runtime-Automation
authored andcommitted
Windows L0 Debugger - Implement async events handling
Add event handlers for context and debug data Signed-off-by: Yates, Brandon <[email protected]>
1 parent b3d94ad commit 481ac32

File tree

3 files changed

+152
-8
lines changed

3 files changed

+152
-8
lines changed

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

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ namespace L0 {
1111

1212
DebugSession *createDebugSessionHelper(const zet_debug_config_t &config, Device *device, int debugFd);
1313

14+
DebugSessionWindows::~DebugSessionWindows() {
15+
closeAsyncThread();
16+
}
17+
1418
DebugSession *DebugSession::create(const zet_debug_config_t &config, Device *device, ze_result_t &result) {
1519
if (!device->getOsInterface().isDebugAttachAvailable()) {
1620
result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
@@ -23,6 +27,8 @@ DebugSession *DebugSession::create(const zet_debug_config_t &config, Device *dev
2327
debugSession->closeConnection();
2428
delete debugSession;
2529
debugSession = nullptr;
30+
} else {
31+
debugSession->startAsyncThread();
2632
}
2733

2834
return debugSession;
@@ -63,6 +69,8 @@ bool DebugSessionWindows::closeConnection() {
6369
return false;
6470
}
6571

72+
closeAsyncThread();
73+
6674
KM_ESCAPE_INFO escapeInfo = {0};
6775
escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_DETACH_DEBUGGER;
6876
escapeInfo.KmEuDbgL0EscapeInfo.DetachDebuggerParams.ProcessID = processId;
@@ -77,6 +85,28 @@ bool DebugSessionWindows::closeConnection() {
7785
return true;
7886
}
7987

88+
void DebugSessionWindows::startAsyncThread() {
89+
asyncThread.thread = NEO::Thread::create(asyncThreadFunction, reinterpret_cast<void *>(this));
90+
}
91+
92+
void DebugSessionWindows::closeAsyncThread() {
93+
asyncThread.close();
94+
}
95+
96+
void *DebugSessionWindows::asyncThreadFunction(void *arg) {
97+
DebugSessionWindows *self = reinterpret_cast<DebugSessionWindows *>(arg);
98+
PRINT_DEBUGGER_INFO_LOG("Debugger async thread start\n", "");
99+
100+
while (self->asyncThread.threadActive) {
101+
self->readAndHandleEvent(100);
102+
}
103+
104+
PRINT_DEBUGGER_INFO_LOG("Debugger async thread closing\n", "");
105+
106+
self->asyncThread.threadFinished.store(true);
107+
return nullptr;
108+
}
109+
80110
NTSTATUS DebugSessionWindows::runEscape(KM_ESCAPE_INFO &escapeInfo) {
81111
D3DKMT_ESCAPE escapeCommand = {0};
82112

@@ -156,15 +186,36 @@ ze_result_t DebugSessionWindows::handleAllocationDataEvent(DBGUMD_READ_EVENT_REA
156186
}
157187

158188
ze_result_t DebugSessionWindows::handleContextCreateDestroyEvent(DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY_EVENT_PARAMS &contextCreateDestroyParams) {
159-
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
189+
PRINT_DEBUGGER_INFO_LOG("DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY_EVENT_PARAMS: hContextHandle: 0x%ullx IsCreated: %d SIPInstalled: %d\n", contextCreateDestroyParams.hContextHandle, contextCreateDestroyParams.IsCreated, contextCreateDestroyParams.IsSIPInstalled);
190+
if (!contextCreateDestroyParams.IsSIPInstalled) {
191+
return ZE_RESULT_SUCCESS;
192+
}
193+
{
194+
std::unique_lock<std::mutex> lock(asyncThreadMutex);
195+
if (contextCreateDestroyParams.IsCreated) {
196+
allContexts.insert(contextCreateDestroyParams.hContextHandle);
197+
} else {
198+
allContexts.erase(contextCreateDestroyParams.hContextHandle);
199+
}
200+
}
201+
return ZE_RESULT_SUCCESS;
160202
}
161203

162204
ze_result_t DebugSessionWindows::handleDeviceCreateDestroyEvent(DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY_EVENT_PARAMS &deviceCreateDestroyParams) {
163205
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
164206
}
165207

166208
ze_result_t DebugSessionWindows::handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CREATE_DEBUG_DATA_PARAMS &createDebugDataParams) {
167-
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
209+
PRINT_DEBUGGER_INFO_LOG("DBGUMD_READ_EVENT_CREATE_DEBUG_DATA_PARAMS:. Type: %d BufferPtr: 0x%ullx DataSize: 0x%ullx\n", createDebugDataParams.DebugDataType, createDebugDataParams.DataBufferPtr, createDebugDataParams.DataSize);
210+
std::unique_lock<std::mutex> lock(asyncThreadMutex);
211+
if (createDebugDataParams.DebugDataType == ELF_BINARY) {
212+
ElfRange elf;
213+
elf.startVA = createDebugDataParams.DataBufferPtr;
214+
elf.endVA = elf.startVA + createDebugDataParams.DataSize;
215+
allElfs.push_back(elf);
216+
}
217+
218+
return ZE_RESULT_SUCCESS;
168219
}
169220

170221
ze_result_t DebugSessionWindows::translateEscapeReturnStatusToZeResult(uint32_t escapeReturnStatus) {
@@ -229,9 +280,6 @@ bool DebugSessionWindows::readModuleDebugArea() {
229280
return false;
230281
}
231282

232-
void DebugSessionWindows::startAsyncThread() {
233-
}
234-
235283
ze_result_t DebugSessionWindows::readSbaBuffer(EuThread::ThreadId, SbaTrackedAddresses &sbaBuffer) {
236284
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
237285
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515

1616
#include "KmEscape.h"
1717

18+
#include <unordered_set>
19+
1820
namespace L0 {
1921

2022
struct DebugSessionWindows : DebugSessionImp {
2123
DebugSessionWindows(const zet_debug_config_t &config, Device *device) : DebugSessionImp(config, device), processId(config.pid) {}
24+
~DebugSessionWindows();
2225

2326
ze_result_t initialize() override;
2427
bool closeConnection() override;
@@ -51,13 +54,26 @@ struct DebugSessionWindows : DebugSessionImp {
5154
bool readSystemRoutineIdent(EuThread *thread, uint64_t vmHandle, SIP::sr_ident &srMagic) override;
5255
bool readModuleDebugArea() override;
5356
void startAsyncThread() override;
57+
void closeAsyncThread();
58+
static void *asyncThreadFunction(void *arg);
59+
60+
ThreadHelper asyncThread;
61+
std::mutex asyncThreadMutex;
5462

5563
NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo);
5664

5765
bool moduleDebugAreaCaptured = false;
5866
uint32_t processId = 0;
5967
uint64_t debugHandle = 0;
6068
NEO::Wddm *wddm = nullptr;
69+
70+
struct ElfRange {
71+
uint64_t startVA;
72+
uint64_t endVA;
73+
};
74+
75+
std::unordered_set<uint64_t> allContexts;
76+
std::vector<ElfRange> allElfs;
6177
};
6278

6379
} // namespace L0

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

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,16 @@ namespace L0 {
1515
namespace ult {
1616

1717
struct MockDebugSessionWindows : DebugSessionWindows {
18+
using DebugSessionWindows::allContexts;
19+
using DebugSessionWindows::allElfs;
20+
using DebugSessionWindows::asyncThread;
21+
using DebugSessionWindows::closeAsyncThread;
1822
using DebugSessionWindows::debugHandle;
1923
using DebugSessionWindows::initialize;
2024
using DebugSessionWindows::moduleDebugAreaCaptured;
2125
using DebugSessionWindows::processId;
2226
using DebugSessionWindows::readAndHandleEvent;
27+
using DebugSessionWindows::startAsyncThread;
2328
using DebugSessionWindows::wddm;
2429

2530
MockDebugSessionWindows(const zet_debug_config_t &config, L0::Device *device) : DebugSessionWindows(config, device) {}
@@ -40,6 +45,7 @@ struct MockDebugSessionWindows : DebugSessionWindows {
4045

4146
ze_result_t resultInitialize = ZE_RESULT_FORCE_UINT32;
4247
ze_result_t resultReadAndHandleEvent = ZE_RESULT_FORCE_UINT32;
48+
static constexpr uint64_t mockDebugHandle = 1;
4349
};
4450

4551
struct DebugApiWindowsFixture : public DeviceFixture {
@@ -181,9 +187,7 @@ TEST_F(DebugApiWindowsTest, givenUnsupportedEventTypeWhenReadAndHandleEventCalle
181187

182188
for (auto unsupportedEventType : {DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION,
183189
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}) {
190+
DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY}) {
187191
mockWddm->readEventOutParams.readEventType = unsupportedEventType;
188192
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, session->readAndHandleEvent(100));
189193
}
@@ -199,6 +203,48 @@ TEST_F(DebugApiWindowsTest, givenUnknownEventTypeWhenReadAndHandleEventCalledThe
199203
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->readAndHandleEvent(100));
200204
}
201205

206+
TEST_F(DebugApiWindowsTest, givenDebugDataEventTypeWhenReadAndHandleEventCalledThenResultDebugDataIsSaved) {
207+
zet_debug_config_t config = {};
208+
config.pid = 0x1234;
209+
210+
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
211+
session->wddm = mockWddm;
212+
213+
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_CREATE_DEBUG_DATA;
214+
mockWddm->readEventOutParams.eventParamsBuffer.ReadCreateDebugDataParams.DebugDataType = ELF_BINARY;
215+
mockWddm->readEventOutParams.eventParamsBuffer.ReadCreateDebugDataParams.DataBufferPtr = 0xa000;
216+
mockWddm->readEventOutParams.eventParamsBuffer.ReadCreateDebugDataParams.DataSize = 8;
217+
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
218+
EXPECT_EQ(1, session->allElfs.size());
219+
auto elf = session->allElfs[0];
220+
EXPECT_EQ(elf.startVA, 0xa000);
221+
EXPECT_EQ(elf.endVA, 0xa008);
222+
}
223+
224+
TEST_F(DebugApiWindowsTest, givenContextCreateEventTypeWhenReadAndHandleEventCalledThenAllContextsIsSetCorrectly) {
225+
zet_debug_config_t config = {};
226+
config.pid = 0x1234;
227+
228+
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
229+
session->wddm = mockWddm;
230+
231+
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY;
232+
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.hContextHandle = 0xa000;
233+
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.IsCreated = 1;
234+
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.IsSIPInstalled = 0;
235+
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
236+
EXPECT_EQ(0, session->allContexts.size());
237+
238+
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.IsSIPInstalled = 1;
239+
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
240+
EXPECT_EQ(1, session->allContexts.size());
241+
EXPECT_EQ(1, session->allContexts.count(0xa000));
242+
243+
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.IsCreated = 0;
244+
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
245+
EXPECT_EQ(0, session->allContexts.size());
246+
}
247+
202248
TEST(DebugSessionWindowsTest, whenTranslateEscapeErrorStatusCalledThenCorrectZeResultReturned) {
203249
EXPECT_EQ(ZE_RESULT_SUCCESS, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_ESCAPE_SUCCESS));
204250
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_DEBUGGER_ATTACH_DEVICE_BUSY));
@@ -210,5 +256,39 @@ TEST(DebugSessionWindowsTest, whenTranslateEscapeErrorStatusCalledThenCorrectZeR
210256
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_RETURN_TYPE_MAX));
211257
}
212258

259+
using DebugApiWindowsAsyncThreadTest = Test<DebugApiWindowsFixture>;
260+
261+
TEST_F(DebugApiWindowsAsyncThreadTest, GivenDebugSessionWhenStartingAndClosingAsyncThreadThenThreadIsStartedAndFinishes) {
262+
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
263+
ASSERT_NE(nullptr, session);
264+
session->wddm = mockWddm;
265+
session->startAsyncThread();
266+
267+
EXPECT_TRUE(session->asyncThread.threadActive);
268+
EXPECT_FALSE(session->asyncThread.threadFinished);
269+
270+
session->closeAsyncThread();
271+
272+
EXPECT_FALSE(session->asyncThread.threadActive);
273+
EXPECT_TRUE(session->asyncThread.threadFinished);
274+
}
275+
276+
TEST_F(DebugApiWindowsAsyncThreadTest, GivenDebugSessionWithAsyncThreadWhenClosingConnectionThenAsyncThreadIsTerminated) {
277+
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
278+
ASSERT_NE(nullptr, session);
279+
session->wddm = mockWddm;
280+
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
281+
282+
session->startAsyncThread();
283+
284+
EXPECT_TRUE(session->asyncThread.threadActive);
285+
EXPECT_FALSE(session->asyncThread.threadFinished);
286+
287+
session->closeConnection();
288+
289+
EXPECT_FALSE(session->asyncThread.threadActive);
290+
EXPECT_TRUE(session->asyncThread.threadFinished);
291+
}
292+
213293
} // namespace ult
214294
} // namespace L0

0 commit comments

Comments
 (0)