Debugger L0 Win - register allocations metadata in debugger

Related-To: NEO-6764

Signed-off-by: Igor Venevtsev <igor.venevtsev@intel.com>
This commit is contained in:
Igor Venevtsev
2022-06-07 15:35:22 +00:00
committed by Compute-Runtime-Automation
parent 2f46a7da63
commit cb6db5672b
11 changed files with 474 additions and 54 deletions

View File

@ -44,13 +44,18 @@ ze_result_t DebugSessionWindows::initialize() {
escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.ProcessId = processId;
auto status = runEscape(escapeInfo);
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);
if (STATUS_SUCCESS != status) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: Failed - ProcessId: %d Status: 0x%llX EscapeReturnStatus: %d\n", processId, status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return DebugSessionWindows::translateNtStatusToZeResult(status);
}
if (DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: Failed - ProcessId: %d Status: 0x%llX EscapeReturnStatus: %d\n", processId, status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
}
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%llx\n", processId, debugHandle);
auto result = ZE_RESULT_SUCCESS;
do {
@ -77,7 +82,7 @@ bool DebugSessionWindows::closeConnection() {
auto status = runEscape(escapeInfo);
if (STATUS_SUCCESS != status) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_DETACH_DEBUGGER: Failed - ProcessId: %d Status: %d\n", processId, status);
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_DETACH_DEBUGGER: Failed - ProcessId: %d Status: 0x%llX\n", processId, status);
return false;
}
@ -111,6 +116,7 @@ NTSTATUS DebugSessionWindows::runEscape(KM_ESCAPE_INFO &escapeInfo) {
D3DKMT_ESCAPE escapeCommand = {0};
escapeInfo.Header.EscapeCode = GFX_ESCAPE_KMD;
escapeInfo.Header.Size = sizeof(escapeInfo) - sizeof(escapeInfo.Header);
escapeInfo.EscapeOperation = KM_ESCAPE_EUDBG_L0_DBGUMD_HANDLER;
escapeInfo.KmEuDbgL0EscapeInfo.hDebugHandle = debugHandle;
@ -140,18 +146,24 @@ ze_result_t DebugSessionWindows::readAndHandleEvent(uint64_t timeoutMs) {
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);
if (STATUS_SUCCESS != status) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_EVENT: Failed - Status: 0x%llX EscapeReturnStatus: %d\n", status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return DebugSessionWindows::translateNtStatusToZeResult(status);
}
if (DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_EVENT: Failed - Status: 0x%llX EscapeReturnStatus: %d\n", status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
}
auto seqNo = escapeInfo.KmEuDbgL0EscapeInfo.ReadEventParams.EventSeqNo;
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);
return handleAllocationDataEvent(seqNo, eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams);
case DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY:
return handleContextCreateDestroyEvent(eventParamsBuffer.eventParamsBuffer.ContextCreateDestroyEventParams);
case DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY:
@ -174,14 +186,25 @@ ze_result_t DebugSessionWindows::handleEuAttentionBitsEvent(DBGUMD_READ_EVENT_EU
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);
ze_result_t DebugSessionWindows::handleAllocationDataEvent(uint32_t seqNo, 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;
}
for (uint32_t i = 0; i < allocationDataParams.NumOfDebugData; ++i) {
auto dataType = allocationDebugData[i].DataType;
PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_READ_ALLOCATION_DATA: DataType=%d DataSize=%d DataPointer=%p\n", dataType, allocationDebugData[i].DataSize, allocationDebugData[i].DataPointer);
NEO::WddmAllocation::RegistrationData registrationData = {0};
auto result = readAllocationDebugData(seqNo, allocationDebugData[i].DataPointer, &registrationData, sizeof(registrationData));
if (result != ZE_RESULT_SUCCESS) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_ALLOCATION_DATA - Fail!\n");
return result;
}
if (allocationDebugData->DataType == MODULE_HEAP_DEBUG_AREA) {
moduleDebugAreaCaptured = true;
}
PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_READ_ALLOCATION_DATA - Success - gpuVA=0x%llX Size=0x%X\n", registrationData.gpuVirtualAddress, registrationData.size);
}
return ZE_RESULT_SUCCESS;
}
@ -202,7 +225,33 @@ ze_result_t DebugSessionWindows::handleContextCreateDestroyEvent(DBGUMD_READ_EVE
}
ze_result_t DebugSessionWindows::handleDeviceCreateDestroyEvent(DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY_EVENT_PARAMS &deviceCreateDestroyParams) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
PRINT_DEBUGGER_INFO_LOG("DEVICE_CREATE_DESTROY_EVENT: hDeviceContext=0x%llx IsCreated=%d ProcessId=%d\n",
deviceCreateDestroyParams.hDeviceContext, deviceCreateDestroyParams.IsCreated, deviceCreateDestroyParams.ProcessID);
return ZE_RESULT_SUCCESS;
}
ze_result_t DebugSessionWindows::readAllocationDebugData(uint32_t seqNo, uint64_t umdDataBufferPtr, void *outBuf, size_t outBufSize) {
KM_ESCAPE_INFO escapeInfo = {0};
escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_READ_ALLOCATION_DATA;
escapeInfo.KmEuDbgL0EscapeInfo.ReadAdditionalAllocDataParams.EventSeqNo = seqNo;
escapeInfo.KmEuDbgL0EscapeInfo.ReadAdditionalAllocDataParams.DebugDataAddr = umdDataBufferPtr;
escapeInfo.KmEuDbgL0EscapeInfo.ReadAdditionalAllocDataParams.OutputBufferSize = static_cast<uint32_t>(outBufSize);
escapeInfo.KmEuDbgL0EscapeInfo.ReadAdditionalAllocDataParams.OutputBufferPtr = reinterpret_cast<uint64_t>(outBuf);
auto status = runEscape(escapeInfo);
if (STATUS_SUCCESS != status) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_ALLOCATION_DATA: Failed - Status: 0x%llX EscapeReturnStatus: %d\n", status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return DebugSessionWindows::translateNtStatusToZeResult(status);
}
if (DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_ALLOCATION_DATA: Failed - Status: 0x%llX EscapeReturnStatus: %d\n", status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
}
return ZE_RESULT_SUCCESS;
}
ze_result_t DebugSessionWindows::handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CREATE_DEBUG_DATA_PARAMS &createDebugDataParams) {
@ -218,6 +267,19 @@ ze_result_t DebugSessionWindows::handleCreateDebugDataEvent(DBGUMD_READ_EVENT_CR
return ZE_RESULT_SUCCESS;
}
ze_result_t DebugSessionWindows::translateNtStatusToZeResult(NTSTATUS status) {
switch (status) {
case STATUS_SUCCESS:
return ZE_RESULT_SUCCESS;
case STATUS_INVALID_PARAMETER:
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
case STATUS_UNSUCCESSFUL:
return ZE_RESULT_ERROR_UNKNOWN;
default:
return ZE_RESULT_ERROR_UNKNOWN;
}
}
ze_result_t DebugSessionWindows::translateEscapeReturnStatusToZeResult(uint32_t escapeReturnStatus) {
switch (escapeReturnStatus) {
case DBGUMD_RETURN_ESCAPE_SUCCESS:

View File

@ -8,6 +8,7 @@
#pragma once
#include "shared/source/os_interface/windows/wddm/wddm.h"
#include "shared/source/os_interface/windows/wddm_allocation.h"
#include "level_zero/core/source/device/device.h"
#include "level_zero/tools/source/debug/debug_session.h"
@ -31,6 +32,7 @@ struct DebugSessionWindows : DebugSessionImp {
ze_result_t writeMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, const void *buffer) override;
ze_result_t acknowledgeEvent(const zet_debug_event_t *event) override;
static ze_result_t translateNtStatusToZeResult(NTSTATUS status);
static ze_result_t translateEscapeReturnStatusToZeResult(uint32_t escapeErrorStatus);
protected:
@ -45,10 +47,11 @@ struct DebugSessionWindows : DebugSessionImp {
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 handleAllocationDataEvent(uint32_t seqNo, 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);
ze_result_t readAllocationDebugData(uint32_t seqNo, uint64_t umdDataBufferPtr, void *outBuf, size_t outBufSize);
void enqueueApiEvent(zet_debug_event_t &debugEvent) override;
bool readSystemRoutineIdent(EuThread *thread, uint64_t vmHandle, SIP::sr_ident &srMagic) override;

View File

@ -5,6 +5,7 @@
*
*/
#include "shared/source/os_interface/windows/wddm_allocation.h"
#include "shared/test/common/mocks/windows/mock_wddm_eudebug.h"
#include "shared/test/common/test_macros/test.h"
@ -23,6 +24,7 @@ struct MockDebugSessionWindows : DebugSessionWindows {
using DebugSessionWindows::initialize;
using DebugSessionWindows::moduleDebugAreaCaptured;
using DebugSessionWindows::processId;
using DebugSessionWindows::readAllocationDebugData;
using DebugSessionWindows::readAndHandleEvent;
using DebugSessionWindows::startAsyncThread;
using DebugSessionWindows::wddm;
@ -110,12 +112,40 @@ TEST_F(DebugApiWindowsTest, givenDebugAttachAvailableAndInitializationFailedWhen
EXPECT_EQ(nullptr, debugSession);
}
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndModuleDebugAreaNotCapturedThenAttachDebuggerAndReadEventEscapesAreInvokedAndErrorNotAvailableReturned) {
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndDebugAttachNtStatusIsFailedThenErrorUnknownReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
mockWddm->ntStatus = STATUS_UNSUCCESSFUL;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize();
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, result);
EXPECT_FALSE(session->moduleDebugAreaCaptured);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
}
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndDebugAttachEscapeReturnStatusIsFailedThenErrorUnsupportedFetaureReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
mockWddm->escapeReturnStatus = DBGUMD_RETURN_EU_DEBUG_NOT_SUPPORTED;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize();
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result);
EXPECT_FALSE(session->moduleDebugAreaCaptured);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
}
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndEventQueueIsEmptyThenAttachDebuggerAndReadEventEscapesAreInvokedAndErrorNotAvailableReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
// KMD event queue is empty
mockWddm->readEventOutParams.escapeReturnStatus = DBGUMD_RETURN_READ_EVENT_TIMEOUT_EXPIRED;
mockWddm->numEvents = 0;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize();
@ -126,15 +156,88 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndModuleDebugAreaN
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
}
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndModuleDebugAreaCapturedThenAttachDebuggerAndReadEventEscapesAreInvokedAndResultSuccessReturned) {
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndEventQueueIsNotAmptyAndModuleDebugAreaIsNotCapturedThenAttachDebuggerAndReadEventEscapesAreInvokedAndErrorNotAvailableReturned) {
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);
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY;
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(2, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
}
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndEventQueueIsNotAmptyAndReadAllocationDataFailedThenAttachDebuggerAndReadEventAndReadAllocationDataEscapesAreInvokedAndResultUnknownIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
GFX_ALLOCATION_DEBUG_DATA_INFO *allocDebugDataInfo = reinterpret_cast<GFX_ALLOCATION_DEBUG_DATA_INFO *>(&mockWddm->eventQueue[2].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr);
allocDebugDataInfo->DataType = MODULE_HEAP_DEBUG_AREA;
WddmAllocation::RegistrationData registrationData = {0x12345678, 0x1000};
mockWddm->readAllocationDataOutParams.escapeReturnStatus = DBGUMD_RETURN_EU_DEBUG_NOT_SUPPORTED;
mockWddm->readAllocationDataOutParams.outData = &registrationData;
mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData);
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize();
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result);
EXPECT_FALSE(session->moduleDebugAreaCaptured);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_ALLOCATION_DATA]);
}
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndEventQueueIsNotAmptyAndReadAllocationDataSucceedAndModuleDebugAreaNotCapturedThenAttachDebuggerAndReadEventAndReadAllocationDataEscapesAreInvokedAndResultUnavailableIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
GFX_ALLOCATION_DEBUG_DATA_INFO *allocDebugDataInfo = reinterpret_cast<GFX_ALLOCATION_DEBUG_DATA_INFO *>(&mockWddm->eventQueue[2].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr);
allocDebugDataInfo->DataType = ISA;
WddmAllocation::RegistrationData registrationData = {0x12345678, 0x1000};
mockWddm->readAllocationDataOutParams.outData = &registrationData;
mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData);
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(2, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_ALLOCATION_DATA]);
}
TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndEventQueueIsNotAmptyAndModuleDebugAreaIsCapturedThenAttachDebuggerAndReadEventEscapesAreInvokedAndResultSuccessReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
mockWddm->numEvents = 3;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY;
mockWddm->eventQueue[1].readEventType = DBGUMD_READ_EVENT_DEVICE_CREATE_DESTROY;
mockWddm->eventQueue[2].readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
mockWddm->eventQueue[2].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
GFX_ALLOCATION_DEBUG_DATA_INFO *allocDebugDataInfo = reinterpret_cast<GFX_ALLOCATION_DEBUG_DATA_INFO *>(&mockWddm->eventQueue[2].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr);
allocDebugDataInfo->DataType = MODULE_HEAP_DEBUG_AREA;
WddmAllocation::RegistrationData registrationData = {0x12345678, 0x1000};
mockWddm->readAllocationDataOutParams.outData = &registrationData;
mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData);
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize();
@ -142,7 +245,8 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndModuleDebugAreaC
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_READ_EVENT]);
EXPECT_EQ(3, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_ALLOCATION_DATA]);
EXPECT_EQ(session->processId, config.pid);
EXPECT_EQ(session->debugHandle, mockWddm->debugHandle);
}
@ -159,11 +263,15 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializedAndCloseConnectionCalled
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);
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
GFX_ALLOCATION_DEBUG_DATA_INFO *allocDebugDataInfo = reinterpret_cast<GFX_ALLOCATION_DEBUG_DATA_INFO *>(&mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr);
allocDebugDataInfo->DataType = MODULE_HEAP_DEBUG_AREA;
WddmAllocation::RegistrationData registrationData = {0x12345678, 0x1000};
mockWddm->readAllocationDataOutParams.outData = &registrationData;
mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData);
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
auto result = session->initialize();
@ -171,6 +279,7 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializedAndCloseConnectionCalled
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_ALLOCATION_DATA]);
EXPECT_EQ(session->processId, config.pid);
EXPECT_EQ(session->debugHandle, mockWddm->debugHandle);
@ -178,6 +287,29 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializedAndCloseConnectionCalled
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_DETACH_DEBUGGER]);
}
TEST_F(DebugApiWindowsTest, givenNtStatusFailedWhenReadAndHandleEventCalledThenResultUnknownIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->ntStatus = STATUS_UNSUCCESSFUL;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->readAndHandleEvent(100));
}
TEST_F(DebugApiWindowsTest, givenEscapeReturnStatusFailedWhenReadAndHandleEventCalledThenResultUnsupportedFeatureIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].escapeReturnStatus = DBGUMD_RETURN_EU_DEBUG_NOT_SUPPORTED;
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, session->readAndHandleEvent(100));
}
TEST_F(DebugApiWindowsTest, givenUnsupportedEventTypeWhenReadAndHandleEventCalledThenResultUnsupportedFeatureIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
@ -185,10 +317,10 @@ TEST_F(DebugApiWindowsTest, givenUnsupportedEventTypeWhenReadAndHandleEventCalle
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_DEVICE_CREATE_DESTROY}) {
mockWddm->readEventOutParams.readEventType = unsupportedEventType;
mockWddm->numEvents = 1;
for (auto unsupportedEventType : {DBGUMD_READ_EVENT_MODULE_CREATE_NOTIFICATION, DBGUMD_READ_EVENT_EU_ATTN_BIT_SET}) {
mockWddm->curEvent = 0;
mockWddm->eventQueue[0].readEventType = unsupportedEventType;
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, session->readAndHandleEvent(100));
}
}
@ -199,10 +331,34 @@ TEST_F(DebugApiWindowsTest, givenUnknownEventTypeWhenReadAndHandleEventCalledThe
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_MAX;
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_MAX;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->readAndHandleEvent(100));
}
TEST_F(DebugApiWindowsTest, givenNtStatusFailedWhenReadAllocationDebugDataCalledThenResultUnknownIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->ntStatus = STATUS_UNSUCCESSFUL;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->readAllocationDebugData(1, 0x1234, nullptr, 0));
}
TEST_F(DebugApiWindowsTest, givenEscapeReturnStatusFailedWhenReadAllocationDebugDataCalledThenResultUnsupportedFeatureIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->readAllocationDataOutParams.escapeReturnStatus = DBGUMD_RETURN_EU_DEBUG_NOT_SUPPORTED;
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, session->readAllocationDebugData(1, 0x1234, nullptr, 0));
}
TEST_F(DebugApiWindowsTest, givenDebugDataEventTypeWhenReadAndHandleEventCalledThenResultDebugDataIsSaved) {
zet_debug_config_t config = {};
config.pid = 0x1234;
@ -210,10 +366,11 @@ TEST_F(DebugApiWindowsTest, givenDebugDataEventTypeWhenReadAndHandleEventCalledT
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_CREATE_DEBUG_DATA;
mockWddm->readEventOutParams.eventParamsBuffer.ReadCreateDebugDataParams.DebugDataType = ELF_BINARY;
mockWddm->readEventOutParams.eventParamsBuffer.ReadCreateDebugDataParams.DataBufferPtr = 0xa000;
mockWddm->readEventOutParams.eventParamsBuffer.ReadCreateDebugDataParams.DataSize = 8;
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_CREATE_DEBUG_DATA;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DebugDataType = ELF_BINARY;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DataBufferPtr = 0xa000;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadCreateDebugDataParams.DataSize = 8;
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
EXPECT_EQ(1, session->allElfs.size());
auto elf = session->allElfs[0];
@ -228,23 +385,33 @@ TEST_F(DebugApiWindowsTest, givenContextCreateEventTypeWhenReadAndHandleEventCal
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->readEventOutParams.readEventType = DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY;
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.hContextHandle = 0xa000;
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.IsCreated = 1;
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.IsSIPInstalled = 0;
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ContextCreateDestroyEventParams.hContextHandle = 0xa000;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ContextCreateDestroyEventParams.IsCreated = 1;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ContextCreateDestroyEventParams.IsSIPInstalled = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
EXPECT_EQ(0, session->allContexts.size());
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.IsSIPInstalled = 1;
mockWddm->curEvent = 0;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ContextCreateDestroyEventParams.IsSIPInstalled = 1;
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
EXPECT_EQ(1, session->allContexts.size());
EXPECT_EQ(1, session->allContexts.count(0xa000));
mockWddm->readEventOutParams.eventParamsBuffer.ContextCreateDestroyEventParams.IsCreated = 0;
mockWddm->curEvent = 0;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ContextCreateDestroyEventParams.IsCreated = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
EXPECT_EQ(0, session->allContexts.size());
}
TEST(DebugSessionWindowsTest, whenTranslateNtStatusCalledThenCorrectZeResultReturned) {
EXPECT_EQ(ZE_RESULT_SUCCESS, DebugSessionWindows::translateNtStatusToZeResult(STATUS_SUCCESS));
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, DebugSessionWindows::translateNtStatusToZeResult(STATUS_INVALID_PARAMETER));
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, DebugSessionWindows::translateNtStatusToZeResult(STATUS_UNSUCCESSFUL));
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, DebugSessionWindows::translateNtStatusToZeResult(NTSTATUS(~0)));
}
TEST(DebugSessionWindowsTest, whenTranslateEscapeErrorStatusCalledThenCorrectZeResultReturned) {
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));

