From c7fe7dde90dcda6822f147a95c0ceef5cc59bf37 Mon Sep 17 00:00:00 2001 From: Aravind Gopalakrishnan Date: Tue, 8 Apr 2025 22:05:33 +0000 Subject: [PATCH] fix: Correct Xe sysfs paths for ccs mode setting Fix the sysfs paths for Xe KMD Related-To: NEO-10378 Signed-off-by: Aravind Gopalakrishnan --- .../execution_environment_drm.cpp | 47 +- .../execution_environment_drm_or_wddm.cpp | 50 +- .../os_interface/linux/ioctl_helper.cpp | 32 + .../source/os_interface/linux/ioctl_helper.h | 7 + .../os_interface/linux/ioctl_helper_i915.cpp | 23 + .../os_interface/linux/xe/ioctl_helper_xe.cpp | 23 + .../os_interface/linux/xe/ioctl_helper_xe.h | 2 + .../common/mocks/mock_execution_environment.h | 1 + .../os_interface/linux/ccs_mode_tests.cpp | 156 +++- .../os_interface/linux/xe/CMakeLists.txt | 3 +- .../linux/xe/ccs_mode_xe_tests.cpp | 805 ++++++++++++++++++ .../os_interface/wddm_linux/CMakeLists.txt | 5 +- .../wddm_linux/ccs_mode_drm_or_wddm_test.cpp | 116 +++ 13 files changed, 1146 insertions(+), 124 deletions(-) create mode 100644 shared/test/unit_test/os_interface/linux/xe/ccs_mode_xe_tests.cpp create mode 100644 shared/test/unit_test/os_interface/wddm_linux/ccs_mode_drm_or_wddm_test.cpp diff --git a/shared/source/execution_environment/execution_environment_drm.cpp b/shared/source/execution_environment/execution_environment_drm.cpp index 461716941d..7f968caed6 100644 --- a/shared/source/execution_environment/execution_environment_drm.cpp +++ b/shared/source/execution_environment/execution_environment_drm.cpp @@ -9,7 +9,10 @@ #include "shared/source/execution_environment/execution_environment.h" #include "shared/source/execution_environment/root_device_environment.h" #include "shared/source/os_interface/linux/drm_memory_operations_handler.h" +#include "shared/source/os_interface/linux/drm_neo.h" #include "shared/source/os_interface/linux/file_descriptor.h" +#include "shared/source/os_interface/linux/ioctl_helper.h" +#include "shared/source/os_interface/os_interface.h" #include "shared/source/utilities/directory.h" #include @@ -40,45 +43,11 @@ void ExecutionEnvironment::configureCcsMode() { const std::string drmPath = "/sys/class/drm"; const std::string expectedFilePrefix = drmPath + "/card"; auto files = Directory::getFiles(drmPath.c_str()); - for (const auto &file : files) { - if (file.find(expectedFilePrefix.c_str()) == std::string::npos) { - continue; - } - - std::string gtPath = file + "/gt"; - auto gtFiles = Directory::getFiles(gtPath.c_str()); - auto expectedGtFilePrefix = gtPath + "/gt"; - for (const auto >File : gtFiles) { - if (gtFile.find(expectedGtFilePrefix.c_str()) == std::string::npos) { - continue; - } - std::string ccsFile = gtFile + "/ccs_mode"; - auto fd = FileDescriptor(ccsFile.c_str(), O_RDWR); - if (fd < 0) { - if ((errno == -EACCES) || (errno == -EPERM)) { - fprintf(stderr, "No read and write permissions for %s, System administrator needs to grant permissions to allow modification of this file from user space\n", ccsFile.c_str()); - fprintf(stdout, "No read and write permissions for %s, System administrator needs to grant permissions to allow modification of this file from user space\n", ccsFile.c_str()); - } - continue; - } - - uint32_t ccsValue = 0; - ssize_t ret = SysCalls::read(fd, &ccsValue, sizeof(uint32_t)); - PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get() && (ret < 0), stderr, "read() on %s failed errno = %d | ret = %d \n", - ccsFile.c_str(), errno, ret); - - if ((ret < 0) || (ccsValue == ccsMode)) { - continue; - } - - do { - ret = SysCalls::write(fd, &ccsMode, sizeof(uint32_t)); - } while (ret == -1 && errno == -EBUSY); - - if (ret > 0) { - deviceCcsModeVec.emplace_back(ccsFile, ccsValue); - } - } + for (auto rootDeviceIndex = 0u; rootDeviceIndex < rootDeviceEnvironments.size(); rootDeviceIndex++) { + auto drm = rootDeviceEnvironments[rootDeviceIndex]->osInterface->getDriverModel()->as(); + auto ioctlHelper = drm->getIoctlHelper(); + auto files = Directory::getFiles(drmPath.c_str()); + ioctlHelper->configureCcsMode(files, expectedFilePrefix, ccsMode, deviceCcsModeVec); } } diff --git a/shared/source/execution_environment/execution_environment_drm_or_wddm.cpp b/shared/source/execution_environment/execution_environment_drm_or_wddm.cpp index 52378e57f1..0fe64d49a1 100644 --- a/shared/source/execution_environment/execution_environment_drm_or_wddm.cpp +++ b/shared/source/execution_environment/execution_environment_drm_or_wddm.cpp @@ -10,7 +10,9 @@ #include "shared/source/execution_environment/root_device_environment.h" #include "shared/source/helpers/driver_model_type.h" #include "shared/source/os_interface/linux/drm_memory_operations_handler.h" +#include "shared/source/os_interface/linux/drm_neo.h" #include "shared/source/os_interface/linux/file_descriptor.h" +#include "shared/source/os_interface/linux/ioctl_helper.h" #include "shared/source/os_interface/os_interface.h" #include "shared/source/utilities/directory.h" @@ -35,6 +37,10 @@ void ExecutionEnvironment::configureCcsMode() { return; } + if (rootDeviceEnvironments.empty() || rootDeviceEnvironments[0]->osInterface->getDriverModel()->getDriverModelType() != DriverModelType::drm) { + return; + } + char *endPtr = nullptr; uint32_t ccsMode = static_cast(std::strtoul(ccsString.c_str(), &endPtr, 10)); if (endPtr == ccsString.c_str()) { @@ -43,47 +49,11 @@ void ExecutionEnvironment::configureCcsMode() { const std::string drmPath = "/sys/class/drm"; const std::string expectedFilePrefix = drmPath + "/card"; + + auto drm = rootDeviceEnvironments[0]->osInterface->getDriverModel()->as(); + auto ioctlHelper = drm->getIoctlHelper(); auto files = Directory::getFiles(drmPath.c_str()); - for (const auto &file : files) { - if (file.find(expectedFilePrefix.c_str()) == std::string::npos) { - continue; - } - - std::string gtPath = file + "/gt"; - auto gtFiles = Directory::getFiles(gtPath.c_str()); - auto expectedGtFilePrefix = gtPath + "/gt"; - for (const auto >File : gtFiles) { - if (gtFile.find(expectedGtFilePrefix.c_str()) == std::string::npos) { - continue; - } - std::string ccsFile = gtFile + "/ccs_mode"; - auto fd = FileDescriptor(ccsFile.c_str(), O_RDWR); - if (fd < 0) { - if ((errno == -EACCES) || (errno == -EPERM)) { - fprintf(stderr, "No read and write permissions for %s, System administrator needs to grant permissions to allow modification of this file from user space\n", ccsFile.c_str()); - fprintf(stdout, "No read and write permissions for %s, System administrator needs to grant permissions to allow modification of this file from user space\n", ccsFile.c_str()); - } - continue; - } - - uint32_t ccsValue = 0; - ssize_t ret = SysCalls::read(fd, &ccsValue, sizeof(uint32_t)); - PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get() && (ret < 0), stderr, "read() on %s failed errno = %d | ret = %d \n", - ccsFile.c_str(), errno, ret); - - if ((ret < 0) || (ccsValue == ccsMode)) { - continue; - } - - do { - ret = SysCalls::write(fd, &ccsMode, sizeof(uint32_t)); - } while (ret == -1 && errno == -EBUSY); - - if (ret > 0) { - deviceCcsModeVec.emplace_back(ccsFile, ccsValue); - } - } - } + ioctlHelper->configureCcsMode(files, expectedFilePrefix, ccsMode, deviceCcsModeVec); } void ExecutionEnvironment::restoreCcsMode() { diff --git a/shared/source/os_interface/linux/ioctl_helper.cpp b/shared/source/os_interface/linux/ioctl_helper.cpp index ddd95c4668..3533d0c28a 100644 --- a/shared/source/os_interface/linux/ioctl_helper.cpp +++ b/shared/source/os_interface/linux/ioctl_helper.cpp @@ -17,6 +17,7 @@ #include "shared/source/os_interface/linux/drm_memory_manager.h" #include "shared/source/os_interface/linux/drm_neo.h" #include "shared/source/os_interface/linux/drm_wrappers.h" +#include "shared/source/os_interface/linux/file_descriptor.h" #include "shared/source/os_interface/linux/os_context_linux.h" #include "shared/source/os_interface/linux/sys_calls.h" @@ -54,6 +55,37 @@ uint32_t IoctlHelper::getFlagsForPrimeHandleToFd() const { return DRM_CLOEXEC | DRM_RDWR; } +void IoctlHelper::writeCcsMode(const std::string >File, uint32_t ccsMode, + std::vector> &deviceCcsModeVec) { + + std::string ccsFile = gtFile + "/ccs_mode"; + auto fd = FileDescriptor(ccsFile.c_str(), O_RDWR); + if (fd < 0) { + if ((errno == -EACCES) || (errno == -EPERM)) { + fprintf(stderr, "No read and write permissions for %s, System administrator needs to grant permissions to allow modification of this file from user space\n", ccsFile.c_str()); + fprintf(stdout, "No read and write permissions for %s, System administrator needs to grant permissions to allow modification of this file from user space\n", ccsFile.c_str()); + } + return; + } + + uint32_t ccsValue = 0; + ssize_t ret = SysCalls::read(fd, &ccsValue, sizeof(uint32_t)); + PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get() && (ret < 0), stderr, "read() on %s failed errno = %d | ret = %d \n", + ccsFile.c_str(), errno, ret); + + if ((ret < 0) || (ccsValue == ccsMode)) { + return; + } + + do { + ret = SysCalls::write(fd, &ccsMode, sizeof(uint32_t)); + } while (ret == -1 && errno == -EBUSY); + + if (ret > 0) { + deviceCcsModeVec.emplace_back(ccsFile, ccsValue); + } +}; + unsigned int IoctlHelper::getIoctlRequestValueBase(DrmIoctl ioctlRequest) const { switch (ioctlRequest) { case DrmIoctl::gemClose: diff --git a/shared/source/os_interface/linux/ioctl_helper.h b/shared/source/os_interface/linux/ioctl_helper.h index 836993080c..83824ffaf3 100644 --- a/shared/source/os_interface/linux/ioctl_helper.h +++ b/shared/source/os_interface/linux/ioctl_helper.h @@ -194,6 +194,11 @@ class IoctlHelper { virtual void setupIpVersion(); virtual bool isImmediateVmBindRequired() const { return false; } + virtual void configureCcsMode(std::vector &files, const std::string expectedFilePrefix, uint32_t ccsMode, + std::vector> &deviceCcsModeVec) = 0; + + void writeCcsMode(const std::string >File, uint32_t ccsMode, + std::vector> &deviceCcsModeVec); uint32_t getFlagsForPrimeHandleToFd() const; virtual std::unique_ptr createMemoryInfo() = 0; virtual size_t getLocalMemoryRegionsSize(const MemoryInfo *memoryInfo, uint32_t subDevicesCount, uint32_t deviceBitfield) const = 0; @@ -269,6 +274,8 @@ class IoctlHelperI915 : public IoctlHelper { std::string getFileForMaxGpuFrequency() const override; std::string getFileForMaxGpuFrequencyOfSubDevice(int tileId) const override; std::string getFileForMaxMemoryFrequencyOfSubDevice(int tileId) const override; + void configureCcsMode(std::vector &files, const std::string expectedFilePrefix, uint32_t ccsMode, + std::vector> &deviceCcsModeVec) override; bool getTopologyDataAndMap(const HardwareInfo &hwInfo, DrmQueryTopologyData &topologyData, TopologyMap &topologyMap) override; bool getFdFromVmExport(uint32_t vmId, uint32_t flags, int32_t *fd) override; uint32_t createGem(uint64_t size, uint32_t memoryBanks, std::optional isCoherent) override; diff --git a/shared/source/os_interface/linux/ioctl_helper_i915.cpp b/shared/source/os_interface/linux/ioctl_helper_i915.cpp index 5c53ed0894..0bd3a96902 100644 --- a/shared/source/os_interface/linux/ioctl_helper_i915.cpp +++ b/shared/source/os_interface/linux/ioctl_helper_i915.cpp @@ -16,12 +16,14 @@ #include "shared/source/os_interface/linux/drm_neo.h" #include "shared/source/os_interface/linux/drm_wrappers.h" #include "shared/source/os_interface/linux/engine_info.h" +#include "shared/source/os_interface/linux/file_descriptor.h" #include "shared/source/os_interface/linux/i915.h" #include "shared/source/os_interface/linux/ioctl_helper.h" #include "shared/source/os_interface/linux/memory_info.h" #include "shared/source/os_interface/linux/os_context_linux.h" #include "shared/source/os_interface/linux/sys_calls.h" #include "shared/source/os_interface/os_time.h" +#include "shared/source/utilities/directory.h" #include #include @@ -452,6 +454,27 @@ std::string IoctlHelperI915::getFileForMaxMemoryFrequencyOfSubDevice(int tileId) return "/gt/gt" + std::to_string(tileId) + "/mem_RP0_freq_mhz"; } +void IoctlHelperI915::configureCcsMode(std::vector &files, const std::string expectedFilePrefix, uint32_t ccsMode, + std::vector> &deviceCcsModeVec) { + + // On i915 path to ccs_mode is /sys/class/drm/card0/gt/gt*/ + for (const auto &file : files) { + if (file.find(expectedFilePrefix.c_str()) == std::string::npos) { + continue; + } + + std::string gtPath = file + "/gt"; + auto gtFiles = Directory::getFiles(gtPath.c_str()); + auto expectedGtFilePrefix = gtPath + "/gt"; + for (const auto >File : gtFiles) { + if (gtFile.find(expectedGtFilePrefix.c_str()) == std::string::npos) { + continue; + } + writeCcsMode(gtFile, ccsMode, deviceCcsModeVec); + } + } +} + bool IoctlHelperI915::getTopologyDataAndMap(const HardwareInfo &hwInfo, DrmQueryTopologyData &topologyData, TopologyMap &topologyMap) { auto request = this->getDrmParamValue(DrmParam::queryTopologyInfo); diff --git a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp index 6670911c78..e044c85c54 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp @@ -23,11 +23,13 @@ #include "shared/source/os_interface/linux/drm_buffer_object.h" #include "shared/source/os_interface/linux/drm_neo.h" #include "shared/source/os_interface/linux/engine_info.h" +#include "shared/source/os_interface/linux/file_descriptor.h" #include "shared/source/os_interface/linux/memory_info.h" #include "shared/source/os_interface/linux/os_context_linux.h" #include "shared/source/os_interface/linux/sys_calls.h" #include "shared/source/os_interface/linux/xe/xedrm.h" #include "shared/source/os_interface/os_time.h" +#include "shared/source/utilities/directory.h" #include #include @@ -1581,6 +1583,27 @@ std::string IoctlHelperXe::getFileForMaxMemoryFrequencyOfSubDevice(int tileId) c return getDirectoryWithFrequencyFiles(tileId, tileIdToGtId[tileId]) + "/rp0_freq"; } +void IoctlHelperXe::configureCcsMode(std::vector &files, const std::string expectedFilePrefix, uint32_t ccsMode, + std::vector> &deviceCcsModeVec) { + + // On Xe, path is /sys/class/drm/card0/device/tile*/gt*/ccs_mode + for (const auto &file : files) { + if (file.find(expectedFilePrefix.c_str()) == std::string::npos) { + continue; + } + + std::string tilePath = file + "/device/tile"; + auto tileFiles = Directory::getFiles(tilePath.c_str()); + for (const auto &tileFile : tileFiles) { + std::string gtPath = tileFile + "/gt"; + auto gtFiles = Directory::getFiles(gtPath.c_str()); + for (const auto >File : gtFiles) { + writeCcsMode(gtFile, ccsMode, deviceCcsModeVec); + } + } + } +} + bool IoctlHelperXe::getFabricLatency(uint32_t fabricId, uint32_t &latency, uint32_t &bandwidth) { return false; } diff --git a/shared/source/os_interface/linux/xe/ioctl_helper_xe.h b/shared/source/os_interface/linux/xe/ioctl_helper_xe.h index e8cb059a91..bb8d6e6d44 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe.h +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe.h @@ -108,6 +108,8 @@ class IoctlHelperXe : public IoctlHelper { std::string getFileForMaxGpuFrequency() const override; std::string getFileForMaxGpuFrequencyOfSubDevice(int subDeviceId) const override; std::string getFileForMaxMemoryFrequencyOfSubDevice(int subDeviceId) const override; + void configureCcsMode(std::vector &files, const std::string expectedPrefix, uint32_t ccsMode, + std::vector> &deviceCcsModeVec) override; bool getFabricLatency(uint32_t fabricId, uint32_t &latency, uint32_t &bandwidth) override; bool isWaitBeforeBindRequired(bool bind) const override; std::unique_ptr createEngineInfo(bool isSysmanEnabled) override; diff --git a/shared/test/common/mocks/mock_execution_environment.h b/shared/test/common/mocks/mock_execution_environment.h index a107cd998f..49bf03af8e 100644 --- a/shared/test/common/mocks/mock_execution_environment.h +++ b/shared/test/common/mocks/mock_execution_environment.h @@ -42,6 +42,7 @@ struct MockRootDeviceEnvironment : public RootDeviceEnvironment { struct MockExecutionEnvironment : ExecutionEnvironment { using ExecutionEnvironment::adjustCcsCountImpl; + using ExecutionEnvironment::configureCcsMode; using ExecutionEnvironment::directSubmissionController; using ExecutionEnvironment::memoryManager; using ExecutionEnvironment::rootDeviceEnvironments; diff --git a/shared/test/unit_test/os_interface/linux/ccs_mode_tests.cpp b/shared/test/unit_test/os_interface/linux/ccs_mode_tests.cpp index f4032a97bf..d4b18d7bf2 100644 --- a/shared/test/unit_test/os_interface/linux/ccs_mode_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/ccs_mode_tests.cpp @@ -6,10 +6,14 @@ */ #include "shared/source/execution_environment/execution_environment.h" +#include "shared/source/execution_environment/root_device_environment.h" #include "shared/source/utilities/directory.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/variable_backup.h" +#include "shared/test/common/libult/linux/drm_mock.h" +#include "shared/test/common/mocks/mock_driver_model.h" #include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" +#include "shared/test/common/test_macros/test.h" #include "gtest/gtest.h" @@ -24,7 +28,29 @@ static ssize_t mockWrite(int fd, const void *buf, size_t count) { return count; } -TEST(CcsModeTest, GivenInvalidCcsModeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { +class CcsModePrelimFixture { + public: + void setUp() { + executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(defaultHwInfo.get()); + + drm = new DrmMock(*executionEnvironment->rootDeviceEnvironments[0]); + executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new OSInterface()); + osInterface = executionEnvironment->rootDeviceEnvironments[0]->osInterface.get(); + osInterface->setDriverModel(std::unique_ptr(drm)); + } + + void tearDown() { + } + DrmMock *drm; + OSInterface *osInterface; + std::unique_ptr executionEnvironment; +}; + +using CcsModeTest = Test; + +TEST_F(CcsModeTest, GivenInvalidCcsModeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -49,24 +75,88 @@ TEST(CcsModeTest, GivenInvalidCcsModeWhenConfigureCcsModeIsCalledThenVerifyCcsMo return count; }); - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(1u, ccsMode); debugManager.flags.ZEX_NUMBER_OF_CCS.set("abc"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(1u, ccsMode); debugManager.flags.ZEX_NUMBER_OF_CCS.set(""); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(1u, ccsMode); directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenValidCcsModeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsProperlyConfigured) { +TEST_F(CcsModeTest, GivenValidCcsModeWhenConfigureCcsModeIsCalledWithoutRootDeviceEnvironmentsThenVerifyCcsModeIsNotConfigured) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("version"); + + directoryFilesMap["/sys/class/drm/card0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/gt"].push_back("/sys/class/drm/card0/gt/gt0"); + directoryFilesMap["/sys/class/drm/card0/gt"].push_back("unknown"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + executionEnvironment->rootDeviceEnvironments.clear(); + executionEnvironment->configureCcsMode(); + EXPECT_EQ(1u, ccsMode); + executionEnvironment->prepareRootDeviceEnvironments(1); + + directoryFilesMap.clear(); +} + +class DefaultDriverModelMock : public MockDriverModel { + public: + DefaultDriverModelMock(DriverModelType driverModelType) : MockDriverModel(driverModelType) { + } + + bool isDriverAvailable() override { + return true; + } + void setGmmInputArgs(void *args) override { + } + + uint32_t getDeviceHandle() const override { + return 0; + } + + PhysicalDevicePciBusInfo getPciBusInfo() const override { + return {}; + } + PhysicalDevicePciSpeedInfo getPciSpeedInfo() const override { + return {}; + } + + bool skipResourceCleanup() const { + return skipResourceCleanupVar; + } + + bool isGpuHangDetected(OsContext &osContext) override { + return false; + } +}; + +TEST_F(CcsModeTest, GivenValidCcsModeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsProperlyConfigured) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -92,17 +182,15 @@ TEST(CcsModeTest, GivenValidCcsModeWhenConfigureCcsModeIsCalledThenVerifyCcsMode return count; }); - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(2u, ccsMode); directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { +TEST_F(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -123,17 +211,15 @@ TEST(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWhenConfigureCcsModeIsCall return count; }); - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(1u, ccsMode); directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWithNoPermissionsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { +TEST_F(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWithNoPermissionsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -154,15 +240,13 @@ TEST(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWithNoPermissionsWhenConfi return count; }); - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; testing::internal::CaptureStdout(); testing::internal::CaptureStderr(); debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); std::string stdOutString = testing::internal::GetCapturedStdout(); std::string stdErrString = testing::internal::GetCapturedStderr(); @@ -174,7 +258,7 @@ TEST(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWithNoPermissionsWhenConfi directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWithNoAccessWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { +TEST_F(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWithNoAccessWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -195,15 +279,13 @@ TEST(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWithNoAccessWhenConfigureC return count; }); - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; testing::internal::CaptureStdout(); testing::internal::CaptureStderr(); debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); std::string stdOutString = testing::internal::GetCapturedStdout(); std::string stdErrString = testing::internal::GetCapturedStderr(); @@ -215,7 +297,7 @@ TEST(CcsModeTest, GivenValidCcsModeAndOpenSysCallFailsWithNoAccessWhenConfigureC directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenNumCCSFlagSetToCurrentConfigurationWhenConfigureCcsModeIsCalledThenVerifyWriteCallIsNotInvoked) { +TEST_F(CcsModeTest, GivenNumCCSFlagSetToCurrentConfigurationWhenConfigureCcsModeIsCalledThenVerifyWriteCallIsNotInvoked) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -237,11 +319,9 @@ TEST(CcsModeTest, GivenNumCCSFlagSetToCurrentConfigurationWhenConfigureCcsModeIs return count; }); - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; debugManager.flags.ZEX_NUMBER_OF_CCS.set("1"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(1u, ccsMode); EXPECT_EQ(0u, SysCalls::writeFuncCalled); @@ -249,7 +329,7 @@ TEST(CcsModeTest, GivenNumCCSFlagSetToCurrentConfigurationWhenConfigureCcsModeIs directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenNumCCSFlagSetToCurrentConfigurationAndReadSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { +TEST_F(CcsModeTest, GivenNumCCSFlagSetToCurrentConfigurationAndReadSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -270,11 +350,9 @@ TEST(CcsModeTest, GivenNumCCSFlagSetToCurrentConfigurationAndReadSysCallFailsWhe return -1; }); - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(1u, ccsMode); EXPECT_EQ(0u, SysCalls::writeFuncCalled); @@ -282,7 +360,7 @@ TEST(CcsModeTest, GivenNumCCSFlagSetToCurrentConfigurationAndReadSysCallFailsWhe directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenValidCcsModeAndWriteSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { +TEST_F(CcsModeTest, GivenValidCcsModeAndWriteSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -305,11 +383,9 @@ TEST(CcsModeTest, GivenValidCcsModeAndWriteSysCallFailsWhenConfigureCcsModeIsCal return count; }); - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_NE(2u, ccsMode); EXPECT_NE(0u, SysCalls::writeFuncCalled); @@ -317,7 +393,7 @@ TEST(CcsModeTest, GivenValidCcsModeAndWriteSysCallFailsWhenConfigureCcsModeIsCal directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenWriteSysCallFailsWithEbusyForFirstTimeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsConfiguredInSecondIteration) { +TEST_F(CcsModeTest, GivenWriteSysCallFailsWithEbusyForFirstTimeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsConfiguredInSecondIteration) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -343,11 +419,9 @@ TEST(CcsModeTest, GivenWriteSysCallFailsWithEbusyForFirstTimeWhenConfigureCcsMod }); { - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; debugManager.flags.ZEX_NUMBER_OF_CCS.set("4"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(4u, ccsMode); EXPECT_NE(0u, SysCalls::writeFuncCalled); @@ -356,7 +430,7 @@ TEST(CcsModeTest, GivenWriteSysCallFailsWithEbusyForFirstTimeWhenConfigureCcsMod directoryFilesMap.clear(); } -TEST(CcsModeTest, GivenValidCcsModeAndOpenCallFailsOnRestoreWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotRestored) { +TEST_F(CcsModeTest, GivenValidCcsModeAndOpenCallFailsOnRestoreWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotRestored) { VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); VariableBackup ccsModeBackup(&ccsMode); @@ -386,11 +460,9 @@ TEST(CcsModeTest, GivenValidCcsModeAndOpenCallFailsOnRestoreWhenConfigureCcsMode }); { - NEO::ExecutionEnvironment executionEnvironment; - DebugManagerStateRestore restorer; debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); - executionEnvironment.configureCcsMode(); + executionEnvironment->configureCcsMode(); EXPECT_EQ(2u, ccsMode); } diff --git a/shared/test/unit_test/os_interface/linux/xe/CMakeLists.txt b/shared/test/unit_test/os_interface/linux/xe/CMakeLists.txt index 7107348f73..c472e7d636 100644 --- a/shared/test/unit_test/os_interface/linux/xe/CMakeLists.txt +++ b/shared/test/unit_test/os_interface/linux/xe/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2023-2024 Intel Corporation +# Copyright (C) 2023-2025 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -7,6 +7,7 @@ set(NEO_CORE_OS_INTERFACE_TESTS_LINUX_XE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/ioctl_helper_xe_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ccs_mode_xe_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/ioctl_helper_xe_perf_tests.cpp ) if(NEO_ENABLE_XE_EU_DEBUG_SUPPORT) diff --git a/shared/test/unit_test/os_interface/linux/xe/ccs_mode_xe_tests.cpp b/shared/test/unit_test/os_interface/linux/xe/ccs_mode_xe_tests.cpp new file mode 100644 index 0000000000..513d41dc23 --- /dev/null +++ b/shared/test/unit_test/os_interface/linux/xe/ccs_mode_xe_tests.cpp @@ -0,0 +1,805 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/execution_environment/execution_environment.h" +#include "shared/source/execution_environment/root_device_environment.h" +#include "shared/source/utilities/directory.h" +#include "shared/test/common/helpers/debug_manager_state_restore.h" +#include "shared/test/common/helpers/variable_backup.h" +#include "shared/test/common/mocks/mock_driver_model.h" +#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" +#include "shared/test/common/os_interface/linux/xe/mock_drm_xe.h" +#include "shared/test/common/os_interface/linux/xe/mock_ioctl_helper_xe.h" +#include "shared/test/common/test_macros/test.h" + +#include "gtest/gtest.h" + +namespace NEO { +extern std::map> directoryFilesMap; +}; + +static uint32_t ccsMode = 1u; + +static ssize_t mockWrite(int fd, const void *buf, size_t count) { + std::memcpy(&ccsMode, buf, count); + return count; +} + +struct DrmMockXeCcs : public DrmMockCustom { + using Drm::engineInfo; + + void testMode(int f, int a = 0) { + forceIoctlAnswer = f; + setIoctlAnswer = a; + } + int ioctl(DrmIoctl request, void *arg) override { + int ret = -1; + ioctlCalled = true; + if (forceIoctlAnswer) { + return setIoctlAnswer; + } + switch (request) { + case DrmIoctl::gemVmCreate: { + struct drm_xe_vm_create *v = static_cast(arg); + v->vm_id = testValueVmId; + ret = 0; + } break; + case DrmIoctl::gemUserptr: { + ret = 0; + } break; + case DrmIoctl::gemClose: { + auto gemClose = reinterpret_cast(arg); + passedGemClose = *gemClose; + gemCloseCalled++; + ret = 0; + } break; + case DrmIoctl::gemVmDestroy: { + struct drm_xe_vm_destroy *v = static_cast(arg); + if (v->vm_id == testValueVmId) + ret = 0; + } break; + case DrmIoctl::gemMmapOffset: { + gemMmapOffsetCalled++; + + if (forceMmapOffsetFail) { + ret = -1; + break; + } + struct drm_xe_gem_mmap_offset *v = static_cast(arg); + v->offset = v->handle; + ret = 0; + + } break; + case DrmIoctl::primeFdToHandle: { + PrimeHandle *v = static_cast(arg); + if (v->fileDescriptor == testValuePrime) { + v->handle = testValuePrime; + ret = 0; + } + } break; + case DrmIoctl::primeHandleToFd: { + PrimeHandle *v = static_cast(arg); + if (v->handle == testValuePrime) { + v->fileDescriptor = testValuePrime; + ret = 0; + } + } break; + case DrmIoctl::gemCreate: { + ioctlCnt.gemCreate++; + auto createParams = static_cast(arg); + this->createParamsSize = createParams->size; + this->createParamsPlacement = createParams->placement; + this->createParamsFlags = createParams->flags; + this->createParamsHandle = createParams->handle = testValueGemCreate; + this->createParamsCpuCaching = createParams->cpu_caching; + if (0 == this->createParamsSize || 0 == this->createParamsPlacement || 0 == this->createParamsCpuCaching) { + return EINVAL; + } + ret = 0; + } break; + case DrmIoctl::getparam: + ret = -2; + break; + case DrmIoctl::getResetStats: { + auto execQueueProperty = static_cast(arg); + EXPECT_EQ(execQueueProperty->property, static_cast(DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN)); + execQueueProperty->value = execQueueBanPropertyReturn; + ret = 0; + } break; + case DrmIoctl::query: { + struct drm_xe_device_query *deviceQuery = static_cast(arg); + switch (deviceQuery->query) { + case DRM_XE_DEVICE_QUERY_CONFIG: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryConfig, sizeof(queryConfig)); + } + deviceQuery->size = sizeof(queryConfig); + break; + case DRM_XE_DEVICE_QUERY_ENGINES: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryEngines, sizeof(queryEngines)); + } + deviceQuery->size = sizeof(queryEngines); + break; + case DRM_XE_DEVICE_QUERY_MEM_REGIONS: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryMemUsage, sizeof(queryMemUsage)); + } + deviceQuery->size = sizeof(queryMemUsage); + break; + case DRM_XE_DEVICE_QUERY_GT_LIST: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryGtList.begin(), sizeof(queryGtList[0]) * queryGtList.size()); + } + deviceQuery->size = static_cast(sizeof(queryGtList[0]) * queryGtList.size()); + break; + case DRM_XE_DEVICE_QUERY_GT_TOPOLOGY: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryTopology.data(), queryTopology.size()); + } + deviceQuery->size = static_cast(queryTopology.size()); + break; + case DRM_XE_DEVICE_QUERY_ENGINE_CYCLES: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryEngineCycles, sizeof(queryEngineCycles)); + } + deviceQuery->size = sizeof(queryEngineCycles); + break; + }; + ret = 0; + } break; + case DrmIoctl::gemVmBind: { + ret = gemVmBindReturn; + auto vmBindInput = static_cast(arg); + vmBindInputs.push_back(*vmBindInput); + + if (vmBindInput->num_syncs == 1) { + auto &syncInput = reinterpret_cast(vmBindInput->syncs)[0]; + syncInputs.push_back(syncInput); + } + } break; + + case DrmIoctl::gemWaitUserFence: { + ret = waitUserFenceReturn; + auto waitUserFenceInput = static_cast(arg); + waitUserFenceInputs.push_back(*waitUserFenceInput); + handleUserFenceWaitExtensions(waitUserFenceInput); + } break; + + case DrmIoctl::gemContextCreateExt: { + auto queueCreate = static_cast(arg); + latestExecQueueCreate = *queueCreate; + latestQueueEngineClassInstances.clear(); + + auto instances = reinterpret_cast(queueCreate->instances); + + for (uint16_t i = 0; i < queueCreate->num_placements; i++) { + latestQueueEngineClassInstances.push_back(instances[i]); + } + + auto extension = queueCreate->extensions; + while (extension) { + auto ext = reinterpret_cast(extension); + if (ext->name == DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY) { + auto setProperty = reinterpret_cast(ext); + execQueueProperties.push_back(*setProperty); + } + handleContextCreateExtensions(ext); + extension = ext->next_extension; + } + queueCreate->exec_queue_id = ++mockExecQueueId; + ret = 0; + } break; + case DrmIoctl::gemContextDestroy: { + gemDestroyContextCalled++; + ret = 0; + } break; + case DrmIoctl::perfOpen: { + ret = 0; + } break; + case DrmIoctl::gemContextSetparam: + case DrmIoctl::gemContextGetparam: + + default: + break; + } + return ret; + } + virtual void handleUserFenceWaitExtensions(drm_xe_wait_user_fence *userFenceWait) {} + virtual void handleContextCreateExtensions(drm_xe_user_extension *extension) {} + + void addMockedQueryTopologyData(uint16_t gtId, uint16_t maskType, uint32_t nBytes, const std::vector &mask) { + ASSERT_EQ(nBytes, mask.size()); + + auto additionalSize = 8u + nBytes; + auto oldSize = queryTopology.size(); + auto newSize = oldSize + additionalSize; + queryTopology.resize(newSize, 0u); + + uint8_t *dataPtr = queryTopology.data() + oldSize; + + drm_xe_query_topology_mask *topo = reinterpret_cast(dataPtr); + topo->gt_id = gtId; + topo->type = maskType; + topo->num_bytes = nBytes; + + memcpy_s(reinterpret_cast(topo->mask), nBytes, mask.data(), nBytes); + } + + int forceIoctlAnswer = 0; + int setIoctlAnswer = 0; + int gemVmBindReturn = 0; + GemClose passedGemClose{}; + int gemCloseCalled = 0; + int gemMmapOffsetCalled = 0; + int gemDestroyContextCalled = 0; + + uint64_t queryConfig[7]{}; // 1 qword for num params and 1 qwords per param + uint32_t mockExecQueueId = 1234; + static constexpr int32_t mockMaxExecQueuePriority = 3; + static constexpr int32_t mockDefaultCxlType = 0; + static constexpr uint32_t mockTimestampFrequency = 12500000; + static_assert(sizeof(drm_xe_engine) == 4 * sizeof(uint64_t), ""); + uint64_t queryEngines[52]{}; // 1 qword for num engines and 4 qwords per engine + static_assert(sizeof(drm_xe_mem_region) == 11 * sizeof(uint64_t), ""); + uint64_t queryMemUsage[34]{}; // 1 qword for num regions and 11 qwords per region + static_assert(sizeof(drm_xe_gt) == 12 * sizeof(uint64_t), ""); + StackVec queryGtList{}; // 1 qword for num gts and 12 qwords per gt + alignas(64) std::vector queryTopology; + static_assert(sizeof(drm_xe_query_engine_cycles) == 5 * sizeof(uint64_t), ""); + uint64_t queryEngineCycles[5]{}; // 1 qword for eci and 4 qwords + StackVec waitUserFenceInputs; + StackVec vmBindInputs; + StackVec syncInputs; + StackVec execQueueProperties; + drm_xe_exec_queue_create latestExecQueueCreate = {}; + std::vector latestQueueEngineClassInstances; + + int waitUserFenceReturn = 0; + int execQueueBanPropertyReturn = 0; + uint32_t createParamsFlags = 0u; + uint16_t createParamsCpuCaching = 0u; + uint32_t createParamsPlacement = 0u; + bool ioctlCalled = false; + bool forceMmapOffsetFail = false; + + DrmMockXeCcs(RootDeviceEnvironment &rootDeviceEnvironment) + : DrmMockCustom(std::make_unique(mockFd, mockPciPath), rootDeviceEnvironment) {} + + virtual void initInstance() { + this->reset(); + auto &gfxCoreHelper = rootDeviceEnvironment.getHelper(); + this->ioctlExpected.contextCreate = static_cast(gfxCoreHelper.getGpgpuEngineInstances(rootDeviceEnvironment).size()); + this->ioctlExpected.contextDestroy = this->ioctlExpected.contextCreate.load(); + + this->ioctlHelper = std::make_unique(*this); + + this->createVirtualMemoryAddressSpace(NEO::GfxCoreHelper::getSubDevicesCount(rootDeviceEnvironment.getHardwareInfo())); + this->isVmBindAvailable(); + + auto xeQueryConfig = reinterpret_cast(this->queryConfig); + xeQueryConfig->num_params = 6; + xeQueryConfig->info[DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID] = 0; // this should be queried by ioctl sys call + xeQueryConfig->info[DRM_XE_QUERY_CONFIG_VA_BITS] = 48; + xeQueryConfig->info[DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY] = mockMaxExecQueuePriority; + + constexpr drm_xe_gt tile0MainGt = { + .type = DRM_XE_QUERY_GT_TYPE_MAIN, + .tile_id = 0, + .gt_id = 0, + .pad = {0}, + .reference_clock = mockTimestampFrequency, + .near_mem_regions = 0b100, + .far_mem_regions = 0x011, + }; + + constexpr drm_xe_gt tile1MediaGt = { + .type = DRM_XE_QUERY_GT_TYPE_MEDIA, + .tile_id = 1, + .gt_id = 1, + .pad = {0}, + .reference_clock = mockTimestampFrequency, + .near_mem_regions = 0b001, + .far_mem_regions = 0x110, + }; + + constexpr drm_xe_gt tile1MainGt = { + .type = DRM_XE_QUERY_GT_TYPE_MAIN, + .tile_id = 1, + .gt_id = 2, + .pad = {0}, + .reference_clock = mockTimestampFrequency, + .near_mem_regions = 0b010, + .far_mem_regions = 0x101, + }; + + constexpr drm_xe_gt tile2MainGt = { + .type = DRM_XE_QUERY_GT_TYPE_MAIN, + .tile_id = 2, + .gt_id = 3, + .pad = {0}, + .reference_clock = mockTimestampFrequency, + .near_mem_regions = 0b100, + .far_mem_regions = 0x011, + }; + + auto xeQueryEngines = reinterpret_cast(this->queryEngines); + xeQueryEngines->num_engines = 11; + xeQueryEngines->engines[0] = {{DRM_XE_ENGINE_CLASS_RENDER, 0, tile0MainGt.gt_id}, {}}; + xeQueryEngines->engines[1] = {{DRM_XE_ENGINE_CLASS_COPY, 1, tile0MainGt.gt_id}, {}}; + xeQueryEngines->engines[2] = {{DRM_XE_ENGINE_CLASS_COPY, 2, tile0MainGt.gt_id}, {}}; + xeQueryEngines->engines[3] = {{DRM_XE_ENGINE_CLASS_COMPUTE, 3, tile0MainGt.gt_id}, {}}; + xeQueryEngines->engines[4] = {{DRM_XE_ENGINE_CLASS_COMPUTE, 4, tile0MainGt.gt_id}, {}}; + xeQueryEngines->engines[5] = {{DRM_XE_ENGINE_CLASS_COMPUTE, 5, tile1MainGt.gt_id}, {}}; + xeQueryEngines->engines[6] = {{DRM_XE_ENGINE_CLASS_COMPUTE, 6, tile1MainGt.gt_id}, {}}; + xeQueryEngines->engines[7] = {{DRM_XE_ENGINE_CLASS_COMPUTE, 7, tile1MainGt.gt_id}, {}}; + xeQueryEngines->engines[8] = {{DRM_XE_ENGINE_CLASS_COMPUTE, 8, tile1MainGt.gt_id}, {}}; + xeQueryEngines->engines[9] = {{DRM_XE_ENGINE_CLASS_VIDEO_DECODE, 9, tile1MainGt.gt_id}, {}}; + xeQueryEngines->engines[10] = {{DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE, 10, tile0MainGt.gt_id}, {}}; + + auto xeQueryMemUsage = reinterpret_cast(this->queryMemUsage); + xeQueryMemUsage->num_mem_regions = 3; + xeQueryMemUsage->mem_regions[0] = { + DRM_XE_MEM_REGION_CLASS_VRAM, // class + 1, // instance + MemoryConstants::pageSize, // min page size + 2 * MemoryConstants::gigaByte, // total size + MemoryConstants::megaByte // used size + }; + xeQueryMemUsage->mem_regions[1] = { + DRM_XE_MEM_REGION_CLASS_SYSMEM, // class + 0, // instance + MemoryConstants::pageSize, // min page size + MemoryConstants::gigaByte, // total size + MemoryConstants::kiloByte // used size + }; + xeQueryMemUsage->mem_regions[2] = { + DRM_XE_MEM_REGION_CLASS_VRAM, // class + 2, // instance + MemoryConstants::pageSize, // min page size + 4 * MemoryConstants::gigaByte, // total size + MemoryConstants::gigaByte // used size + }; + + this->queryGtList.resize(1 + (6 * 12)); // 1 qword for num gts and 12 qwords per gt + auto xeQueryGtList = reinterpret_cast(this->queryGtList.begin()); + xeQueryGtList->num_gt = 4; + xeQueryGtList->gt_list[0] = tile0MainGt; + xeQueryGtList->gt_list[1] = tile1MediaGt; + xeQueryGtList->gt_list[2] = tile1MainGt; + xeQueryGtList->gt_list[3] = tile2MainGt; + this->reset(); + } +}; + +class CcsModeXeFixture { + public: + void setUp() { + executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + executionEnvironment->rootDeviceEnvironments[0]->setHwInfoAndInitHelpers(defaultHwInfo.get()); + + drm = new DrmMockXeCcs(*executionEnvironment->rootDeviceEnvironments[0]); + drm->initInstance(); + + executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new OSInterface()); + osInterface = executionEnvironment->rootDeviceEnvironments[0]->osInterface.get(); + osInterface->setDriverModel(std::unique_ptr(drm)); + } + + void tearDown() { + } + + DrmMockXeCcs *drm; + OSInterface *osInterface; + std::unique_ptr executionEnvironment; +}; + +using CcsModeXeTest = Test; + +TEST_F(CcsModeXeTest, GivenXeDrmAndInvalidCcsModeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + // On Xe, path is /sys/class/drm/card0/device/tile*/gt*/ccs_mode + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("unknown"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + DebugManagerStateRestore restorer; + executionEnvironment->configureCcsMode(); + EXPECT_EQ(1u, ccsMode); + + debugManager.flags.ZEX_NUMBER_OF_CCS.set("abc"); + executionEnvironment->configureCcsMode(); + EXPECT_EQ(1u, ccsMode); + + debugManager.flags.ZEX_NUMBER_OF_CCS.set(""); + executionEnvironment->configureCcsMode(); + EXPECT_EQ(1u, ccsMode); + + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndValidCcsModeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsProperlyConfigured) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + // On Xe, path is /sys/class/drm/card0/device/tile*/gt*/ccs_mode + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card1"); + directoryFilesMap["/sys/class/drm"].push_back("version"); + + directoryFilesMap["/sys/class/drm/card0/device/tile"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile"].push_back("/sys/class/drm/card0/device/tile0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + executionEnvironment->configureCcsMode(); + + EXPECT_EQ(2u, ccsMode); + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndValidCcsModeAndOpenSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + directoryFilesMap["/sys/class/drm"] = {"/sys/class/drm/card0"}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {"/sys/class/drm/card0/device/tile0/gt0"}; + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = -ENOENT; + return -1; + }); + + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + executionEnvironment->configureCcsMode(); + + EXPECT_EQ(1u, ccsMode); + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndValidCcsModeAndOpenSysCallFailsWithNoPermissionsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card1"); + + directoryFilesMap["/sys/class/drm/card0/device/tile"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile"].push_back("/sys/class/drm/card0/device/tile0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = -EPERM; + return -1; + }); + + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + DebugManagerStateRestore restorer; + + testing::internal::CaptureStdout(); + testing::internal::CaptureStderr(); + + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + executionEnvironment->configureCcsMode(); + + std::string stdOutString = testing::internal::GetCapturedStdout(); + std::string stdErrString = testing::internal::GetCapturedStderr(); + std::string expectedOutput = "No read and write permissions for /sys/class/drm/card0/device/tile0/gt0/ccs_mode, System administrator needs to grant permissions to allow modification of this file from user space\n"; + + EXPECT_EQ(1u, ccsMode); + EXPECT_STREQ(stdOutString.c_str(), expectedOutput.c_str()); + EXPECT_STREQ(stdErrString.c_str(), expectedOutput.c_str()); + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndNumCCSFlagSetToCurrentConfigurationWhenConfigureCcsModeIsCalledThenVerifyWriteCallIsNotInvoked) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card1"); + + directoryFilesMap["/sys/class/drm/card0/device/tile"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile"].push_back("/sys/class/drm/card0/device/tile0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + SysCalls::writeFuncCalled = 0u; + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + SysCalls::writeFuncCalled++; + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("1"); + executionEnvironment->configureCcsMode(); + + EXPECT_EQ(1u, ccsMode); + EXPECT_EQ(0u, SysCalls::writeFuncCalled); + SysCalls::writeFuncCalled = 0u; + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndValidCcsModeAndOpenSysCallFailsWithNoAccessWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card1"); + + directoryFilesMap["/sys/class/drm/card0/device/tile"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile"].push_back("/sys/class/drm/card0/device/tile0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + errno = -EACCES; + return -1; + }); + + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + DebugManagerStateRestore restorer; + + testing::internal::CaptureStdout(); + testing::internal::CaptureStderr(); + + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + executionEnvironment->configureCcsMode(); + + std::string stdOutString = testing::internal::GetCapturedStdout(); + std::string stdErrString = testing::internal::GetCapturedStderr(); + std::string expectedOutput = "No read and write permissions for /sys/class/drm/card0/device/tile0/gt0/ccs_mode, System administrator needs to grant permissions to allow modification of this file from user space\n"; + + EXPECT_EQ(1u, ccsMode); + EXPECT_STREQ(stdOutString.c_str(), expectedOutput.c_str()); + EXPECT_STREQ(stdErrString.c_str(), expectedOutput.c_str()); + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndNumCCSFlagSetToCurrentConfigurationAndReadSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card1"); + + directoryFilesMap["/sys/class/drm/card0/device/tile"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile"].push_back("/sys/class/drm/card0/device/tile0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + SysCalls::writeFuncCalled = 0u; + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + SysCalls::writeFuncCalled++; + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + return -1; + }); + + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + executionEnvironment->configureCcsMode(); + + EXPECT_EQ(1u, ccsMode); + EXPECT_EQ(0u, SysCalls::writeFuncCalled); + SysCalls::writeFuncCalled = 0u; + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndValidCcsModeAndWriteSysCallFailsWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotConfigured) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card1"); + + directoryFilesMap["/sys/class/drm/card0/device/tile"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile"].push_back("/sys/class/drm/card0/device/tile0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + SysCalls::writeFuncCalled = 0u; + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + SysCalls::writeFuncCalled++; + errno = -EAGAIN; + return -1; + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + executionEnvironment->configureCcsMode(); + + EXPECT_NE(2u, ccsMode); + EXPECT_NE(0u, SysCalls::writeFuncCalled); + SysCalls::writeFuncCalled = 0u; + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndWriteSysCallFailsWithEbusyForFirstTimeWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsConfiguredInSecondIteration) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card1"); + + directoryFilesMap["/sys/class/drm/card0/device/tile"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile"].push_back("/sys/class/drm/card0/device/tile0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + SysCalls::writeFuncCalled = 0u; + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + if (SysCalls::writeFuncCalled++ == 0u) { + errno = -EBUSY; + return -1; + } + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + { + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("4"); + executionEnvironment->configureCcsMode(); + + EXPECT_EQ(4u, ccsMode); + EXPECT_NE(0u, SysCalls::writeFuncCalled); + } + SysCalls::writeFuncCalled = 0u; + directoryFilesMap.clear(); +} + +TEST_F(CcsModeXeTest, GivenXeDrmAndValidCcsModeAndOpenCallFailsOnRestoreWhenConfigureCcsModeIsCalledThenVerifyCcsModeIsNotRestored) { + VariableBackup>> directoryFilesMapBackup(&directoryFilesMap); + VariableBackup ccsModeBackup(&ccsMode); + + // On Xe, path is /sys/class/drm/card0/device/tile*/gt*/ccs_mode + directoryFilesMap["/sys/class/drm"] = {}; + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card0"); + directoryFilesMap["/sys/class/drm"].push_back("/sys/class/drm/card1"); + + directoryFilesMap["/sys/class/drm/card0/device/tile"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile"].push_back("/sys/class/drm/card0/device/tile0"); + + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"] = {}; + directoryFilesMap["/sys/class/drm/card0/device/tile0/gt"].push_back("/sys/class/drm/card0/device/tile0/gt0"); + + SysCalls::openFuncCalled = 0u; + VariableBackup openBackup(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + if (SysCalls::openFuncCalled == 1u) { + return 1; + } + return -1; + }); + + VariableBackup writeBackup(&SysCalls::sysCallsWrite, [](int fd, const void *buf, size_t count) -> ssize_t { + return mockWrite(fd, buf, count); + }); + + VariableBackup readBackup(&SysCalls::sysCallsRead, [](int fd, void *buf, size_t count) -> ssize_t { + memcpy(buf, &ccsMode, count); + return count; + }); + + { + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + executionEnvironment->configureCcsMode(); + + EXPECT_EQ(2u, ccsMode); + } + + EXPECT_NE(1u, ccsMode); + directoryFilesMap.clear(); +} \ No newline at end of file diff --git a/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt b/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt index 61f8d72388..571246900a 100644 --- a/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt +++ b/shared/test/unit_test/os_interface/wddm_linux/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2021-2022 Intel Corporation +# Copyright (C) 2021-2025 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -8,5 +8,6 @@ if(UNIX AND NOT DISABLE_WDDM_LINUX) target_sources(neo_shared_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/configure_device_address_space_drm_or_wddm_test.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ccs_mode_drm_or_wddm_test.cpp ) -endif() \ No newline at end of file +endif() diff --git a/shared/test/unit_test/os_interface/wddm_linux/ccs_mode_drm_or_wddm_test.cpp b/shared/test/unit_test/os_interface/wddm_linux/ccs_mode_drm_or_wddm_test.cpp new file mode 100644 index 0000000000..00d90f8591 --- /dev/null +++ b/shared/test/unit_test/os_interface/wddm_linux/ccs_mode_drm_or_wddm_test.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/gmm_helper/gmm_helper.h" +#include "shared/source/helpers/hw_info.h" +#include "shared/source/memory_manager/gfx_partition.h" +#include "shared/source/os_interface/windows/gdi_interface.h" +#include "shared/source/os_interface/windows/os_environment_win.h" +#include "shared/source/os_interface/windows/wddm/um_km_data_translator.h" +#include "shared/source/os_interface/windows/wddm/wddm.h" +#include "shared/source/os_interface/windows/wddm_memory_manager.h" +#include "shared/test/common/helpers/debug_manager_state_restore.h" +#include "shared/test/common/helpers/default_hw_info.h" +#include "shared/test/common/helpers/variable_backup.h" +#include "shared/test/common/mocks/mock_execution_environment.h" +#include "shared/test/common/mocks/mock_gmm.h" +#include "shared/test/common/mocks/mock_gmm_client_context.h" + +#include "gmm_memory.h" + +static uint32_t ccsMode = 1u; + +struct MockWddmLinux : NEO::Wddm { + MockWddmLinux(std::unique_ptr hwDeviceId, NEO::RootDeviceEnvironment &rootDeviceEnvironment) + : NEO::Wddm(std::move(hwDeviceId), rootDeviceEnvironment) { + constexpr uint64_t gfxHeap32Size = 4 * MemoryConstants::gigaByte; // 4GB + gfxPartition.SVM.Base = 0; + gfxPartition.SVM.Limit = MemoryConstants::max64BitAppAddress + 1; + decltype(gfxPartition.SVM) *precHeap = &gfxPartition.SVM; + for (auto heap : {&gfxPartition.Heap32[0], &gfxPartition.Heap32[1], &gfxPartition.Heap32[2], &gfxPartition.Heap32[3], &gfxPartition.Standard, &gfxPartition.Standard64KB}) { + heap->Base = precHeap->Limit; + heap->Limit = heap->Base + gfxHeap32Size; + precHeap = heap; + } + UNRECOVERABLE_IF(!isAligned(precHeap->Limit)); + } + + bool reserveValidAddressRange(size_t size, void *&reservedMem) override { + if (validAddressBase + size > MemoryConstants::max64BitAppAddress) { + validAddressRangeReservations.push_back(std::make_tuple(size, reservedMem, false)); + return false; + } + reservedMem = reinterpret_cast(validAddressBase); + validAddressBase += size; + validAddressRangeReservations.push_back(std::make_tuple(size, reservedMem, true)); + return true; + } + + void releaseReservedAddress(void *reservedAddress) override { + Wddm::releaseReservedAddress(reservedAddress); + validAddressRangeReleases.push_back(reservedAddress); + } + + uintptr_t validAddressBase = 128U * MemoryConstants::megaByte + 4U; // intentionally only DWORD alignment to improve alignment testing + std::vector> validAddressRangeReservations; + std::vector validAddressRangeReleases; + + using Wddm::featureTable; + using Wddm::getReadOnlyFlagValue; + using Wddm::gfxPartition; + using Wddm::gfxPlatform; + using Wddm::gmmMemory; + using Wddm::isReadOnlyFlagFallbackSupported; +}; + +struct WddmLinuxMockHwDeviceIdWddm : public NEO::HwDeviceIdWddm { + using HwDeviceIdWddm::HwDeviceIdWddm; + using HwDeviceIdWddm::umKmDataTranslator; +}; + +struct MockGmmMemoryWddmLinux : NEO::GmmMemory { + MockGmmMemoryWddmLinux(NEO::GmmClientContext *gmmClientContext) : NEO::GmmMemory(gmmClientContext) { + } + + bool setDeviceInfo(GMM_DEVICE_INFO *deviceInfo) override { + return true; + } +}; + +struct CcsModeWddmLinuxTest : public ::testing::Test { + void SetUp() override { + osEnvironment = std::make_unique(); + auto hwDeviceIdIn = std::make_unique(NULL_HANDLE, LUID{}, 1u, osEnvironment.get(), std::make_unique()); + this->hwDeviceId = hwDeviceIdIn.get(); + auto &rootDeviceEnvironment = *mockExecEnv.rootDeviceEnvironments[0]; + auto wddm = std::make_unique(std::move(hwDeviceIdIn), rootDeviceEnvironment); + this->wddm = wddm.get(); + auto gmmHelper = rootDeviceEnvironment.getGmmHelper(); + + wddm->gmmMemory = std::make_unique(gmmHelper->getClientContext()); + static_cast(*wddm->gfxPlatform) = NEO::defaultHwInfo->platform; + + rootDeviceEnvironment.osInterface.reset(new NEO::OSInterface); + rootDeviceEnvironment.osInterface->setDriverModel(std::move(wddm)); + } + + std::unique_ptr osEnvironment; + NEO::MockExecutionEnvironment mockExecEnv; + MockWddmLinux *wddm = nullptr; + WddmLinuxMockHwDeviceIdWddm *hwDeviceId = nullptr; +}; + +TEST_F(CcsModeWddmLinuxTest, GivenValidCcsModeWhenConfigureCcsModeIsCalledWithWddmDriverModelThenVerifyCcsModeIsNotConfigured) { + VariableBackup ccsModeBackup(&ccsMode); + DebugManagerStateRestore restorer; + debugManager.flags.ZEX_NUMBER_OF_CCS.set("2"); + + std::unique_ptr osInterface = std::make_unique(); + + mockExecEnv.configureCcsMode(); + EXPECT_EQ(1u, ccsMode); +}