Skip to content

Commit 4a8a93a

Browse files
Debugger L0 Win - Generate Proc Entry/Exit events
Related-To: NEO-7117 Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
1 parent b450d3c commit 4a8a93a

File tree

8 files changed

+181
-6
lines changed

8 files changed

+181
-6
lines changed

level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
#include "shared/test/common/test_macros/hw_test.h"
1818

1919
#include "level_zero/core/source/device/device.h"
20+
#include "level_zero/core/test/unit_tests/mocks/mock_cmdqueue.h"
2021
#include "level_zero/core/test/unit_tests/mocks/mock_driver_handle.h"
22+
#include "level_zero/core/test/unit_tests/sources/debugger/l0_debugger_fixture.h"
2123

2224
#include <algorithm>
2325
#include <memory>
@@ -76,5 +78,25 @@ TEST_F(L0DebuggerWindowsTest, givenWindowsOSWhenL0DebuggerIsCreatedAddressModeIs
7678
EXPECT_TRUE(device->getL0Debugger()->getSingleAddressSpaceSbaTracking());
7779
}
7880

81+
HWTEST_F(L0DebuggerWindowsTest, givenDebuggingEnabledAndCommandQueuesAreCreatedAndDestroyedThanDebuggerL0IsNotified) {
82+
auto debuggerL0Hw = static_cast<MockDebuggerL0Hw<FamilyType> *>(device->getL0Debugger());
83+
84+
neoDevice->getDefaultEngine().commandStreamReceiver->getOsContext().ensureContextInitialized();
85+
86+
ze_command_queue_desc_t queueDesc = {};
87+
ze_result_t returnValue;
88+
auto commandQueue1 = CommandQueue::create(productFamily, device, neoDevice->getDefaultEngine().commandStreamReceiver, &queueDesc, false, false, returnValue);
89+
EXPECT_EQ(1u, debuggerL0Hw->commandQueueCreatedCount);
90+
91+
auto commandQueue2 = CommandQueue::create(productFamily, device, neoDevice->getDefaultEngine().commandStreamReceiver, &queueDesc, false, false, returnValue);
92+
EXPECT_EQ(2u, debuggerL0Hw->commandQueueCreatedCount);
93+
94+
commandQueue1->destroy();
95+
EXPECT_EQ(1u, debuggerL0Hw->commandQueueDestroyedCount);
96+
97+
commandQueue2->destroy();
98+
EXPECT_EQ(2u, debuggerL0Hw->commandQueueDestroyedCount);
99+
}
100+
79101
} // namespace ult
80102
} // namespace L0

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "level_zero/tools/source/debug/windows/debug_session.h"
99

1010
#include "shared/source/helpers/register_offsets.h"
11+
#include "shared/source/os_interface/windows/wddm_debug.h"
1112

1213
#include "common/StateSaveAreaHeader.h"
1314

@@ -268,12 +269,20 @@ ze_result_t DebugSessionWindows::readAllocationDebugData(uint32_t seqNo, uint64_
268269

269270
ze_result_t DebugSessionWindows::handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CREATE_DEBUG_DATA_PARAMS &createDebugDataParams) {
270271
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);
271-
std::unique_lock<std::mutex> lock(asyncThreadMutex);
272272
if (createDebugDataParams.DebugDataType == ELF_BINARY) {
273+
std::unique_lock<std::mutex> lock(asyncThreadMutex);
273274
ElfRange elf;
274275
elf.startVA = createDebugDataParams.DataBufferPtr;
275276
elf.endVA = elf.startVA + createDebugDataParams.DataSize;
276277
allElfs.push_back(elf);
278+
} else if (createDebugDataParams.DebugDataType == static_cast<uint32_t>(NEO::DebugDataType::CMD_QUEUE_CREATED)) {
279+
zet_debug_event_t debugEvent = {};
280+
debugEvent.type = ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY;
281+
pushApiEvent(debugEvent);
282+
} else if (createDebugDataParams.DebugDataType == static_cast<uint32_t>(NEO::DebugDataType::CMD_QUEUE_DESTROYED)) {
283+
zet_debug_event_t debugEvent = {};
284+
debugEvent.type = ZET_DEBUG_EVENT_TYPE_PROCESS_EXIT;
285+
pushApiEvent(debugEvent);
277286
}
278287