View File

@ -28,6 +28,7 @@
#include "shared/test/common/mocks/mock_memory_manager.h"
#include "shared/test/common/mocks/mock_os_context.h"
#include "shared/test/common/mocks/ult_device_factory.h"
#include "shared/test/common/mocks/windows/mock_wddm_eudebug.h"
#include "shared/test/unit_test/utilities/base_object_utils.h"
#include "opencl/source/helpers/cl_memory_properties_helpers.h"
@ -2243,6 +2244,33 @@ TEST_F(MockWddmMemoryManagerTest, givenCompressedFlagSetWhenInternalIsSetThenUpd
EXPECT_EQ(expectedCallCount, mockMngr->updateAuxTableCalled);
}
TEST_F(MockWddmMemoryManagerWithEuDebugInterfaceTest, givenAllocateGraphicsMemoryWhenAllocationRegistrationIsRequiredThenAllocationIsRegistered) {
WddmMemoryManager memoryManager(*executionEnvironment);
uint32_t registerAllocationTypeCalled = 0;
for (auto allocationType : {AllocationType::DEBUG_CONTEXT_SAVE_AREA,
AllocationType::DEBUG_SBA_TRACKING_BUFFER,
AllocationType::DEBUG_MODULE_AREA}) {
auto wddmAlloc = static_cast<WddmAllocation *>(memoryManager.allocateGraphicsMemoryWithProperties(MockAllocationProperties{rootDeviceIndex, MemoryConstants::pageSize, allocationType}));
EXPECT_EQ(++registerAllocationTypeCalled, wddm->registerAllocationTypeCalled);
WddmAllocation::RegistrationData registrationData = {0};
registrationData.gpuVirtualAddress = wddmAlloc->getGpuAddress();
registrationData.size = wddmAlloc->getUnderlyingBufferSize();
EXPECT_EQ(0, memcmp(wddm->registerAllocationTypePassedParams.allocData, &registrationData, sizeof(registrationData)));
memoryManager.freeGraphicsMemory(wddmAlloc);
}
}
TEST_F(MockWddmMemoryManagerWithEuDebugInterfaceTest, givenAllocateGraphicsMemoryWhenAllocationRegistrationIsNotRequiredThenAllocationIsNotRegistered) {
WddmMemoryManager memoryManager(*executionEnvironment);
auto wddmAlloc = static_cast<WddmAllocation *>(memoryManager.allocateGraphicsMemoryWithProperties(MockAllocationProperties{rootDeviceIndex, MemoryConstants::pageSize, AllocationType::BUFFER}));
EXPECT_EQ(0, wddm->registerAllocationTypeCalled);
memoryManager.freeGraphicsMemory(wddmAlloc);
}
TEST_F(WddmMemoryManagerTest2, givenReadOnlyMemoryWhenCreateAllocationFailsThenPopulateOsHandlesReturnsInvalidPointer) {
OsHandleStorage handleStorage;
handleStorage.fragmentCount = 1;

View File

@ -16,6 +16,7 @@
#include "shared/test/common/mocks/mock_gmm_page_table_mngr.h"
#include "shared/test/common/mocks/mock_wddm_residency_allocations_container.h"
#include "shared/test/common/mocks/windows/mock_gdi_interface.h"
#include "shared/test/common/mocks/windows/mock_wddm_eudebug.h"
#include "shared/test/common/os_interface/windows/mock_wddm_memory_manager.h"
#include "shared/test/common/os_interface/windows/wddm_fixture.h"
#include "shared/test/common/test_macros/test.h"
@ -188,4 +189,26 @@ class MockWddmMemoryManagerTest : public ::testing::Test {
const uint32_t rootDeviceIndex = 0u;
};
class MockWddmMemoryManagerWithEuDebugInterfaceTest : public ::testing::Test {
public:
void SetUp() override {
executionEnvironment = getExecutionEnvironmentImpl(hwInfo, 2);
executionEnvironment->incRefInternal();
wddm = new WddmEuDebugInterfaceMock(*executionEnvironment->rootDeviceEnvironments[1].get());
wddm->callBaseDestroyAllocations = false;
wddm->callBaseMapGpuVa = false;
executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(wddm));
executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->memoryOperationsInterface = std::make_unique<WddmMemoryOperationsHandler>(wddm);
}
void TearDown() override {
executionEnvironment->decRefInternal();
}
HardwareInfo *hwInfo = nullptr;
WddmEuDebugInterfaceMock *wddm = nullptr;
ExecutionEnvironment *executionEnvironment = nullptr;
const uint32_t rootDeviceIndex = 0u;
};
using OsAgnosticMemoryManagerUsingWddmTest = MockWddmMemoryManagerTest;

