diff --git a/level_zero/core/source/driver/driver_handle_imp.cpp b/level_zero/core/source/driver/driver_handle_imp.cpp index 71986eaac5..e4e9f28fcf 100644 --- a/level_zero/core/source/driver/driver_handle_imp.cpp +++ b/level_zero/core/source/driver/driver_handle_imp.cpp @@ -17,6 +17,7 @@ #include "shared/source/memory_manager/allocation_properties.h" #include "shared/source/memory_manager/memory_manager.h" #include "shared/source/memory_manager/unified_memory_manager.h" +#include "shared/source/os_interface/os_interface.h" #include "shared/source/os_interface/os_library.h" #include "level_zero/core/source/builtin/builtin_functions_lib.h" @@ -222,6 +223,11 @@ ze_result_t DriverHandleImp::initialize(std::vector auto device = Device::create(this, pNeoDevice, false, &returnValue); this->devices.push_back(device); + auto osInterface = device->getNEODevice()->getRootDeviceEnvironment().osInterface.get(); + if (osInterface && !osInterface->isDebugAttachAvailable() && enableProgramDebugging) { + return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE; + } + multiOsContextDriver |= device->isImplicitScalingCapable(); if (returnValue != ZE_RESULT_SUCCESS) { return returnValue; diff --git a/level_zero/core/test/unit_tests/sources/debugger/linux/test_l0_debugger_linux.cpp b/level_zero/core/test/unit_tests/sources/debugger/linux/test_l0_debugger_linux.cpp index 4f29bd5c7d..b903a16bf4 100644 --- a/level_zero/core/test/unit_tests/sources/debugger/linux/test_l0_debugger_linux.cpp +++ b/level_zero/core/test/unit_tests/sources/debugger/linux/test_l0_debugger_linux.cpp @@ -308,6 +308,54 @@ HWTEST_F(L0DebuggerLinuxTest, givenDebuggingEnabledWhenCommandQueuesAreCreatedAn EXPECT_EQ(2u, debuggerL0Hw->commandQueueDestroyedCount); } +HWTEST_F(L0DebuggerLinuxTest, givenDebuggingEnabledAndDebugAttachAvailableWhenInitializingDriverThenSuccessIsReturned) { + auto executionEnvironment = new NEO::ExecutionEnvironment(); + executionEnvironment->prepareRootDeviceEnvironments(1); + executionEnvironment->setDebuggingEnabled(); + executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(defaultHwInfo.get()); + executionEnvironment->initializeMemoryManager(); + auto osInterface = new OSInterface(); + auto drmMock = new DrmMockResources(*executionEnvironment->rootDeviceEnvironments[0]); + executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface); + executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(drmMock)); + + auto neoDevice = NEO::MockDevice::create(executionEnvironment, 0u); + + NEO::DeviceVector devices; + devices.push_back(std::unique_ptr(neoDevice)); + auto driverHandle = std::make_unique>(); + driverHandle->enableProgramDebugging = true; + + drmMock->allowDebugAttach = true; + + ze_result_t result = driverHandle->initialize(std::move(devices)); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +HWTEST_F(L0DebuggerLinuxTest, givenDebuggingEnabledAndDebugAttachNotAvailableWhenInitializingDriverThenErrorIsReturned) { + auto executionEnvironment = new NEO::ExecutionEnvironment(); + executionEnvironment->prepareRootDeviceEnvironments(1); + executionEnvironment->setDebuggingEnabled(); + executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(defaultHwInfo.get()); + executionEnvironment->initializeMemoryManager(); + auto osInterface = new OSInterface(); + auto drmMock = new DrmMockResources(*executionEnvironment->rootDeviceEnvironments[0]); + executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface); + executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(drmMock)); + + auto neoDevice = NEO::MockDevice::create(executionEnvironment, 0u); + + NEO::DeviceVector devices; + devices.push_back(std::unique_ptr(neoDevice)); + auto driverHandle = std::make_unique>(); + driverHandle->enableProgramDebugging = true; + + drmMock->allowDebugAttach = false; + + ze_result_t result = driverHandle->initialize(std::move(devices)); + EXPECT_EQ(ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE, result); +} + HWTEST_F(L0DebuggerLinuxTest, givenDebuggingEnabledWhenImmCommandListsCreatedAndDestroyedThenDebuggerL0IsNotified) { auto debuggerL0Hw = static_cast *>(device->getL0Debugger()); diff --git a/level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp b/level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp index 81416ba1d7..2e2b1f004f 100644 --- a/level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp +++ b/level_zero/core/test/unit_tests/sources/debugger/windows/test_l0_debugger_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -195,5 +195,65 @@ TEST_F(L0DebuggerWindowsTest, givenDebuggerL0NotifyModuleDestroyCalledAndModuleD EXPECT_TRUE(hasSubstr(testing::internal::GetCapturedStderr(), std::string("KM_ESCAPE_EUDBG_UMD_MODULE_DESTROY_NOTIFY: Failed - Status:"))); } +TEST_F(L0DebuggerWindowsTest, givenProgramDebuggingEnabledAndDebugAttachAvailableWhenInitializingDriverThenSuccessIsReturned) { + auto executionEnvironment = new NEO::ExecutionEnvironment(); + executionEnvironment->prepareRootDeviceEnvironments(1); + executionEnvironment->setDebuggingEnabled(); + auto hwInfo = *NEO::defaultHwInfo.get(); + executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(&hwInfo); + + WddmEuDebugInterfaceMock *wddm = new WddmEuDebugInterfaceMock(*executionEnvironment->rootDeviceEnvironments[0]); + wddm->callBaseDestroyAllocations = false; + wddm->callBaseMapGpuVa = false; + wddm->callBaseWaitFromCpu = false; + + auto osInterface = new OSInterface(); + executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface); + executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(wddm)); + wddm->init(); + executionEnvironment->memoryManager.reset(new MockWddmMemoryManager(*executionEnvironment)); + + auto neoDevice = NEO::MockDevice::create(executionEnvironment, 0u); + NEO::DeviceVector devices; + devices.push_back(std::unique_ptr(neoDevice)); + auto driverHandle = std::make_unique>(); + + driverHandle->enableProgramDebugging = true; + wddm->debugAttachAvailable = true; + + ze_result_t result = driverHandle->initialize(std::move(devices)); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(L0DebuggerWindowsTest, givenProgramDebuggingEnabledAndDebugAttachNotAvailableWhenInitializingDriverThenErrorIsReturned) { + auto executionEnvironment = new NEO::ExecutionEnvironment(); + executionEnvironment->prepareRootDeviceEnvironments(1); + executionEnvironment->setDebuggingEnabled(); + auto hwInfo = *NEO::defaultHwInfo.get(); + executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(&hwInfo); + + WddmEuDebugInterfaceMock *wddm = new WddmEuDebugInterfaceMock(*executionEnvironment->rootDeviceEnvironments[0]); + wddm->callBaseDestroyAllocations = false; + wddm->callBaseMapGpuVa = false; + wddm->callBaseWaitFromCpu = false; + + auto osInterface = new OSInterface(); + executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface); + executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(wddm)); + wddm->init(); + executionEnvironment->memoryManager.reset(new MockWddmMemoryManager(*executionEnvironment)); + + auto neoDevice = NEO::MockDevice::create(executionEnvironment, 0u); + NEO::DeviceVector devices; + devices.push_back(std::unique_ptr(neoDevice)); + auto driverHandle = std::make_unique>(); + + driverHandle->enableProgramDebugging = true; + wddm->debugAttachAvailable = false; + + ze_result_t result = driverHandle->initialize(std::move(devices)); + EXPECT_EQ(ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE, result); +} + } // namespace ult } // namespace L0 diff --git a/shared/source/os_interface/linux/drm_neo.cpp b/shared/source/os_interface/linux/drm_neo.cpp index 2671cd51b3..820f3c39d6 100644 --- a/shared/source/os_interface/linux/drm_neo.cpp +++ b/shared/source/os_interface/linux/drm_neo.cpp @@ -824,7 +824,9 @@ bool Drm::sysmanQueryEngineInfo() { } bool Drm::isDebugAttachAvailable() { - return ioctlHelper->isDebugAttachAvailable(); + int prelimEnableEuDebug = 0; + getPrelimEuDebug(prelimEnableEuDebug); + return (prelimEnableEuDebug == 1) && ioctlHelper->isDebugAttachAvailable(); } int getMaxGpuFrequencyOfDevice(Drm &drm, std::string &sysFsPciPath, int &maxGpuFrequency) { @@ -969,6 +971,20 @@ void Drm::getPrelimVersion(std::string &prelimVersion) { ifs.close(); } +void Drm::getPrelimEuDebug(int &prelimEuDebug) { + prelimEuDebug = 0; + std::string sysFsPciPath = getSysFsPciPath(); + std::string prelimEuDebugPath = sysFsPciPath + "/prelim_enable_eu_debug"; + + std::ifstream ifs(prelimEuDebugPath.c_str(), std::ifstream::in); + + if (!ifs.fail()) { + ifs >> prelimEuDebug; + } + + ifs.close(); +} + int Drm::waitUserFence(uint32_t ctxId, uint64_t address, uint64_t value, ValueWidth dataWidth, int64_t timeout, uint16_t flags) { return ioctlHelper->waitUserFence(ctxId, address, value, static_cast(dataWidth), timeout, flags); } diff --git a/shared/source/os_interface/linux/drm_neo.h b/shared/source/os_interface/linux/drm_neo.h index 62358e230b..6953b4ae46 100644 --- a/shared/source/os_interface/linux/drm_neo.h +++ b/shared/source/os_interface/linux/drm_neo.h @@ -135,6 +135,7 @@ class Drm : public DriverModel { void setupSystemInfo(HardwareInfo *hwInfo, SystemInfo *sysInfo); void setupCacheInfo(const HardwareInfo &hwInfo); MOCKABLE_VIRTUAL void getPrelimVersion(std::string &prelimVersion); + MOCKABLE_VIRTUAL void getPrelimEuDebug(int &prelimEuDebug); PhysicalDevicePciBusInfo getPciBusInfo() const override; bool isGpuHangDetected(OsContext &osContext) override; diff --git a/shared/test/common/libult/linux/drm_query_mock.h b/shared/test/common/libult/linux/drm_query_mock.h index 11ae299722..73470148f5 100644 --- a/shared/test/common/libult/linux/drm_query_mock.h +++ b/shared/test/common/libult/linux/drm_query_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Intel Corporation + * Copyright (C) 2022-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -28,6 +28,11 @@ class DrmQueryMock : public DrmMock { contextDebugSupported, }; + void getPrelimEuDebug(int &prelimEuDebug) override { + prelimEuDebug = prelimEuDebugValue; + } + int prelimEuDebugValue = 0; + static constexpr uint32_t maxEngineCount{9}; ContextEnginesLoadBalance receivedContextEnginesLoadBalance{}; ContextParamEngines<1 + maxEngineCount> receivedContextParamEngines{}; diff --git a/shared/test/common/test_files/linux/devices/device/drm/card1/prelim_enable_eu_debug b/shared/test/common/test_files/linux/devices/device/drm/card1/prelim_enable_eu_debug new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/shared/test/common/test_files/linux/devices/device/drm/card1/prelim_enable_eu_debug @@ -0,0 +1 @@ +1 diff --git a/shared/test/unit_test/os_interface/linux/drm_query_prelim_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_query_prelim_tests.cpp index 86a471622a..08482828dc 100644 --- a/shared/test/unit_test/os_interface/linux/drm_query_prelim_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_query_prelim_tests.cpp @@ -207,14 +207,24 @@ TEST(DrmQueryTest, givenCreateContextWithAccessCounterWhenDrmContextIsCreatedThe } } -TEST(DrmQueryTest, WhenCallingIsDebugAttachAvailableThenReturnValueIsTrue) { +TEST(DrmQueryTest, givenPrelimEuDebugEnabledWhenCallingIsDebugAttachAvailableThenReturnValueIsTrue) { auto executionEnvironment = std::make_unique(); DrmQueryMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; drm.allowDebugAttachCallBase = true; + drm.prelimEuDebugValue = 1; EXPECT_TRUE(drm.isDebugAttachAvailable()); } +TEST(DrmQueryTest, givenPrelimEuDebugDisabledWhenCallingIsDebugAttachAvailableThenReturnValueIsFalse) { + auto executionEnvironment = std::make_unique(); + DrmQueryMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + drm.allowDebugAttachCallBase = true; + drm.prelimEuDebugValue = 0; + + EXPECT_FALSE(drm.isDebugAttachAvailable()); +} + TEST(DrmPrelimTest, GivenDebuggerOpenIoctlWhenErrorEbusyReturnedThenErrorIsReturnedWithoutReinvokingIoctl) { auto executionEnvironment = std::make_unique(); DrmQueryMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; diff --git a/shared/test/unit_test/os_interface/linux/drm_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_tests.cpp index 6ddc0e078f..d2bf53a0f6 100644 --- a/shared/test/unit_test/os_interface/linux/drm_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_tests.cpp @@ -1196,6 +1196,33 @@ TEST(DrmQueryTest, givenUapiPrelimVersionWithInvalidPathThenReturnEmptyString) { EXPECT_TRUE(prelimVersion.empty()); } +TEST(DrmQueryTest, givenPrelimEnableEuDebugThenReturnCorrectValue) { + auto executionEnvironment = std::make_unique(); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + std::string prelimEuDebugFile = getLinuxDevicesPath("device/drm/card1/prelim_enable_eu_debug"); + EXPECT_TRUE(fileExists(prelimEuDebugFile)); + + drm.setPciPath("device"); + + int prelimEnableEuDebug = 0; + drm.getPrelimEuDebug(prelimEnableEuDebug); + + EXPECT_EQ(1, prelimEnableEuDebug); +} + +TEST(DrmQueryTest, givenPrelimEnableEuDebugWithInvalidPathThenReturnDefaultValue) { + auto executionEnvironment = std::make_unique(); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("invalidPath"); + + int prelimEnableEuDebug = 1; + drm.getPrelimEuDebug(prelimEnableEuDebug); + + EXPECT_EQ(0, prelimEnableEuDebug); +} + TEST(DrmTest, givenInvalidUapiPrelimVersionThenFallbackToBasePrelim) { auto executionEnvironment = std::make_unique(); DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]};