From f45431c173ff2ed5f922106917a1da35c5f91164 Mon Sep 17 00:00:00 2001 From: Igor Venevtsev Date: Thu, 12 May 2022 13:36:35 +0000 Subject: [PATCH] L0 Debugger Windows - implement debugger attach/detach Related-To: NEO-6718 Signed-off-by: Igor Venevtsev --- .../core/source/dll/windows/CMakeLists.txt | 3 +- .../tools/source/debug/windows/CMakeLists.txt | 1 + .../source/debug/windows/debug_session.cpp | 150 +++++++++++++++++- .../source/debug/windows/debug_session.h | 54 +++++++ .../windows/debug_session_windows_helper.cpp | 16 ++ .../debug/windows/test_debug_api_windows.cpp | 133 +++++++++++++++- .../os_interface/windows/os_interface_win.cpp | 4 + .../source/os_interface/windows/wddm/wddm.cpp | 4 + .../source/os_interface/windows/wddm/wddm.h | 3 +- .../os_interface/windows/wddm_tests.cpp | 5 + 10 files changed, 363 insertions(+), 10 deletions(-) create mode 100644 level_zero/tools/source/debug/windows/debug_session.h create mode 100644 level_zero/tools/source/debug/windows/debug_session_windows_helper.cpp diff --git a/level_zero/core/source/dll/windows/CMakeLists.txt b/level_zero/core/source/dll/windows/CMakeLists.txt index 06405d563c..7130e200a9 100644 --- a/level_zero/core/source/dll/windows/CMakeLists.txt +++ b/level_zero/core/source/dll/windows/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2020 Intel Corporation +# Copyright (C) 2020-2022 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -7,6 +7,7 @@ set(L0_SRCS_DLL_WINDOWS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/debugger_l0_windows.cpp + ${NEO_SOURCE_DIR}/level_zero/tools/source/debug/windows/debug_session_windows_helper.cpp ) set_property(GLOBAL PROPERTY L0_SRCS_DLL_WINDOWS ${L0_SRCS_DLL_WINDOWS}) diff --git a/level_zero/tools/source/debug/windows/CMakeLists.txt b/level_zero/tools/source/debug/windows/CMakeLists.txt index 2a081ff192..971dc28d3b 100644 --- a/level_zero/tools/source/debug/windows/CMakeLists.txt +++ b/level_zero/tools/source/debug/windows/CMakeLists.txt @@ -8,6 +8,7 @@ if(WIN32) target_sources(${L0_STATIC_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/debug_session.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/debug_session.h ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ) endif() diff --git a/level_zero/tools/source/debug/windows/debug_session.cpp b/level_zero/tools/source/debug/windows/debug_session.cpp index 1b61258f46..c40faf6235 100644 --- a/level_zero/tools/source/debug/windows/debug_session.cpp +++ b/level_zero/tools/source/debug/windows/debug_session.cpp @@ -5,14 +5,154 @@ * */ -#include "level_zero/tools/source/debug/debug_session.h" - -#include "level_zero/core/source/device/device.h" +#include "level_zero/tools/source/debug/windows/debug_session.h" namespace L0 { +DebugSession *createDebugSessionHelper(const zet_debug_config_t &config, Device *device, int debugFd); + DebugSession *DebugSession::create(const zet_debug_config_t &config, Device *device, ze_result_t &result) { - result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; - return nullptr; + if (!device->getOsInterface().isDebugAttachAvailable()) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + return nullptr; + } + + auto debugSession = createDebugSessionHelper(config, device, 0); + result = debugSession->initialize(); + if (result != ZE_RESULT_SUCCESS) { + debugSession->closeConnection(); + delete debugSession; + debugSession = nullptr; + } + + return debugSession; } + +ze_result_t DebugSessionWindows::initialize() { + wddm = connectedDevice->getOsInterface().getDriverModel()->as(); + UNRECOVERABLE_IF(wddm == nullptr); + + KM_ESCAPE_INFO escapeInfo = {0}; + escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_ATTACH_DEBUGGER; + escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.hAdapter = wddm->getAdapter(); + escapeInfo.KmEuDbgL0EscapeInfo.AttachDebuggerParams.ProcessId = processId; + + auto status = runEscape(escapeInfo); + if (STATUS_SUCCESS != status) { + PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: Failed - ProcessId: %d Status: %d 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); + return ZE_RESULT_SUCCESS; +} + +bool DebugSessionWindows::closeConnection() { + if (debugHandle == 0) { + return false; + } + + KM_ESCAPE_INFO escapeInfo = {0}; + escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_DETACH_DEBUGGER; + escapeInfo.KmEuDbgL0EscapeInfo.DetachDebuggerParams.ProcessID = processId; + + auto status = runEscape(escapeInfo); + if (STATUS_SUCCESS != status) { + PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_DETACH_DEBUGGER: Failed - ProcessId: %d Status: %d\n", processId, status); + return false; + } + + PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_DETACH_DEBUGGER: SUCCESS\n"); + return true; +} + +NTSTATUS DebugSessionWindows::runEscape(KM_ESCAPE_INFO &escapeInfo) { + D3DKMT_ESCAPE escapeCommand = {0}; + + escapeInfo.Header.EscapeCode = GFX_ESCAPE_KMD; + escapeInfo.EscapeOperation = KM_ESCAPE_EUDBG_L0_DBGUMD_HANDLER; + escapeInfo.KmEuDbgL0EscapeInfo.hDebugHandle = debugHandle; + + 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; + + return wddm->escape(escapeCommand); +} + +ze_result_t DebugSessionWindows::translateEscapeReturnStatusToZeResult(uint32_t escapeReturnStatus) { + switch (escapeReturnStatus) { + case DBGUMD_ACTION_ESCAPE_SUCCESS: + return ZE_RESULT_SUCCESS; + case DBGUMD_ACTION_DEBUGGER_ATTACH_DEVICE_BUSY: + case DBGUMD_ACTION_READ_EVENT_TIMEOUT_EXPIRED: + return ZE_RESULT_ERROR_NOT_AVAILABLE; + case DBGUMD_ACTION_INVALID_ARGS: + case DBGUMD_ACTION_NOT_VALID_PROCESS: + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + case DBGUMD_ACTION_PERMISSION_DENIED: + return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; + case DBGUMD_ACTION_EU_DEBUG_NOT_SUPPORTED: + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + default: + return ZE_RESULT_ERROR_UNKNOWN; + } +} + +ze_result_t DebugSessionWindows::readEvent(uint64_t timeout, zet_debug_event_t *event) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t DebugSessionWindows::readMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t DebugSessionWindows::writeMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, const void *buffer) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t DebugSessionWindows::acknowledgeEvent(const zet_debug_event_t *event) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t DebugSessionWindows::resumeImp(std::vector threads, uint32_t deviceIndex) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t DebugSessionWindows::interruptImp(uint32_t deviceIndex) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t DebugSessionWindows::readGpuMemory(uint64_t memoryHandle, char *output, size_t size, uint64_t gpuVa) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t DebugSessionWindows::writeGpuMemory(uint64_t memoryHandle, const char *input, size_t size, uint64_t gpuVa) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +void DebugSessionWindows::enqueueApiEvent(zet_debug_event_t &debugEvent) { +} + +bool DebugSessionWindows::readSystemRoutineIdent(EuThread *thread, uint64_t vmHandle, SIP::sr_ident &srMagic) { + return false; +} + +bool DebugSessionWindows::readModuleDebugArea() { + return false; +} + +void DebugSessionWindows::startAsyncThread() { +} + +ze_result_t DebugSessionWindows::readSbaBuffer(EuThread::ThreadId, SbaTrackedAddresses &sbaBuffer) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + } // namespace L0 diff --git a/level_zero/tools/source/debug/windows/debug_session.h b/level_zero/tools/source/debug/windows/debug_session.h new file mode 100644 index 0000000000..3d9ca2723a --- /dev/null +++ b/level_zero/tools/source/debug/windows/debug_session.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/source/os_interface/windows/wddm/wddm.h" + +#include "level_zero/core/source/device/device.h" +#include "level_zero/tools/source/debug/debug_session.h" +#include "level_zero/tools/source/debug/debug_session_imp.h" + +#include "KmEscape.h" + +namespace L0 { + +struct DebugSessionWindows : DebugSessionImp { + DebugSessionWindows(const zet_debug_config_t &config, Device *device) : DebugSessionImp(config, device), processId(config.pid) {} + + ze_result_t initialize() override; + bool closeConnection() override; + + ze_result_t readEvent(uint64_t timeout, zet_debug_event_t *event) override; + ze_result_t readMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer) override; + 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 translateEscapeReturnStatusToZeResult(uint32_t escapeErrorStatus); + + protected: + ze_result_t resumeImp(std::vector threads, uint32_t deviceIndex) override; + ze_result_t interruptImp(uint32_t deviceIndex) override; + + ze_result_t readGpuMemory(uint64_t memoryHandle, char *output, size_t size, uint64_t gpuVa) override; + ze_result_t writeGpuMemory(uint64_t memoryHandle, const char *input, size_t size, uint64_t gpuVa) override; + + ze_result_t readSbaBuffer(EuThread::ThreadId, SbaTrackedAddresses &sbaBuffer) override; + + void enqueueApiEvent(zet_debug_event_t &debugEvent) override; + bool readSystemRoutineIdent(EuThread *thread, uint64_t vmHandle, SIP::sr_ident &srMagic) override; + bool readModuleDebugArea() override; + void startAsyncThread() override; + + NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo); + + NEO::Wddm *wddm = nullptr; + uint32_t processId = 0; + uint64_t debugHandle = 0; +}; + +} // namespace L0 diff --git a/level_zero/tools/source/debug/windows/debug_session_windows_helper.cpp b/level_zero/tools/source/debug/windows/debug_session_windows_helper.cpp new file mode 100644 index 0000000000..e668b43398 --- /dev/null +++ b/level_zero/tools/source/debug/windows/debug_session_windows_helper.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/tools/source/debug/windows/debug_session.h" +#include +namespace L0 { + +DebugSession *createDebugSessionHelper(const zet_debug_config_t &config, Device *device, int debugFd) { + return new DebugSessionWindows(config, device); +} + +} // namespace L0 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 bb5a674fec..e1699e0ea8 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,47 +5,174 @@ * */ +#include "shared/test/common/mocks/mock_wddm.h" #include "shared/test/common/test_macros/test.h" #include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" +#include "level_zero/tools/source/debug/windows/debug_session.h" namespace L0 { namespace ult { +struct WddmEuDebugInterfaceMock : public WddmMock { + WddmEuDebugInterfaceMock(RootDeviceEnvironment &rootDeviceEnvironment) : WddmMock(rootDeviceEnvironment) {} + + bool isDebugAttachAvailable() override { + return debugAttachAvailable; + } + + NTSTATUS escape(D3DKMT_ESCAPE &escapeCommand) override { + auto pEscapeInfo = static_cast(escapeCommand.pPrivateDriverData); + if (pEscapeInfo->EscapeOperation != KM_ESCAPE_EUDBG_L0_DBGUMD_HANDLER) { + return escapeStatus; + } + + ++dbgUmdEscapeActionCalled[pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeActionType]; + + switch (pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeActionType) { + case DBGUMD_ACTION_ATTACH_DEBUGGER: { + pEscapeInfo->KmEuDbgL0EscapeInfo.EscapeReturnStatus = DBGUMD_ACTION_ESCAPE_SUCCESS; + pEscapeInfo->KmEuDbgL0EscapeInfo.AttachDebuggerParams.hDebugHandle = debugHandle; + break; + } + case DBGUMD_ACTION_DETACH_DEBUGGER: + break; + } + return escapeStatus; + }; + + bool debugAttachAvailable = true; + NTSTATUS escapeStatus = STATUS_SUCCESS; + uint64_t debugHandle = 0x0DEB0DEB; + uint32_t dbgUmdEscapeActionCalled[DBGUMD_ACTION_MAX] = {0}; +}; + +struct MockDebugSessionWindows : DebugSessionWindows { + using DebugSessionWindows::debugHandle; + using DebugSessionWindows::initialize; + using DebugSessionWindows::processId; + + MockDebugSessionWindows(const zet_debug_config_t &config, L0::Device *device) : DebugSessionWindows(config, device) {} + + ze_result_t initialize() override { + if (resultInitialize != ZE_RESULT_FORCE_UINT32) { + return resultInitialize; + } + return DebugSessionWindows::initialize(); + } + + ze_result_t resultInitialize = ZE_RESULT_FORCE_UINT32; +}; + struct DebugApiWindowsFixture : public DeviceFixture { void SetUp() { DeviceFixture::SetUp(); + mockWddm = new WddmEuDebugInterfaceMock(*neoDevice->executionEnvironment->rootDeviceEnvironments[0]); neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new NEO::OSInterface); + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(mockWddm)); } void TearDown() { DeviceFixture::TearDown(); } + + WddmEuDebugInterfaceMock *mockWddm = nullptr; }; -using DebugApiWinTest = Test; +using DebugApiWindowsTest = Test; -TEST_F(DebugApiWinTest, givenDeviceWhenGettingDebugPropertiesThanNoFlagIsSet) { +TEST_F(DebugApiWindowsTest, givenDebugAttachIsNotAvailableWhenGetDebugPropertiesCalledThenNoFlagIsReturned) { zet_device_debug_properties_t debugProperties = {}; debugProperties.flags = ZET_DEVICE_DEBUG_PROPERTY_FLAG_FORCE_UINT32; + mockWddm->debugAttachAvailable = false; auto result = zetDeviceGetDebugProperties(device->toHandle(), &debugProperties); EXPECT_EQ(ZE_RESULT_SUCCESS, result); EXPECT_EQ(0u, debugProperties.flags); } -TEST_F(DebugApiWinTest, givenDeviceWhenCallingDebugAttachThenErrorIsReturned) { +using isDebugSupportedProduct = IsWithinProducts; +HWTEST2_F(DebugApiWindowsTest, givenDebugAttachAvailableWhenGetDebugPropertiesCalledThenCorrectFlagIsReturned, isDebugSupportedProduct) { + zet_device_debug_properties_t debugProperties = {}; + debugProperties.flags = ZET_DEVICE_DEBUG_PROPERTY_FLAG_FORCE_UINT32; + auto result = zetDeviceGetDebugProperties(device->toHandle(), &debugProperties); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(ZET_DEVICE_DEBUG_PROPERTY_FLAG_ATTACH, debugProperties.flags); +} + +TEST_F(DebugApiWindowsTest, givenDebugAttachIsNotAvailableWhenDebugSessionCreatedThenNullptrAndResultUnsupportedFeatureAreReturned) { zet_debug_config_t config = {}; config.pid = 0x1234; zet_debug_session_handle_t debugSession = nullptr; + mockWddm->debugAttachAvailable = false; auto result = zetDebugAttach(device->toHandle(), &config, &debugSession); EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); EXPECT_EQ(nullptr, debugSession); } +TEST_F(DebugApiWindowsTest, givenDebugAttachAvailableAndInitializationFailedWhenDebugSessionCreatedThenNullptrAndErrorStatusAreReturned) { + zet_debug_config_t config = {}; + config.pid = 0x0; // debugSession->initialize() will fail + + zet_debug_session_handle_t debugSession = nullptr; + auto result = zetDebugAttach(device->toHandle(), &config, &debugSession); + + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, result); + EXPECT_EQ(nullptr, debugSession); +} + +TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledThenAttachDebuggerEscapeIsInvoked) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device); + auto result = session->initialize(); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]); + EXPECT_EQ(session->processId, config.pid); + EXPECT_EQ(session->debugHandle, mockWddm->debugHandle); +} + +TEST_F(DebugApiWindowsTest, givenDebugSessionCloseConnectionCalledWithoutInitializationThenFalseIsReturned) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device); + EXPECT_FALSE(session->closeConnection()); +} + +TEST_F(DebugApiWindowsTest, givenDebugSessionInitializedAndCloseConnectionCalledThenDebuggerDetachEscapeIsInvoked) { + zet_debug_config_t config = {}; + config.pid = 0x1234; + + auto session = std::make_unique(config, device); + auto result = session->initialize(); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]); + EXPECT_EQ(session->processId, config.pid); + EXPECT_EQ(session->debugHandle, mockWddm->debugHandle); + + EXPECT_TRUE(session->closeConnection()); + EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_DETACH_DEBUGGER]); +} + +TEST(DebugSessionWindowsTest, whenTranslateEscapeErrorStatusCalledThenCorrectZeResultReturned) { + EXPECT_EQ(ZE_RESULT_SUCCESS, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_ACTION_ESCAPE_SUCCESS)); + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_ACTION_DEBUGGER_ATTACH_DEVICE_BUSY)); + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_ACTION_READ_EVENT_TIMEOUT_EXPIRED)); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_ACTION_INVALID_ARGS)); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_ACTION_NOT_VALID_PROCESS)); + EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_ACTION_PERMISSION_DENIED)); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_ACTION_EU_DEBUG_NOT_SUPPORTED)); + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, DebugSessionWindows::translateEscapeReturnStatusToZeResult(DBGUMD_ACTION_ESCAPE_RETURN_TYPE_MAX)); +} + } // namespace ult } // namespace L0 diff --git a/shared/source/os_interface/windows/os_interface_win.cpp b/shared/source/os_interface/windows/os_interface_win.cpp index b4e0c99b28..2ed255900e 100644 --- a/shared/source/os_interface/windows/os_interface_win.cpp +++ b/shared/source/os_interface/windows/os_interface_win.cpp @@ -6,6 +6,7 @@ */ #include "shared/source/os_interface/os_interface.h" +#include "shared/source/os_interface/windows/wddm/wddm.h" namespace NEO { @@ -15,6 +16,9 @@ bool OSInterface::gpuIdleImplicitFlush = false; bool OSInterface::requiresSupportForWddmTrimNotification = true; bool OSInterface::isDebugAttachAvailable() const { + if (driverModel) { + return driverModel->as()->isDebugAttachAvailable(); + } return false; } diff --git a/shared/source/os_interface/windows/wddm/wddm.cpp b/shared/source/os_interface/windows/wddm/wddm.cpp index 2be4657db5..e956ca79c9 100644 --- a/shared/source/os_interface/windows/wddm/wddm.cpp +++ b/shared/source/os_interface/windows/wddm/wddm.cpp @@ -1029,6 +1029,10 @@ bool Wddm::isShutdownInProgress() { return NEO::isShutdownInProgress(); } +bool Wddm::isDebugAttachAvailable() { + return false; +} + void Wddm::releaseReservedAddress(void *reservedAddress) { if (reservedAddress) { this->virtualFree(reservedAddress, 0); diff --git a/shared/source/os_interface/windows/wddm/wddm.h b/shared/source/os_interface/windows/wddm/wddm.h index 55f3648fa5..a0a656dce6 100644 --- a/shared/source/os_interface/windows/wddm/wddm.h +++ b/shared/source/os_interface/windows/wddm/wddm.h @@ -101,7 +101,7 @@ class Wddm : public DriverModel { MOCKABLE_VIRTUAL bool submit(uint64_t commandBuffer, size_t size, void *commandHeader, WddmSubmitArguments &submitArguments); MOCKABLE_VIRTUAL bool waitFromCpu(uint64_t lastFenceValue, const MonitoredFence &monitoredFence); - NTSTATUS escape(D3DKMT_ESCAPE &escapeCommand); + MOCKABLE_VIRTUAL NTSTATUS escape(D3DKMT_ESCAPE &escapeCommand); MOCKABLE_VIRTUAL VOID *registerTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, WddmResidencyController &residencyController); void unregisterTrimCallback(PFND3DKMT_TRIMNOTIFICATIONCALLBACK callback, VOID *trimCallbackHandle); MOCKABLE_VIRTUAL void releaseReservedAddress(void *reservedAddress); @@ -111,6 +111,7 @@ class Wddm : public DriverModel { MOCKABLE_VIRTUAL void virtualFree(void *ptr, size_t size); MOCKABLE_VIRTUAL bool isShutdownInProgress(); + MOCKABLE_VIRTUAL bool isDebugAttachAvailable(); bool isGpuHangDetected(OsContext &osContext) override; diff --git a/shared/test/unit_test/os_interface/windows/wddm_tests.cpp b/shared/test/unit_test/os_interface/windows/wddm_tests.cpp index e64ebbd741..41ca70637c 100644 --- a/shared/test/unit_test/os_interface/windows/wddm_tests.cpp +++ b/shared/test/unit_test/os_interface/windows/wddm_tests.cpp @@ -74,6 +74,11 @@ TEST_F(WddmTests, whenCheckedIfResourcesCleanupCanBeSkippedThenReturnsFalse) { EXPECT_FALSE(wddm->skipResourceCleanup()); } +TEST_F(WddmTests, whenCheckedIfDebugAttachAvailableThenReturnsFalse) { + init(); + EXPECT_FALSE(wddm->isDebugAttachAvailable()); +} + TEST_F(WddmTests, whenCreatingContextWithPowerHintSuccessIsReturned) { init(); auto newContext = osContext.get();