279288
return ZE_RESULT_SUCCESS;
@@ -311,10 +320,6 @@ ze_result_t DebugSessionWindows::translateEscapeReturnStatusToZeResult(uint32_t
311320
}
312321
}
313322

314-
ze_result_t DebugSessionWindows::readEvent(uint64_t timeout, zet_debug_event_t *event) {
315-
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
316-
}
317-
318323
ze_result_t DebugSessionWindows::readElfSpace(const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer) {
319324
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
320325
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ struct DebugSessionWindows : DebugSessionImp {
2828
ze_result_t initialize() override;
2929
bool closeConnection() override;
3030

31-
ze_result_t readEvent(uint64_t timeout, zet_debug_event_t *event) override;
3231
ze_result_t readMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer) override;
3332
ze_result_t writeMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, const void *buffer) override;
3433
ze_result_t acknowledgeEvent(const zet_debug_event_t *event) override;
@@ -38,6 +37,12 @@ struct DebugSessionWindows : DebugSessionImp {
3837

3938
protected:
4039
ze_result_t resumeImp(const std::vector<EuThread::ThreadId> &threads, uint32_t deviceIndex) override;
40+
void pushApiEvent(zet_debug_event_t &debugEvent) {
41+
std::unique_lock<std::mutex> lock(asyncThreadMutex);
42+
apiEvents.push(debugEvent);
43+
apiEventCondition.notify_all();
44+
}
45+
4146
ze_result_t interruptImp(uint32_t deviceIndex) override;
4247

4348
ze_result_t readGpuMemory(uint64_t memoryHandle, char *output, size_t size, uint64_t gpuVa) override;

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

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77

88
#include "shared/source/built_ins/sip.h"
99
#include "shared/source/os_interface/windows/wddm_allocation.h"
10+
#include "shared/source/os_interface/windows/wddm_debug.h"
1011
#include "shared/test/common/mocks/mock_sip.h"
1112
#include "shared/test/common/mocks/windows/mock_wddm_eudebug.h"
1213
#include "shared/test/common/test_macros/hw_test.h"
1314

1415
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
16+
#include "level_zero/tools/source/debug/debug_handlers.h"
1517
#include "level_zero/tools/source/debug/windows/debug_session.h"
1618

1719
#include "common/StateSaveAreaHeader.h"
@@ -45,6 +47,7 @@ struct MockDebugSessionWindows : DebugSessionWindows {
4547
using DebugSessionWindows::stateSaveAreaVA;
4648
using DebugSessionWindows::wddm;
4749
using DebugSessionWindows::writeGpuMemory;
50+
using L0::DebugSessionImp::apiEvents;
4851
using L0::DebugSessionImp::getStateSaveAreaHeader;
4952
using L0::DebugSessionImp::isValidGpuAddress;
5053

@@ -482,6 +485,79 @@ TEST_F(DebugApiWindowsTest, givenDebugDataEventTypeWhenReadAndHandleEventCalledT
482485
EXPECT_EQ(elf.endVA, 0xa008u);
483486
}
484487

488+
TEST(DebugSessionTest, GivenNullptrEventWhenReadingEventThenErrorNullptrReturned) {
489+
zet_debug_config_t config = {};
490+
config.pid = 0x1234;
491+
492+
auto session = std::make_unique<MockDebugSessionWindows>(config, nullptr);
493+
ASSERT_NE(nullptr, session);
494+
495+
auto result = session->readEvent(10, nullptr);
496+
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_NULL_POINTER, result);
497+
}
498+
499+
TEST_F(DebugApiWindowsTest, GivenMatchingDebugDataEventsForCommandQueueCreateWhenReadingEventsThenProcessEntryIsReturned) {
500+
zet_debug_config_t config = {};
501+
config.pid = 0x1234;
502+
503+
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
504+
session->wddm = mockWddm;
505+
ASSERT_NE(nullptr, session);
506+
507+
EXPECT_TRUE(session->apiEvents.empty());
508+
mockWddm->numEvents = 1;
509+
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_CREATE_DEBUG_DATA;
510+
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DebugDataType = static_cast<uint32_t>(NEO::DebugDataType::CMD_QUEUE_CREATED);
511+
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DataBufferPtr = 0xa000;
512+
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DataSize = 8;
513+
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
514+
EXPECT_EQ(session->apiEvents.size(), 1u);
515+
516+
zet_debug_event_t event = {};
517+
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
518+
ze_result_t result = zetDebugReadEvent(session->toHandle(), 0, &event);
519+
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
520+
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY, event.type);
521+
}
522+
523+
TEST_F(DebugApiWindowsTest, GivenMatchingDebugDataEventsForCommandQueueDestroyWhenReadingEventsThenProcessExitIsReturned) {
524+
zet_debug_config_t config = {};
525+
config.pid = 0x1234;
526+
527+
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
528+
session->wddm = mockWddm;
529+
ASSERT_NE(nullptr, session);
530+
531+
EXPECT_TRUE(session->apiEvents.empty());
532+
mockWddm->numEvents = 1;
533+
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_CREATE_DEBUG_DATA;
534+
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DebugDataType = static_cast<uint32_t>(NEO::DebugDataType::CMD_QUEUE_DESTROYED);
535+
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DataBufferPtr = 0xa000;
536+
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DataSize = 8;
537+
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
538+
EXPECT_EQ(session->apiEvents.size(), 1u);
539+
540+
zet_debug_event_t event = {};
541+
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
542+
ze_result_t result = zetDebugReadEvent(session->toHandle(), 0, &event);
543+
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
544+
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_PROCESS_EXIT, event.type);
545+
}
546+
547+
TEST_F(DebugApiWindowsTest, GivenNoEventsAvailableWhenReadingEventThenResultNotReadyIsReturned) {
548+
zet_debug_config_t config = {};
549+
config.pid = 0x1234;
550+
551+
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
552+
session->wddm = mockWddm;
553+
ASSERT_NE(nullptr, session);
554+
555+
zet_debug_event_t event = {};
556+
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
557+
ze_result_t result = zetDebugReadEvent(session->toHandle(), 0, &event);
558+
EXPECT_EQ(result, ZE_RESULT_NOT_READY);
559+
}
560+
485561
TEST_F(DebugApiWindowsTest, givenAllocationEventTypeForStateSaveWhenReadAndHandleEventCalledThenStateSaveIsCaptured) {
486562
zet_debug_config_t config = {};
487563
config.pid = 0x1234;

shared/source/debugger/debugger_l0.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class DebuggerL0 : public NEO::Debugger, NEO::NonCopyableOrMovableClass {
126126
std::atomic<uint32_t> commandQueueCount = 0u;
127127
uint32_t uuidL0CommandQueueHandle = 0;
128128
bool singleAddressSpaceSbaTracking = false;
129+
std::mutex debuggerL0Mutex;
129130
};
130131

131132
using DebugerL0CreateFn = DebuggerL0 *(*)(NEO::Device *device);

shared/source/debugger/windows/debugger_l0_windows.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include "shared/source/helpers/hw_helper.h"
1111
#include "shared/source/kernel/debug_data.h"
1212
#include "shared/source/os_interface/windows/wddm/wddm.h"
13+
#include "shared/source/os_interface/windows/wddm_debug.h"
14+
15+
#include "KmEscape.h"
1316

1417
namespace NEO {
1518
bool DebuggerL0::initDebuggingInOs(NEO::OSInterface *osInterface) {
@@ -39,10 +42,55 @@ bool DebuggerL0::removeZebinModule(uint32_t moduleHandle) {
3942
return false;
4043
}
4144

45+
static NTSTATUS runEscape(NEO::Wddm *wddm, KM_ESCAPE_INFO &escapeInfo) {
46+
D3DKMT_ESCAPE escapeCommand = {0};
47+
48+
escapeInfo.Header.EscapeCode = GFX_ESCAPE_KMD;
49+
escapeInfo.Header.Size = sizeof(escapeInfo) - sizeof(escapeInfo.Header);
50+
escapeInfo.EscapeOperation = KM_ESCAPE_EUDBG_UMD_CREATE_DEBUG_DATA;
51+
52+
escapeCommand.Flags.HardwareAccess = 0;
53+
escapeCommand.Flags.Reserved = 0;
54+
escapeCommand.hAdapter = wddm->getAdapter();
55+
escapeCommand.hContext = (D3DKMT_HANDLE)0;
56+
escapeCommand.hDevice = wddm->getDeviceHandle();
57+
escapeCommand.pPrivateDriverData = &escapeInfo;
58+
escapeCommand.PrivateDriverDataSize = sizeof(escapeInfo);
59+
escapeCommand.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
60+
61+
return wddm->escape(escapeCommand);
62+
}
63+
4264
void DebuggerL0::notifyCommandQueueCreated() {
65+
if (device->getRootDeviceEnvironment().osInterface.get() != nullptr) {
66+
std::unique_lock<std::mutex> commandQueueCountLock(debuggerL0Mutex);
67+
if (++commandQueueCount == 1) {
68+
auto pWddm = device->getRootDeviceEnvironment().osInterface->getDriverModel()->as<NEO::Wddm>();
69+
int val = 0;
70+
KM_ESCAPE_INFO escapeInfo = {0};
71+
escapeInfo.KmEuDbgUmdCreateDebugData.DataSize = sizeof(val);
72+
escapeInfo.KmEuDbgUmdCreateDebugData.DebugDataType = static_cast<uint32_t>(NEO::DebugDataType::CMD_QUEUE_CREATED);
73+
escapeInfo.KmEuDbgUmdCreateDebugData.hElfAddressPtr = reinterpret_cast<uint64_t>(&val);
74+
75+
runEscape(pWddm, escapeInfo);
76+
}
77+
}
4378
}
4479

4580
void DebuggerL0::notifyCommandQueueDestroyed() {
81+
if (device->getRootDeviceEnvironment().osInterface.get() != nullptr) {
82+
std::unique_lock<std::mutex> commandQueueCountLock(debuggerL0Mutex);
83+
if (--commandQueueCount == 0) {
84+
auto pWddm = device->getRootDeviceEnvironment().osInterface->getDriverModel()->as<NEO::Wddm>();
85+
int val = 0;
86+
KM_ESCAPE_INFO escapeInfo = {0};
87+
escapeInfo.KmEuDbgUmdCreateDebugData.DataSize = sizeof(val);
88+
escapeInfo.KmEuDbgUmdCreateDebugData.DebugDataType = static_cast<uint32_t>(NEO::DebugDataType::CMD_QUEUE_DESTROYED);
89+
escapeInfo.KmEuDbgUmdCreateDebugData.hElfAddressPtr = reinterpret_cast<uint64_t>(&val);
90+
91+
runEscape(pWddm, escapeInfo);
92+
}
93+
}
4694
}
4795

4896
} // namespace NEO

shared/source/os_interface/windows/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ set(NEO_CORE_OS_INTERFACE_WDDM
110110
${CMAKE_CURRENT_SOURCE_DIR}/wddm_residency_controller.cpp
111111
${CMAKE_CURRENT_SOURCE_DIR}/wddm_residency_controller.h
112112
${CMAKE_CURRENT_SOURCE_DIR}/windows_defs.h
113+
${CMAKE_CURRENT_SOURCE_DIR}/wddm_debug.h
113114
${CMAKE_CURRENT_SOURCE_DIR}/windows_wrapper.h
114115
${CMAKE_CURRENT_SOURCE_DIR}/sys_calls_wrapper.h
115116
${CMAKE_CURRENT_SOURCE_DIR}/wddm${BRANCH_DIR_SUFFIX}/init_context_private_data.cpp
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright (C) 2022 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: MIT
5+
*
6+
*/
7+
8+
#pragma once
9+
10+
#include <utility>
11+
12+
namespace NEO {
13+
enum class DebugDataType : uint32_t {
14+
CMD_QUEUE_CREATED = 0x100,
15+
CMD_QUEUE_DESTROYED
16+
};
17+
} // namespace NEO

0 commit comments

Comments
 (0)