View File

@ -121,6 +121,11 @@ if(NOT WIN32 AND NOT DISABLE_WDDM_LINUX)
${CMAKE_CURRENT_SOURCE_DIR}/wddm/adapter_factory_create_dxcore.cpp
${CMAKE_CURRENT_SOURCE_DIR}/trim_callback_stub.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sys_calls_wrapper_drm_or_wddm.cpp
${CMAKE_CURRENT_SOURCE_DIR}/wddm_memory_manager_register_allocation.cpp
)
else()
list(APPEND NEO_CORE_OS_INTERFACE_WDDM
${CMAKE_CURRENT_SOURCE_DIR}/wddm_memory_manager_register_allocation_win.cpp
)
endif()

View File

@ -24,6 +24,11 @@ constexpr size_t trimListUnusedPosition = std::numeric_limits<size_t>::max();
class WddmAllocation : public GraphicsAllocation {
public:
struct RegistrationData {
uint64_t gpuVirtualAddress = 0;
uint64_t size = 0;
};
WddmAllocation(uint32_t rootDeviceIndex, AllocationType allocationType, void *cpuPtrIn, uint64_t canonizedAddress, size_t sizeIn, void *reservedAddr, MemoryPool pool, uint32_t shareable, size_t maxOsContextCount)
: WddmAllocation(rootDeviceIndex, 1, allocationType, cpuPtrIn, canonizedAddress, sizeIn, reservedAddr, pool, shareable, maxOsContextCount) {}

View File

@ -79,6 +79,7 @@ class WddmMemoryManager : public MemoryManager {
bool isNTHandle(osHandle handle, uint32_t rootDeviceIndex) override;
void releaseDeviceSpecificMemResources(uint32_t rootDeviceIndex) override{};
void createDeviceSpecificMemResources(uint32_t rootDeviceIndex) override{};
void registerAllocationInOs(GraphicsAllocation *allocation) override;
protected:
GraphicsAllocation *createGraphicsAllocation(OsHandleStorage &handleStorage, const AllocationData &allocationData) override;

View File

@ -0,0 +1,14 @@
/*
* Copyright (C) 2018-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/os_interface/windows/wddm_memory_manager.h"
namespace NEO {
void WddmMemoryManager::registerAllocationInOs(GraphicsAllocation *allocation) {}
} // namespace NEO

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2018-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/os_interface/windows/wddm/wddm.h"
#include "shared/source/os_interface/windows/wddm_memory_manager.h"
#include "KmEscape.h"
namespace NEO {
void WddmMemoryManager::registerAllocationInOs(GraphicsAllocation *allocation) {
auto dataType = MAX_GFX_ALLOCATION_TYPE;
auto wddmAllocation = static_cast<WddmAllocation *>(allocation);
switch (wddmAllocation->getAllocationType()) {
case AllocationType::DEBUG_CONTEXT_SAVE_AREA:
dataType = SIP_CONTEXT_SAVE_AREA;
break;
case AllocationType::DEBUG_SBA_TRACKING_BUFFER:
dataType = SBA_BUFFER_AREA;
break;
case AllocationType::DEBUG_MODULE_AREA:
dataType = MODULE_HEAP_DEBUG_AREA;
break;
default:
break;
}
if (dataType == MAX_GFX_ALLOCATION_TYPE) {
return;
}
WddmAllocation::RegistrationData registrationData = {0};
registrationData.gpuVirtualAddress = wddmAllocation->getGpuAddress();
registrationData.size = wddmAllocation->getUnderlyingBufferSize();
PRINT_DEBUGGER_INFO_LOG("REGISTER_ALLOCATION_TYPE: gpuVA=0x%llX Size=%X DataType=%d DataSize=%d DataPointer=%p\n",
registrationData.gpuVirtualAddress, registrationData.size, dataType, sizeof(registrationData), &registrationData);
GFX_ALLOCATION_DEBUG_DATA_INFO allocationDebugDataInfo;
allocationDebugDataInfo.DataType = dataType;
allocationDebugDataInfo.DataSize = sizeof(registrationData);
allocationDebugDataInfo.DataPointer = reinterpret_cast<uint64_t>(&registrationData);
KM_ESCAPE_INFO escapeInfo;
memset(&escapeInfo, 0, sizeof(escapeInfo));
escapeInfo.Header.EscapeCode = GFX_ESCAPE_KMD;
escapeInfo.Header.Size = sizeof(escapeInfo) - sizeof(escapeInfo.Header);
escapeInfo.EscapeOperation = KM_ESCAPE_EUDBG_UMD_REGISTER_ALLOCATION_TYPE;
escapeInfo.KmEuDbgUmdRegisterAllocationData.hAllocation = wddmAllocation->getDefaultHandle();
escapeInfo.KmEuDbgUmdRegisterAllocationData.hElfAddressPtr = uint64_t(-1);
escapeInfo.KmEuDbgUmdRegisterAllocationData.NumOfDebugDataInfo = 1;
escapeInfo.KmEuDbgUmdRegisterAllocationData.DebugDataBufferPtr = reinterpret_cast<uint64_t>(&allocationDebugDataInfo);
auto &wddm = getWddm(allocation->getRootDeviceIndex());
D3DKMT_ESCAPE escapeCommand = {0};
escapeCommand.Flags.HardwareAccess = 0;
escapeCommand.Flags.Reserved = 0;
escapeCommand.hAdapter = wddm.getAdapter();
escapeCommand.hContext = (D3DKMT_HANDLE)0;
escapeCommand.hDevice = wddm.getDeviceHandle();
escapeCommand.pPrivateDriverData = &escapeInfo;
escapeCommand.PrivateDriverDataSize = sizeof(escapeInfo);
escapeCommand.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
[[maybe_unused]] auto status = wddm.escape(escapeCommand);
DEBUG_BREAK_IF(STATUS_SUCCESS != status);
}
} // namespace NEO

View File

@ -22,45 +22,83 @@ struct WddmEuDebugInterfaceMock : public WddmMock {
NTSTATUS escape(D3DKMT_ESCAPE &escapeCommand) override {
auto pEscapeInfo = static_cast<KM_ESCAPE_INFO *>(escapeCommand.pPrivateDriverData);
if (pEscapeInfo->EscapeOperation == KM_ESCAPE_EUDBG_UMD_REGISTER_ALLOCATION_TYPE) {
++registerAllocationTypeCalled;
GFX_ALLOCATION_DEBUG_DATA_INFO *allocDataInfo = reinterpret_cast<GFX_ALLOCATION_DEBUG_DATA_INFO *>(pEscapeInfo->KmEuDbgUmdRegisterAllocationData.DebugDataBufferPtr);
registerAllocationTypePassedParams.allocDataSize = allocDataInfo->DataSize;
memcpy_s(registerAllocationTypePassedParams.allocData, 100, reinterpret_cast<uint8_t *>(allocDataInfo->DataPointer), allocDataInfo->DataSize);
return ntStatus;
}
if (pEscapeInfo->EscapeOperation != KM_ESCAPE_EUDBG_L0_DBGUMD_HANDLER) {
return escapeStatus;
return ntStatus;
}
++dbgUmdEscapeActionCalled[pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeActionType];
pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = escapeReturnStatus;
switch (pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeActionType) {
case DBGUMD_ACTION_ATTACH_DEBUGGER: {
pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = DBGUMD_RETURN_ESCAPE_SUCCESS;
pEscapeInfo->KmEuDbgL0EscapeInfo.AttachDebuggerParams.hDebugHandle = debugHandle;
break;
}
case DBGUMD_ACTION_DETACH_DEBUGGER:
break;
case DBGUMD_ACTION_READ_EVENT: {
pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = readEventOutParams.escapeReturnStatus;
if (DBGUMD_RETURN_READ_EVENT_TIMEOUT_EXPIRED == pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
if (curEvent >= numEvents) {
// KMD event queue is empty
pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = DBGUMD_RETURN_READ_EVENT_TIMEOUT_EXPIRED;
break;
}
pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.ReadEventType = readEventOutParams.readEventType;
pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = eventQueue[curEvent].escapeReturnStatus;
pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.ReadEventType = eventQueue[curEvent].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));
memcpy_s(paramBuffer, pEscapeInfo->KmEuDbgL0EscapeInfo.ReadEventParams.EventParamsBufferSize, &eventQueue[curEvent].eventParamsBuffer, sizeof(READ_EVENT_PARAMS_BUFFER));
return eventQueue[curEvent++].ntStatus;
}
case DBGUMD_ACTION_READ_ALLOCATION_DATA: {
pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = readAllocationDataOutParams.escapeReturnStatus;
if (readAllocationDataOutParams.outData != nullptr) {
auto outBuffer = reinterpret_cast<uint8_t *>(pEscapeInfo->KmEuDbgL0EscapeInfo.ReadAdditionalAllocDataParams.OutputBufferPtr);
memcpy_s(outBuffer, pEscapeInfo->KmEuDbgL0EscapeInfo.ReadAdditionalAllocDataParams.OutputBufferSize, readAllocationDataOutParams.outData, readAllocationDataOutParams.outDataSize);
}
break;
}
}
return escapeStatus;
return ntStatus;
};
uint32_t numEvents = 0;
uint32_t curEvent = 0;
struct {
NTSTATUS ntStatus = STATUS_SUCCESS;
EUDBG_L0DBGUMD_ESCAPE_RETURN_TYPE escapeReturnStatus = DBGUMD_RETURN_ESCAPE_SUCCESS;
EUDBG_DBGUMD_READ_EVENT_TYPE readEventType = DBGUMD_READ_EVENT_MAX;
union {
READ_EVENT_PARAMS_BUFFER eventParamsBuffer;
uint8_t rawBytes[READ_EVENT_PARAMS_BUFFER_MIN_SIZE_BYTES] = {0};
} eventParamsBuffer;
} eventQueue[10] = {0};
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;
void *outData = nullptr;
size_t outDataSize = 0;
} readAllocationDataOutParams;
struct {
uint32_t allocDataSize = 0;
uint32_t allocData[100] = {0};
} registerAllocationTypePassedParams;
bool debugAttachAvailable = true;
NTSTATUS escapeStatus = STATUS_SUCCESS;
NTSTATUS ntStatus = STATUS_SUCCESS;
uint32_t escapeReturnStatus = DBGUMD_RETURN_ESCAPE_SUCCESS;
uint64_t debugHandle = 0x0DEB0DEB;
uint32_t dbgUmdEscapeActionCalled[DBGUMD_ACTION_MAX] = {0};
uint32_t registerAllocationTypeCalled = 0;
};
} // namespace NEO