diff --git a/level_zero/tools/source/debug/windows/debug_session.cpp b/level_zero/tools/source/debug/windows/debug_session.cpp index 7782d9f264..1a7955cd22 100644 --- a/level_zero/tools/source/debug/windows/debug_session.cpp +++ b/level_zero/tools/source/debug/windows/debug_session.cpp @@ -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(&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(allocationDataParams.DebugDataBufferPtr); +ze_result_t DebugSessionWindows::handleAllocationDataEvent(uint32_t seqNo, DBGUMD_READ_EVENT_READ_ALLOCATION_DATA_PARAMS &allocationDataParams) { + auto allocationDebugData = reinterpret_cast(&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, ®istrationData, 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(outBufSize); + escapeInfo.KmEuDbgL0EscapeInfo.ReadAdditionalAllocDataParams.OutputBufferPtr = reinterpret_cast(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: diff --git a/level_zero/tools/source/debug/windows/debug_session.h b/level_zero/tools/source/debug/windows/debug_session.h index 08a45aa379..389d695547 100644 --- a/level_zero/tools/source/debug/windows/debug_session.h +++ b/level_zero/tools/source/debug/windows/debug_session.h @@ -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; diff --git a/level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp b/level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp index fa635165b6..f8073c694c 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/windows/test_debug_api_windows.cpp @@ -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(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(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(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(&allocDebugDataInfo); + mockWddm->numEvents = 1; + mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_CONTEXT_CREATE_DESTROY; + + auto session = std::make_unique(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(&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 = ®istrationData; + mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData); + + auto session = std::make_unique(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(&mockWddm->eventQueue[2].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr); + allocDebugDataInfo->DataType = ISA; + + WddmAllocation::RegistrationData registrationData = {0x12345678, 0x1000}; + mockWddm->readAllocationDataOutParams.outData = ®istrationData; + mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData); + + auto session = std::make_unique(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(&mockWddm->eventQueue[2].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr); + allocDebugDataInfo->DataType = MODULE_HEAP_DEBUG_AREA; + + WddmAllocation::RegistrationData registrationData = {0x12345678, 0x1000}; + mockWddm->readAllocationDataOutParams.outData = ®istrationData; + mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData); auto session = std::make_unique(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(&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(&mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr); + allocDebugDataInfo->DataType = MODULE_HEAP_DEBUG_AREA; + + WddmAllocation::RegistrationData registrationData = {0x12345678, 0x1000}; + mockWddm->readAllocationDataOutParams.outData = ®istrationData; + mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData); auto session = std::make_unique(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(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(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(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(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(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(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(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(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)); diff --git a/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_tests.cpp b/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_tests.cpp index 007d00be16..a2050b20a0 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_tests.cpp @@ -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(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, ®istrationData, sizeof(registrationData))); + memoryManager.freeGraphicsMemory(wddmAlloc); + } +} + +TEST_F(MockWddmMemoryManagerWithEuDebugInterfaceTest, givenAllocateGraphicsMemoryWhenAllocationRegistrationIsNotRequiredThenAllocationIsNotRegistered) { + WddmMemoryManager memoryManager(*executionEnvironment); + + auto wddmAlloc = static_cast(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; diff --git a/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_tests.h b/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_tests.h index e318d860cf..574dc2af98 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_tests.h +++ b/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_tests.h @@ -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(wddm)); + executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->memoryOperationsInterface = std::make_unique(wddm); + } + + void TearDown() override { + executionEnvironment->decRefInternal(); + } + + HardwareInfo *hwInfo = nullptr; + WddmEuDebugInterfaceMock *wddm = nullptr; + ExecutionEnvironment *executionEnvironment = nullptr; + const uint32_t rootDeviceIndex = 0u; +}; + using OsAgnosticMemoryManagerUsingWddmTest = MockWddmMemoryManagerTest; diff --git a/shared/source/os_interface/windows/CMakeLists.txt b/shared/source/os_interface/windows/CMakeLists.txt index b231b9fba8..60c6fb09b2 100644 --- a/shared/source/os_interface/windows/CMakeLists.txt +++ b/shared/source/os_interface/windows/CMakeLists.txt @@ -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() diff --git a/shared/source/os_interface/windows/wddm_allocation.h b/shared/source/os_interface/windows/wddm_allocation.h index 8d28dc30d0..51a7fc6e8d 100644 --- a/shared/source/os_interface/windows/wddm_allocation.h +++ b/shared/source/os_interface/windows/wddm_allocation.h @@ -24,6 +24,11 @@ constexpr size_t trimListUnusedPosition = std::numeric_limits::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) {} diff --git a/shared/source/os_interface/windows/wddm_memory_manager.h b/shared/source/os_interface/windows/wddm_memory_manager.h index d7e88ac3b2..17c73b526e 100644 --- a/shared/source/os_interface/windows/wddm_memory_manager.h +++ b/shared/source/os_interface/windows/wddm_memory_manager.h @@ -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; diff --git a/shared/source/os_interface/windows/wddm_memory_manager_register_allocation.cpp b/shared/source/os_interface/windows/wddm_memory_manager_register_allocation.cpp new file mode 100644 index 0000000000..f2bb31356e --- /dev/null +++ b/shared/source/os_interface/windows/wddm_memory_manager_register_allocation.cpp @@ -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 diff --git a/shared/source/os_interface/windows/wddm_memory_manager_register_allocation_win.cpp b/shared/source/os_interface/windows/wddm_memory_manager_register_allocation_win.cpp new file mode 100644 index 0000000000..4f123ee433 --- /dev/null +++ b/shared/source/os_interface/windows/wddm_memory_manager_register_allocation_win.cpp @@ -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(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), ®istrationData); + + GFX_ALLOCATION_DEBUG_DATA_INFO allocationDebugDataInfo; + allocationDebugDataInfo.DataType = dataType; + allocationDebugDataInfo.DataSize = sizeof(registrationData); + allocationDebugDataInfo.DataPointer = reinterpret_cast(®istrationData); + + 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(&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 diff --git a/shared/test/common/mocks/windows/mock_wddm_eudebug.h b/shared/test/common/mocks/windows/mock_wddm_eudebug.h index 218345d4de..685a81c663 100644 --- a/shared/test/common/mocks/windows/mock_wddm_eudebug.h +++ b/shared/test/common/mocks/windows/mock_wddm_eudebug.h @@ -22,45 +22,83 @@ struct WddmEuDebugInterfaceMock : public WddmMock { NTSTATUS escape(D3DKMT_ESCAPE &escapeCommand) override { auto pEscapeInfo = static_cast(escapeCommand.pPrivateDriverData); + if (pEscapeInfo->EscapeOperation == KM_ESCAPE_EUDBG_UMD_REGISTER_ALLOCATION_TYPE) { + ++registerAllocationTypeCalled; + GFX_ALLOCATION_DEBUG_DATA_INFO *allocDataInfo = reinterpret_cast(pEscapeInfo->KmEuDbgUmdRegisterAllocationData.DebugDataBufferPtr); + registerAllocationTypePassedParams.allocDataSize = allocDataInfo->DataSize; + memcpy_s(registerAllocationTypePassedParams.allocData, 100, reinterpret_cast(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(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(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