From f9e4381c1e83231d8119f25f6c4bad39eeeea48c Mon Sep 17 00:00:00 2001 From: "Bari, Pratik" Date: Wed, 9 Aug 2023 09:03:06 +0000 Subject: [PATCH] feature: Add FsAccess and Derived class in Sysman Kmd Interface - The FsAccess, ProcFsAccess and SysfsAccess classes have been added in a file in the Sysman Shared directory. The instances of these classes are maintained in the Sysman Kmd Interface classes. - Added functions for opendir, readdir and closedir in the shared code. - Added a ULT in the sysman directory to cover these new functions from the shared code. Related-To: LOCI-4689 Signed-off-by: Bari, Pratik --- .../sysman/source/shared/linux/CMakeLists.txt | 2 + .../linux/sysman_fs_access_interface.cpp | 553 ++++++++++++++++++ .../shared/linux/sysman_fs_access_interface.h | 146 +++++ .../shared/linux/sysman_kmd_interface.cpp | 42 ++ .../shared/linux/sysman_kmd_interface.h | 22 +- .../unit_tests/sources/linux/test_sysman.cpp | 36 ++ .../linux/os_frequency_imp_prelim.cpp | 58 +- .../frequency/linux/os_frequency_imp_prelim.h | 6 - .../source/sysman/linux/os_sysman_imp.cpp | 3 - .../tools/source/sysman/linux/os_sysman_imp.h | 8 - .../linux/test_zes_frequency_prelim.cpp | 45 -- shared/source/os_interface/linux/sys_calls.h | 3 + .../os_interface/linux/sys_calls_linux.cpp | 12 + .../linux/sys_calls_linux_ult.cpp | 33 ++ .../os_interface/linux/sys_calls_linux_ult.h | 3 + 15 files changed, 879 insertions(+), 93 deletions(-) create mode 100644 level_zero/sysman/source/shared/linux/sysman_fs_access_interface.cpp create mode 100644 level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h diff --git a/level_zero/sysman/source/shared/linux/CMakeLists.txt b/level_zero/sysman/source/shared/linux/CMakeLists.txt index fbdd5d0d3d..7c645cae67 100644 --- a/level_zero/sysman/source/shared/linux/CMakeLists.txt +++ b/level_zero/sysman/source/shared/linux/CMakeLists.txt @@ -8,6 +8,8 @@ if(UNIX) target_sources(${L0_STATIC_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/sysman_kmd_interface.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sysman_fs_access_interface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sysman_kmd_interface.h + ${CMAKE_CURRENT_SOURCE_DIR}/sysman_fs_access_interface.h ) endif() diff --git a/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.cpp b/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.cpp new file mode 100644 index 0000000000..db15af5ed0 --- /dev/null +++ b/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.cpp @@ -0,0 +1,553 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h" + +#include +#include +#include +#include +#include + +namespace L0 { +namespace Sysman { + +FsAccessInterface::~FsAccessInterface() = default; + +static ze_result_t getResult(int err) { + if ((EPERM == err) || (EACCES == err)) { + return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; + } else if (ENOENT == err) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } else if (EBUSY == err) { + return ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE; + } else { + return ZE_RESULT_ERROR_UNKNOWN; + } +} + +void FdCacheInterface::eraseLeastUsedEntryFromCache() { + auto it = fdMap.begin(); + uint32_t fdCountRef = it->second.second; + std::map>::iterator leastUsedIterator = it; + while (++it != fdMap.end()) { + if (it->second.second < fdCountRef) { + fdCountRef = it->second.second; + leastUsedIterator = it; + } + } + NEO::SysCalls::close(leastUsedIterator->second.first); + fdMap.erase(leastUsedIterator); +} + +int FdCacheInterface::getFd(std::string file) { + int fd = -1; + if (fdMap.find(file) == fdMap.end()) { + fd = NEO::SysCalls::open(file.c_str(), O_RDONLY); + if (fd < 0) { + return -1; + } + if (fdMap.size() == maxSize) { + eraseLeastUsedEntryFromCache(); + } + fdMap[file] = std::make_pair(fd, 1); + } else { + auto &fdPair = fdMap[file]; + fdPair.second++; + } + return fdMap[file].first; +} + +FdCacheInterface::~FdCacheInterface() { + for (auto it = fdMap.begin(); it != fdMap.end(); ++it) { + NEO::SysCalls::close(it->second.second); + } + fdMap.clear(); +} + +template +ze_result_t FsAccessInterface::readValue(const std::string file, T &val) { + + std::string readVal(64, '\0'); + int fd = pFdCacheInterface->getFd(file); + if (fd < 0) { + return getResult(errno); + } + + ssize_t bytesRead = NEO::SysCalls::pread(fd, readVal.data(), readVal.size(), 0); + if (bytesRead < 0) { + return getResult(errno); + } + + std::istringstream stream(readVal); + stream >> val; + if (stream.fail()) { + return ZE_RESULT_ERROR_UNKNOWN; + } + + return ZE_RESULT_SUCCESS; +} + +// Generic Filesystem Access +FsAccessInterface::FsAccessInterface() { + pFdCacheInterface = std::make_unique(); +} + +std::unique_ptr FsAccessInterface::create() { + return std::unique_ptr(new FsAccessInterface()); +} + +ze_result_t FsAccessInterface::read(const std::string file, uint64_t &val) { + return readValue(file, val); +} + +ze_result_t FsAccessInterface::read(const std::string file, double &val) { + return readValue(file, val); +} + +ze_result_t FsAccessInterface::read(const std::string file, int32_t &val) { + return readValue(file, val); +} + +ze_result_t FsAccessInterface::read(const std::string file, uint32_t &val) { + return readValue(file, val); +} + +ze_result_t FsAccessInterface::read(const std::string file, std::string &val) { + // Read a single line from text file without trailing newline + std::ifstream fs; + val.clear(); + + fs.open(file.c_str()); + if (fs.fail()) { + return getResult(errno); + } + fs >> val; + if (fs.fail()) { + fs.close(); + return getResult(errno); + } + fs.close(); + // Strip trailing newline + if (val.back() == '\n') { + val.pop_back(); + } + return ZE_RESULT_SUCCESS; +} + +ze_result_t FsAccessInterface::read(const std::string file, std::vector &val) { + // Read a entire text file, one line per vector entry + std::string line; + std::ifstream fs; + val.clear(); + + fs.open(file.c_str()); + if (fs.fail()) { + return getResult(errno); + } + while (std::getline(fs, line)) { + if (fs.fail()) { + fs.close(); + return getResult(errno); + } + if (line.back() == '\n') { + line.pop_back(); + } + val.push_back(line); + } + fs.close(); + + return ZE_RESULT_SUCCESS; +} + +ze_result_t FsAccessInterface::write(const std::string file, const std::string val) { + int fd = NEO::SysCalls::open(file.c_str(), O_WRONLY); + if (fd < 0) { + return getResult(errno); + } + + ssize_t bytesWritten = NEO::SysCalls::pwrite(fd, val.data(), val.size(), 0); + NEO::SysCalls::close(fd); + if (bytesWritten < 0) { + return getResult(errno); + } + + if (bytesWritten != static_cast(val.size())) { + return ZE_RESULT_ERROR_UNKNOWN; + } + + return ZE_RESULT_SUCCESS; +} + +ze_result_t FsAccessInterface::canRead(const std::string file) { + struct stat sb; + if (statSyscall(file.c_str(), &sb) != 0) { + return ZE_RESULT_ERROR_UNKNOWN; + } + if (sb.st_mode & S_IRUSR) { + return ZE_RESULT_SUCCESS; + } + return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; +} + +ze_result_t FsAccessInterface::canWrite(const std::string file) { + struct stat sb; + if (statSyscall(file.c_str(), &sb) != 0) { + return ZE_RESULT_ERROR_UNKNOWN; + } + if (sb.st_mode & S_IWUSR) { + return ZE_RESULT_SUCCESS; + } + return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; +} + +bool FsAccessInterface::fileExists(const std::string file) { + if (NEO::SysCalls::access(file.c_str(), F_OK)) { + return false; + } + return true; +} + +ze_result_t FsAccessInterface::getFileMode(const std::string file, ::mode_t &mode) { + struct stat sb; + if (0 != statSyscall(file.c_str(), &sb)) { + return getResult(errno); + } + mode = sb.st_mode; + return ZE_RESULT_SUCCESS; +} + +ze_result_t FsAccessInterface::readSymLink(const std::string path, std::string &val) { + // returns the value of symlink at path + char buf[PATH_MAX]; + ssize_t len = NEO::SysCalls::readlink(path.c_str(), buf, PATH_MAX - 1); + if (len < 0) { + return getResult(errno); + } + buf[len] = '\0'; + val = std::string(buf); + return ZE_RESULT_SUCCESS; +} + +ze_result_t FsAccessInterface::getRealPath(const std::string path, std::string &val) { + // returns the real file path after resolving all symlinks in path + char buf[PATH_MAX]; + char *realPath = NEO::SysCalls::realpath(path.c_str(), buf); + if (!realPath) { + return getResult(errno); + } + val = std::string(buf); + return ZE_RESULT_SUCCESS; +} + +ze_result_t FsAccessInterface::listDirectory(const std::string path, std::vector &list) { + list.clear(); + ::DIR *procDir = NEO::SysCalls::opendir(path.c_str()); + if (!procDir) { + return getResult(errno); + } + struct ::dirent *ent; + int err = 0; + // readdir doesn't clear errno, so make sure it is clear + errno = 0; + while (NULL != (ent = NEO::SysCalls::readdir(procDir))) { + // Ignore . and .. + std::string name = std::string(ent->d_name); + if (!name.compare(".") || !name.compare("..")) { + errno = 0; + continue; + } + list.push_back(std::string(ent->d_name)); + errno = 0; + } + err = errno; + NEO::SysCalls::closedir(procDir); + // Check if in above while loop, readdir encountered any error. + if ((err != 0) && (err != ENOENT)) { + list.clear(); + return getResult(err); + } + return ZE_RESULT_SUCCESS; +} + +std::string FsAccessInterface::getBaseName(const std::string path) { + size_t pos = path.rfind("/"); + if (std::string::npos == pos) { + return path; + } + return path.substr(pos + 1, std::string::npos); +} + +std::string FsAccessInterface::getDirName(const std::string path) { + size_t pos = path.rfind("/"); + if (std::string::npos == pos) { + return std::string(""); + } + // Include trailing slash + return path.substr(0, pos); +} + +bool FsAccessInterface::isRootUser() { + return (geteuid() == 0); +} + +bool FsAccessInterface::directoryExists(const std::string path) { + if (accessSyscall(path.c_str(), F_OK)) { + return false; + } + return true; +} + +// Procfs Access +ProcFsAccessInterface::ProcFsAccessInterface() = default; +ProcFsAccessInterface::~ProcFsAccessInterface() = default; + +const std::string ProcFsAccessInterface::procDir = "/proc/"; +const std::string ProcFsAccessInterface::fdDir = "/fd/"; + +std::string ProcFsAccessInterface::fullPath(const ::pid_t pid) { + // Returns the full path for proc entry for process pid + return std::string(procDir + std::to_string(pid)); +} + +std::string ProcFsAccessInterface::fdDirPath(const ::pid_t pid) { + // Returns the full path to file descritpor directory + // for process pid + return std::string(fullPath(pid) + fdDir); +} + +std::string ProcFsAccessInterface::fullFdPath(const ::pid_t pid, const int fd) { + // Returns the full path for filedescriptor fd + // for process pid + return std::string(fdDirPath(pid) + std::to_string(fd)); +} + +std::unique_ptr ProcFsAccessInterface::create() { + return std::unique_ptr(new ProcFsAccessInterface()); +} + +ze_result_t ProcFsAccessInterface::listProcesses(std::vector<::pid_t> &list) { + // Returns a vector with all the active process ids in the system + list.clear(); + std::vector dir; + ze_result_t result = FsAccessInterface::listDirectory(procDir, dir); + if (ZE_RESULT_SUCCESS != result) { + return result; + } + for (auto &&file : dir) { + ::pid_t pid; + std::istringstream stream(file); + stream >> pid; + if (stream.fail()) { + // Non numeric filename, not a process, skip + continue; + } + list.push_back(pid); + } + return ZE_RESULT_SUCCESS; +} + +ze_result_t ProcFsAccessInterface::getFileDescriptors(const ::pid_t pid, std::vector &list) { + // Returns a vector with all the filedescriptor numbers opened by a pid + list.clear(); + std::vector dir; + ze_result_t result = FsAccessInterface::listDirectory(fdDirPath(pid), dir); + if (ZE_RESULT_SUCCESS != result) { + return result; + } + for (auto &&file : dir) { + int fd; + std::istringstream stream(file); + stream >> fd; + if (stream.fail()) { + // Non numeric filename, not a file descriptor + continue; + } + list.push_back(fd); + } + return ZE_RESULT_SUCCESS; +} + +ze_result_t ProcFsAccessInterface::getFileName(const ::pid_t pid, const int fd, std::string &val) { + // Given a process id and a file descriptor number + // return full name of the open file. + // NOTE: For sockets, the name will be of the format "socket:[nnnnnnn]" + return FsAccessInterface::readSymLink(fullFdPath(pid, fd), val); +} + +bool ProcFsAccessInterface::isAlive(const ::pid_t pid) { + return FsAccessInterface::fileExists(fullPath(pid)); +} + +void ProcFsAccessInterface::kill(const ::pid_t pid) { + ::kill(pid, SIGKILL); +} + +::pid_t ProcFsAccessInterface::myProcessId() { + return ::getpid(); +} + +// Sysfs Access +SysFsAccessInterface::SysFsAccessInterface() = default; +SysFsAccessInterface::~SysFsAccessInterface() = default; + +const std::string SysFsAccessInterface::drmPath = "/sys/class/drm/"; +const std::string SysFsAccessInterface::devicesPath = "device/drm/"; +const std::string SysFsAccessInterface::primaryDevName = "card"; +const std::string SysFsAccessInterface::drmDriverDevNodeDir = "/dev/dri/"; +const std::string SysFsAccessInterface::intelGpuBindEntry = "/sys/bus/pci/drivers/i915/bind"; +const std::string SysFsAccessInterface::intelGpuUnbindEntry = "/sys/bus/pci/drivers/i915/unbind"; + +std::string SysFsAccessInterface::fullPath(const std::string file) { + // Prepend sysfs directory path for this device + return std::string(dirname + file); +} + +SysFsAccessInterface::SysFsAccessInterface(const std::string dev) { + // dev could be either /dev/dri/cardX or /dev/dri/renderDX + std::string fileName = FsAccessInterface::getBaseName(dev); + std::string devicesDir = drmPath + fileName + std::string("/") + devicesPath; + + FsAccessInterface::listDirectory(devicesDir, deviceNames); + for (auto &&next : deviceNames) { + if (!next.compare(0, primaryDevName.length(), primaryDevName)) { + dirname = drmPath + next + std::string("/"); + break; + } + } +} + +std::unique_ptr SysFsAccessInterface::create(const std::string dev) { + return std::unique_ptr(new SysFsAccessInterface(dev)); +} + +ze_result_t SysFsAccessInterface::canRead(const std::string file) { + // Prepend sysfs directory path and call the base canRead + return FsAccessInterface::canRead(fullPath(file)); +} + +ze_result_t SysFsAccessInterface::canWrite(const std::string file) { + // Prepend sysfs directory path and call the base canWrite + return FsAccessInterface::canWrite(fullPath(file)); +} + +ze_result_t SysFsAccessInterface::getFileMode(const std::string file, ::mode_t &mode) { + // Prepend sysfs directory path and call the base getFileMode + return FsAccessInterface::getFileMode(fullPath(file), mode); +} + +ze_result_t SysFsAccessInterface::read(const std::string file, std::string &val) { + // Prepend sysfs directory path and call the base read + return FsAccessInterface::read(fullPath(file).c_str(), val); +} + +ze_result_t SysFsAccessInterface::read(const std::string file, int32_t &val) { + return FsAccessInterface::read(fullPath(file), val); +} + +ze_result_t SysFsAccessInterface::read(const std::string file, uint32_t &val) { + return FsAccessInterface::read(fullPath(file), val); +} + +ze_result_t SysFsAccessInterface::read(const std::string file, double &val) { + return FsAccessInterface::read(fullPath(file), val); +} + +ze_result_t SysFsAccessInterface::read(const std::string file, uint64_t &val) { + return FsAccessInterface::read(fullPath(file), val); +} + +ze_result_t SysFsAccessInterface::read(const std::string file, std::vector &val) { + // Prepend sysfs directory path and call the base read + return FsAccessInterface::read(fullPath(file), val); +} + +ze_result_t SysFsAccessInterface::write(const std::string file, const std::string val) { + // Prepend sysfs directory path and call the base write + return FsAccessInterface::write(fullPath(file).c_str(), val); +} + +ze_result_t SysFsAccessInterface::write(const std::string file, const int val) { + std::ostringstream stream; + stream << val; + + if (stream.fail()) { + return ZE_RESULT_ERROR_UNKNOWN; + } + return FsAccessInterface::write(fullPath(file), stream.str()); +} + +ze_result_t SysFsAccessInterface::write(const std::string file, const double val) { + std::ostringstream stream; + stream << val; + + if (stream.fail()) { + return ZE_RESULT_ERROR_UNKNOWN; + } + return FsAccessInterface::write(fullPath(file), stream.str()); +} + +ze_result_t SysFsAccessInterface::write(const std::string file, const uint64_t val) { + std::ostringstream stream; + stream << val; + + if (stream.fail()) { + return ZE_RESULT_ERROR_UNKNOWN; + } + return FsAccessInterface::write(fullPath(file), stream.str()); +} + +ze_result_t SysFsAccessInterface::scanDirEntries(const std::string path, std::vector &list) { + list.clear(); + return FsAccessInterface::listDirectory(fullPath(path).c_str(), list); +} + +ze_result_t SysFsAccessInterface::readSymLink(const std::string path, std::string &val) { + // Prepend sysfs directory path and call the base readSymLink + return FsAccessInterface::readSymLink(fullPath(path).c_str(), val); +} + +ze_result_t SysFsAccessInterface::getRealPath(const std::string path, std::string &val) { + // Prepend sysfs directory path and call the base getRealPath + return FsAccessInterface::getRealPath(fullPath(path).c_str(), val); +} + +ze_result_t SysFsAccessInterface::bindDevice(std::string device) { + return FsAccessInterface::write(intelGpuBindEntry, device); +} + +ze_result_t SysFsAccessInterface::unbindDevice(std::string device) { + return FsAccessInterface::write(intelGpuUnbindEntry, device); +} + +bool SysFsAccessInterface::fileExists(const std::string file) { + // Prepend sysfs directory path and call the base fileExists + return FsAccessInterface::fileExists(fullPath(file).c_str()); +} + +bool SysFsAccessInterface::directoryExists(const std::string path) { + return FsAccessInterface::directoryExists(fullPath(path).c_str()); +} + +bool SysFsAccessInterface::isMyDeviceFile(const std::string dev) { + // dev is a full pathname. + if (getDirName(dev).compare(drmDriverDevNodeDir)) { + for (auto &&next : deviceNames) { + if (!getBaseName(dev).compare(next)) { + return true; + } + } + } + return false; +} + +bool SysFsAccessInterface::isRootUser() { + return FsAccessInterface::isRootUser(); +} + +} // namespace Sysman +} // namespace L0 \ No newline at end of file diff --git a/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h b/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h new file mode 100644 index 0000000000..309c38219a --- /dev/null +++ b/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/source/os_interface/linux/sys_calls.h" + +#include + +#include +#include +#include + +namespace L0 { +namespace Sysman { + +class FdCacheInterface { + public: + FdCacheInterface() = default; + ~FdCacheInterface(); + + static const int maxSize = 10; + int getFd(std::string file); + + protected: + std::map> fdMap = {}; + + private: + void eraseLeastUsedEntryFromCache(); +}; + +class FsAccessInterface { + public: + static std::unique_ptr create(); + virtual ~FsAccessInterface(); + + virtual ze_result_t canRead(const std::string file); + virtual ze_result_t canWrite(const std::string file); + virtual ze_result_t getFileMode(const std::string file, ::mode_t &mode); + + virtual ze_result_t read(const std::string file, uint64_t &val); + virtual ze_result_t read(const std::string file, std::string &val); + virtual ze_result_t read(const std::string file, std::vector &val); + virtual ze_result_t read(const std::string file, double &val); + virtual ze_result_t read(const std::string file, uint32_t &val); + virtual ze_result_t read(const std::string file, int32_t &val); + + virtual ze_result_t write(const std::string file, const std::string val); + + virtual ze_result_t readSymLink(const std::string path, std::string &buf); + virtual ze_result_t getRealPath(const std::string path, std::string &buf); + virtual ze_result_t listDirectory(const std::string path, std::vector &list); + virtual bool isRootUser(); + std::string getBaseName(const std::string path); + std::string getDirName(const std::string path); + virtual bool fileExists(const std::string file); + virtual bool directoryExists(const std::string path); + + protected: + FsAccessInterface(); + decltype(&NEO::SysCalls::access) accessSyscall = NEO::SysCalls::access; + decltype(&stat) statSyscall = stat; + + private: + template + ze_result_t readValue(const std::string file, T &val); + std::unique_ptr pFdCacheInterface = nullptr; +}; + +class ProcFsAccessInterface : private FsAccessInterface { + public: + static std::unique_ptr create(); + ~ProcFsAccessInterface() override; + + MOCKABLE_VIRTUAL ze_result_t listProcesses(std::vector<::pid_t> &list); + MOCKABLE_VIRTUAL ::pid_t myProcessId(); + MOCKABLE_VIRTUAL ze_result_t getFileDescriptors(const ::pid_t pid, std::vector &list); + MOCKABLE_VIRTUAL ze_result_t getFileName(const ::pid_t pid, const int fd, std::string &val); + MOCKABLE_VIRTUAL bool isAlive(const ::pid_t pid); + MOCKABLE_VIRTUAL void kill(const ::pid_t pid); + + protected: + ProcFsAccessInterface(); + + private: + std::string fullPath(const ::pid_t pid); + std::string fdDirPath(const ::pid_t pid); + std::string fullFdPath(const ::pid_t pid, const int fd); + static const std::string procDir; + static const std::string fdDir; +}; + +class SysFsAccessInterface : protected FsAccessInterface { + public: + static std::unique_ptr create(const std::string file); + ~SysFsAccessInterface() override; + + ze_result_t canRead(const std::string file) override; + ze_result_t canWrite(const std::string file) override; + ze_result_t getFileMode(const std::string file, ::mode_t &mode) override; + + ze_result_t read(const std::string file, std::string &val) override; + ze_result_t read(const std::string file, int32_t &val) override; + ze_result_t read(const std::string file, uint32_t &val) override; + ze_result_t read(const std::string file, uint64_t &val) override; + ze_result_t read(const std::string file, double &val) override; + ze_result_t read(const std::string file, std::vector &val) override; + + ze_result_t write(const std::string file, const std::string val) override; + MOCKABLE_VIRTUAL ze_result_t write(const std::string file, const int val); + MOCKABLE_VIRTUAL ze_result_t write(const std::string file, const uint64_t val); + MOCKABLE_VIRTUAL ze_result_t write(const std::string file, const double val); + ze_result_t write(const std::string file, std::vector val); + + MOCKABLE_VIRTUAL ze_result_t scanDirEntries(const std::string path, std::vector &list); + ze_result_t readSymLink(const std::string path, std::string &buf) override; + ze_result_t getRealPath(const std::string path, std::string &buf) override; + MOCKABLE_VIRTUAL ze_result_t bindDevice(const std::string device); + MOCKABLE_VIRTUAL ze_result_t unbindDevice(const std::string device); + bool fileExists(const std::string file) override; + MOCKABLE_VIRTUAL bool isMyDeviceFile(const std::string dev); + bool directoryExists(const std::string path) override; + bool isRootUser() override; + + protected: + SysFsAccessInterface(); + SysFsAccessInterface(const std::string file); + std::vector deviceNames; + + private: + std::string fullPath(const std::string file); + std::string dirname; + static const std::string drmPath; + static const std::string devicesPath; + static const std::string primaryDevName; + static const std::string drmDriverDevNodeDir; + static const std::string intelGpuBindEntry; + static const std::string intelGpuUnbindEntry; +}; + +} // namespace Sysman +} // namespace L0 \ No newline at end of file diff --git a/level_zero/sysman/source/shared/linux/sysman_kmd_interface.cpp b/level_zero/sysman/source/shared/linux/sysman_kmd_interface.cpp index a25edb927e..3b96279491 100644 --- a/level_zero/sysman/source/shared/linux/sysman_kmd_interface.cpp +++ b/level_zero/sysman/source/shared/linux/sysman_kmd_interface.cpp @@ -13,11 +13,26 @@ #include "shared/source/os_interface/linux/i915_prelim.h" #include "level_zero/sysman/source/linux/pmu/sysman_pmu_imp.h" +#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h" namespace L0 { namespace Sysman { using NEO::PrelimI915::I915_SAMPLE_BUSY; +SysmanKmdInterface::SysmanKmdInterface() = default; + +SysmanKmdInterfaceI915::SysmanKmdInterfaceI915(const PRODUCT_FAMILY productFamily) { + initSysfsNameToFileMap(productFamily); +} + +SysmanKmdInterfaceXe::SysmanKmdInterfaceXe(const PRODUCT_FAMILY productFamily) { + initSysfsNameToFileMap(productFamily); +} + +SysmanKmdInterface::~SysmanKmdInterface() = default; +SysmanKmdInterfaceI915::~SysmanKmdInterfaceI915() = default; +SysmanKmdInterfaceXe::~SysmanKmdInterfaceXe() = default; + std::unique_ptr SysmanKmdInterface::create(const NEO::Drm &drm) { std::unique_ptr pSysmanKmdInterface; auto drmVersion = drm.getDrmVersion(drm.getFileDescriptor()); @@ -32,6 +47,33 @@ std::unique_ptr SysmanKmdInterface::create(const NEO::Drm &d return pSysmanKmdInterface; } +FsAccessInterface *SysmanKmdInterface::getFsAccess() { + + if (nullptr == pFsAccess.get()) { + pFsAccess = FsAccessInterface::create(); + } + UNRECOVERABLE_IF(nullptr == pFsAccess.get()); + return pFsAccess.get(); +} + +ProcFsAccessInterface *SysmanKmdInterface::getProcFsAccess() { + + if (nullptr == pProcfsAccess.get()) { + pProcfsAccess = ProcFsAccessInterface::create(); + } + UNRECOVERABLE_IF(nullptr == pProcfsAccess.get()); + return pProcfsAccess.get(); +} + +SysFsAccessInterface *SysmanKmdInterface::getSysFsAccess(std::string deviceName) { + + if (nullptr == pSysfsAccess.get()) { + pSysfsAccess = SysFsAccessInterface::create(deviceName); + } + UNRECOVERABLE_IF(nullptr == pSysfsAccess.get()); + return pSysfsAccess.get(); +} + std::string SysmanKmdInterfaceI915::getBasePath(uint32_t subDeviceId) const { return "gt/gt" + std::to_string(subDeviceId) + "/"; } diff --git a/level_zero/sysman/source/shared/linux/sysman_kmd_interface.h b/level_zero/sysman/source/shared/linux/sysman_kmd_interface.h index f463c83b8c..09e3dfd3ab 100644 --- a/level_zero/sysman/source/shared/linux/sysman_kmd_interface.h +++ b/level_zero/sysman/source/shared/linux/sysman_kmd_interface.h @@ -21,6 +21,9 @@ class Drm; namespace L0 { namespace Sysman { +class FsAccessInterface; +class ProcFsAccessInterface; +class SysFsAccessInterface; class PmuInterface; typedef std::pair valuePair; @@ -79,7 +82,8 @@ enum class SysfsName { class SysmanKmdInterface { public: - virtual ~SysmanKmdInterface() = default; + SysmanKmdInterface(); + virtual ~SysmanKmdInterface(); static std::unique_ptr create(const NEO::Drm &drm); virtual std::string getBasePath(uint32_t subDeviceId) const = 0; @@ -89,12 +93,20 @@ class SysmanKmdInterface { virtual std::string getHwmonName(uint32_t subDeviceId, bool isSubdevice) const = 0; virtual bool isStandbyModeControlAvailable() const = 0; virtual bool clientInfoAvailableInFdInfo() = 0; + FsAccessInterface *getFsAccess(); + ProcFsAccessInterface *getProcFsAccess(); + SysFsAccessInterface *getSysFsAccess(std::string deviceName); + + protected: + std::unique_ptr pFsAccess; + std::unique_ptr pProcfsAccess; + std::unique_ptr pSysfsAccess; }; class SysmanKmdInterfaceI915 : public SysmanKmdInterface { public: - SysmanKmdInterfaceI915(const PRODUCT_FAMILY productFamily) { initSysfsNameToFileMap(productFamily); } - ~SysmanKmdInterfaceI915() override = default; + SysmanKmdInterfaceI915(const PRODUCT_FAMILY productFamily); + ~SysmanKmdInterfaceI915() override; std::string getBasePath(uint32_t subDeviceId) const override; std::string getSysfsFilePath(SysfsName sysfsName, uint32_t subDeviceId, bool baseDirectoryExists) override; @@ -111,8 +123,8 @@ class SysmanKmdInterfaceI915 : public SysmanKmdInterface { class SysmanKmdInterfaceXe : public SysmanKmdInterface { public: - SysmanKmdInterfaceXe(const PRODUCT_FAMILY productFamily) { initSysfsNameToFileMap(productFamily); } - ~SysmanKmdInterfaceXe() override = default; + SysmanKmdInterfaceXe(const PRODUCT_FAMILY productFamily); + ~SysmanKmdInterfaceXe() override; std::string getBasePath(uint32_t subDeviceId) const override; std::string getSysfsFilePath(SysfsName sysfsName, uint32_t subDeviceId, bool baseDirectoryExists) override; diff --git a/level_zero/sysman/test/unit_tests/sources/linux/test_sysman.cpp b/level_zero/sysman/test/unit_tests/sources/linux/test_sysman.cpp index 61bd00215f..0c3df6204b 100644 --- a/level_zero/sysman/test/unit_tests/sources/linux/test_sysman.cpp +++ b/level_zero/sysman/test/unit_tests/sources/linux/test_sysman.cpp @@ -8,6 +8,8 @@ #include "shared/test/common/mocks/mock_driver_info.h" #include "shared/test/common/test_macros/test.h" +#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h" +#include "level_zero/sysman/source/shared/linux/sysman_kmd_interface.h" #include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h" namespace NEO { @@ -20,6 +22,12 @@ namespace L0 { namespace Sysman { namespace ult { +struct dirent mockEntries[] = { + {0, 0, 0, 0, "."}, + {0, 0, 0, 0, "mockDir1"}, + {0, 0, 0, 0, "mockDir2"}, +}; + inline static int mockAccessFailure(const char *pathname, int mode) { return -1; } @@ -42,6 +50,34 @@ inline static int mockStatNoPermissions(const char *pathname, struct stat *sb) n return 0; } +TEST_F(SysmanDeviceFixture, GivenValidSysmanKmdInterfaceWhenCallingListDirectoriesThenSuccessIsReturned) { + + auto pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface(); + auto pFsAccess = pSysmanKmdInterface->getFsAccess(); + const uint32_t numEntries = sizeof(mockEntries) / sizeof(mockEntries[0]); + + VariableBackup mockOpendir(&NEO::SysCalls::sysCallsOpendir, [](const char *name) -> DIR * { + return reinterpret_cast(0xc001); + }); + + VariableBackup mockReaddir( + &NEO::SysCalls::sysCallsReaddir, [](DIR * dir) -> struct dirent * { + static uint32_t entryIndex = 0u; + if (entryIndex >= numEntries) { + entryIndex = 0; + return nullptr; + } + return &mockEntries[entryIndex++]; + }); + + VariableBackup mockClosedir(&NEO::SysCalls::sysCallsClosedir, [](DIR *dir) -> int { + return 0; + }); + + std::vector listFiles; + EXPECT_EQ(ZE_RESULT_SUCCESS, pFsAccess->listDirectory("MockDir", listFiles)); +} + TEST_F(SysmanDeviceFixture, GivenCreateFsAccessHandleWhenCallinggetFsAccessThenCreatedFsAccessHandleWillBeRetrieved) { if (pLinuxSysmanImp->pFsAccess != nullptr) { // delete previously allocated pFsAccess diff --git a/level_zero/tools/source/sysman/frequency/linux/os_frequency_imp_prelim.cpp b/level_zero/tools/source/sysman/frequency/linux/os_frequency_imp_prelim.cpp index b9f03ac361..f6ee056b6d 100644 --- a/level_zero/tools/source/sysman/frequency/linux/os_frequency_imp_prelim.cpp +++ b/level_zero/tools/source/sysman/frequency/linux/os_frequency_imp_prelim.cpp @@ -11,15 +11,12 @@ #include "shared/source/device/device.h" #include "shared/source/helpers/hw_info.h" -#include "level_zero/sysman/source/shared/linux/sysman_kmd_interface.h" #include "level_zero/tools/source/sysman/linux/os_sysman_imp.h" #include "igfxfmid.h" #include -using namespace L0::Sysman; - namespace L0 { const bool LinuxFrequencyImp::canControl = true; // canControl is true on i915 (GEN9 Hardcode) @@ -387,37 +384,46 @@ ze_result_t LinuxFrequencyImp::getMinVal(double &minVal) { } void LinuxFrequencyImp::init() { - - const std::string baseDir = pSysmanKmdInterface->getBasePath(subdeviceId); - bool baseDirectoryExists = false; - + const std::string baseDir = "gt/gt" + std::to_string(subdeviceId) + "/"; if (pSysfsAccess->directoryExists(baseDir)) { - baseDirectoryExists = true; + minFreqFile = baseDir + "rps_min_freq_mhz"; + minDefaultFreqFile = baseDir + ".defaults/rps_min_freq_mhz"; + maxFreqFile = baseDir + "rps_max_freq_mhz"; + boostFreqFile = baseDir + "rps_boost_freq_mhz"; + maxDefaultFreqFile = baseDir + ".defaults/rps_max_freq_mhz"; + requestFreqFile = baseDir + "punit_req_freq_mhz"; + tdpFreqFile = baseDir + "rapl_PL1_freq_mhz"; + actualFreqFile = baseDir + "rps_act_freq_mhz"; + efficientFreqFile = baseDir + "rps_RP1_freq_mhz"; + maxValFreqFile = baseDir + "rps_RP0_freq_mhz"; + minValFreqFile = baseDir + "rps_RPn_freq_mhz"; + throttleReasonStatusFile = baseDir + "throttle_reason_status"; + throttleReasonPL1File = baseDir + "throttle_reason_pl1"; + throttleReasonPL2File = baseDir + "throttle_reason_pl2"; + throttleReasonPL4File = baseDir + "throttle_reason_pl4"; + throttleReasonThermalFile = baseDir + "throttle_reason_thermal"; + } else { + minFreqFile = "gt_min_freq_mhz"; + maxFreqFile = "gt_max_freq_mhz"; + boostFreqFile = "gt_boost_freq_mhz"; + requestFreqFile = "gt_cur_freq_mhz"; + tdpFreqFile = "rapl_PL1_freq_mhz"; + actualFreqFile = "gt_act_freq_mhz"; + efficientFreqFile = "gt_RP1_freq_mhz"; + maxValFreqFile = "gt_RP0_freq_mhz"; + minValFreqFile = "gt_RPn_freq_mhz"; + throttleReasonStatusFile = "gt_throttle_reason_status"; + throttleReasonPL1File = "gt_throttle_reason_status_pl1"; + throttleReasonPL2File = "gt_throttle_reason_status_pl2"; + throttleReasonPL4File = "gt_throttle_reason_status_pl4"; + throttleReasonThermalFile = "gt_throttle_reason_status_thermal"; } - - minFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinFrequency, subdeviceId, baseDirectoryExists); - minDefaultFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinDefaultFrequency, subdeviceId, baseDirectoryExists); - maxFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxFrequency, subdeviceId, baseDirectoryExists); - maxDefaultFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxDefaultFrequency, subdeviceId, baseDirectoryExists); - boostFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameBoostFrequency, subdeviceId, baseDirectoryExists); - requestFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameCurrentFrequency, subdeviceId, baseDirectoryExists); - tdpFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameTdpFrequency, subdeviceId, baseDirectoryExists); - actualFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameActualFrequency, subdeviceId, baseDirectoryExists); - efficientFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameEfficientFrequency, subdeviceId, baseDirectoryExists); - maxValFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxValueFrequency, subdeviceId, baseDirectoryExists); - minValFreqFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinValueFrequency, subdeviceId, baseDirectoryExists); - throttleReasonStatusFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonStatus, subdeviceId, baseDirectoryExists); - throttleReasonPL1File = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL1, subdeviceId, baseDirectoryExists); - throttleReasonPL2File = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL2, subdeviceId, baseDirectoryExists); - throttleReasonPL4File = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL4, subdeviceId, baseDirectoryExists); - throttleReasonThermalFile = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonThermal, subdeviceId, baseDirectoryExists); } LinuxFrequencyImp::LinuxFrequencyImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_freq_domain_t frequencyDomainNumber) : isSubdevice(onSubdevice), subdeviceId(subdeviceId), frequencyDomainNumber(frequencyDomainNumber) { LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); pDevice = Device::fromHandle(pLinuxSysmanImp->getSysmanDeviceImp()->hCoreDevice); - pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface(); init(); } diff --git a/level_zero/tools/source/sysman/frequency/linux/os_frequency_imp_prelim.h b/level_zero/tools/source/sysman/frequency/linux/os_frequency_imp_prelim.h index f7b1d84745..8e18792627 100644 --- a/level_zero/tools/source/sysman/frequency/linux/os_frequency_imp_prelim.h +++ b/level_zero/tools/source/sysman/frequency/linux/os_frequency_imp_prelim.h @@ -12,11 +12,6 @@ #include "level_zero/tools/source/sysman/frequency/os_frequency.h" #include "level_zero/tools/source/sysman/linux/fs_access.h" -namespace L0 { -namespace Sysman { -class SysmanKmdInterface; -} // namespace Sysman -} // namespace L0 namespace L0 { class LinuxFrequencyImp : public OsFrequency, NEO::NonCopyableOrMovableClass { @@ -43,7 +38,6 @@ class LinuxFrequencyImp : public OsFrequency, NEO::NonCopyableOrMovableClass { ~LinuxFrequencyImp() override = default; protected: - L0::Sysman::SysmanKmdInterface *pSysmanKmdInterface = nullptr; SysfsAccess *pSysfsAccess = nullptr; ze_result_t getMin(double &min); ze_result_t setMin(double min); diff --git a/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp b/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp index 2faab118c7..08dd35befe 100644 --- a/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp +++ b/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp @@ -16,7 +16,6 @@ #include "level_zero/core/source/device/device_imp.h" #include "level_zero/core/source/driver/driver_handle_imp.h" -#include "level_zero/sysman/source/shared/linux/sysman_kmd_interface.h" #include "level_zero/tools/source/sysman/firmware_util/firmware_util.h" #include "level_zero/tools/source/sysman/linux/fs_access.h" #include "level_zero/tools/source/sysman/pci/linux/os_pci_imp.h" @@ -55,8 +54,6 @@ ze_result_t LinuxSysmanImp::init() { DEBUG_BREAK_IF(nullptr == pPmuInterface); - pSysmanKmdInterface = L0::Sysman::SysmanKmdInterface::create(getDrm()); - getMemoryType(); return createPmtHandles(); } diff --git a/level_zero/tools/source/sysman/linux/os_sysman_imp.h b/level_zero/tools/source/sysman/linux/os_sysman_imp.h index ba5e7d05f9..d8f156f5c5 100644 --- a/level_zero/tools/source/sysman/linux/os_sysman_imp.h +++ b/level_zero/tools/source/sysman/linux/os_sysman_imp.h @@ -22,12 +22,6 @@ #include #include -namespace L0 { -namespace Sysman { -class SysmanKmdInterface; -} // namespace Sysman -} // namespace L0 - namespace L0 { class PmuInterface; @@ -92,10 +86,8 @@ class LinuxSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass { bool isMemoryDiagnostics = false; Device *pDevice = nullptr; std::string gtDevicePath; - L0::Sysman::SysmanKmdInterface *getSysmanKmdInterface() { return pSysmanKmdInterface.get(); } protected: - std::unique_ptr pSysmanKmdInterface; FsAccess *pFsAccess = nullptr; ProcfsAccess *pProcfsAccess = nullptr; SysfsAccess *pSysfsAccess = nullptr; diff --git a/level_zero/tools/test/unit_tests/sources/sysman/frequency/linux/test_zes_frequency_prelim.cpp b/level_zero/tools/test/unit_tests/sources/sysman/frequency/linux/test_zes_frequency_prelim.cpp index 8e6f941de1..8cebd83907 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/frequency/linux/test_zes_frequency_prelim.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/frequency/linux/test_zes_frequency_prelim.cpp @@ -5,15 +5,12 @@ * */ -#include "level_zero/sysman/source/shared/linux/sysman_kmd_interface.h" #include "level_zero/tools/test/unit_tests/sources/sysman/frequency/linux/mock_sysfs_frequency_prelim.h" #include "level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h" #include "gtest/gtest.h" #include "igfxfmid.h" -using namespace L0::Sysman; - #include extern bool sysmanUltsEnable; @@ -110,48 +107,6 @@ class SysmanDeviceFrequencyFixture : public SysmanDeviceFixture { } }; -TEST_F(SysmanDeviceFrequencyFixture, GivenKmdInterfaceWhenGettingFilenamesForFrequencyFilesForI915VersionAndBaseDirectoryExistsThenProperPathsAreReturned) { - auto pSysmanKmdInterface = std::make_unique(device->getNEODevice()->getHardwareInfo().platform.eProductFamily); - bool baseDirectoryExists = true; - EXPECT_STREQ("gt/gt1/rps_min_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/rps_max_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/.defaults/rps_min_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinDefaultFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/.defaults/rps_max_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxDefaultFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/rps_boost_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameBoostFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/punit_req_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameCurrentFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/rapl_PL1_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameTdpFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/rps_act_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameActualFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/rps_RP1_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameEfficientFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/rps_RP0_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxValueFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/rps_RPn_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinValueFrequency, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/throttle_reason_status", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonStatus, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/throttle_reason_pl1", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL1, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/throttle_reason_pl2", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL2, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/throttle_reason_pl4", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL4, 1, baseDirectoryExists).c_str()); - EXPECT_STREQ("gt/gt1/throttle_reason_thermal", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonThermal, 1, baseDirectoryExists).c_str()); -} - -TEST_F(SysmanDeviceFrequencyFixture, GivenKmdInterfaceWhenGettingFilenamesForFrequencyFilesForXeVersionAndBaseDirectoryExistsThenProperPathsAreReturned) { - auto pSysmanKmdInterface = std::make_unique(device->getNEODevice()->getHardwareInfo().platform.eProductFamily); - bool baseDirectoryExists = true; - EXPECT_STREQ("device/tile0/gt0/rps_min_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/rps_max_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/.defaults/rps_min_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinDefaultFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/.defaults/rps_max_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxDefaultFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/rps_boost_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameBoostFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/punit_req_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameCurrentFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/rapl_PL1_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameTdpFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/rps_act_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameActualFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/rps_RP1_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameEfficientFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/rps_RP0_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMaxValueFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/rps_RPn_freq_mhz", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameMinValueFrequency, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/throttle_reason_status", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonStatus, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/throttle_reason_pl1", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL1, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/throttle_reason_pl2", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL2, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/throttle_reason_pl4", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonPL4, 0, baseDirectoryExists).c_str()); - EXPECT_STREQ("device/tile0/gt0/throttle_reason_thermal", pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNameThrottleReasonThermal, 0, baseDirectoryExists).c_str()); -} - TEST_F(SysmanDeviceFrequencyFixture, GivenComponentCountZeroWhenEnumeratingFrequencyHandlesThenNonZeroCountIsReturnedAndCallSucceds) { uint32_t count = 0U; diff --git a/shared/source/os_interface/linux/sys_calls.h b/shared/source/os_interface/linux/sys_calls.h index 6f1f1cbc37..53985cb3eb 100644 --- a/shared/source/os_interface/linux/sys_calls.h +++ b/shared/source/os_interface/linux/sys_calls.h @@ -48,5 +48,8 @@ int scandir(const char *dirp, int (*compar)(const struct dirent **, const struct dirent **)); int unlink(const std::string &pathname); +DIR *opendir(const char *name); +struct dirent *readdir(DIR *dir); +int closedir(DIR *dir); } // namespace SysCalls } // namespace NEO diff --git a/shared/source/os_interface/linux/sys_calls_linux.cpp b/shared/source/os_interface/linux/sys_calls_linux.cpp index 31a9374a53..905786e751 100644 --- a/shared/source/os_interface/linux/sys_calls_linux.cpp +++ b/shared/source/os_interface/linux/sys_calls_linux.cpp @@ -171,5 +171,17 @@ int unlink(const std::string &pathname) { return ::unlink(pathname.c_str()); } +DIR *opendir(const char *name) { + return ::opendir(name); +} + +struct dirent *readdir(DIR *dir) { + return ::readdir(dir); +} + +int closedir(DIR *dir) { + return ::closedir(dir); +} + } // namespace SysCalls } // namespace NEO diff --git a/shared/test/common/os_interface/linux/sys_calls_linux_ult.cpp b/shared/test/common/os_interface/linux/sys_calls_linux_ult.cpp index 6b1bb4db2f..5d444c43dc 100644 --- a/shared/test/common/os_interface/linux/sys_calls_linux_ult.cpp +++ b/shared/test/common/os_interface/linux/sys_calls_linux_ult.cpp @@ -58,6 +58,9 @@ int mkstempCalled = 0; int renameCalled = 0; int pathFileExistsCalled = 0; int flockCalled = 0; +int opendirCalled = 0; +int readdirCalled = 0; +int closedirCalled = 0; std::vector mmapVector(64); std::vector mmapCapturedExtendedPointers(64); @@ -92,6 +95,9 @@ int (*sysCallsStat)(const std::string &filePath, struct stat *statbuf) = nullptr int (*sysCallsMkstemp)(char *fileName) = nullptr; int (*sysCallsMkdir)(const std::string &dir) = nullptr; bool (*sysCallsPathExists)(const std::string &path) = nullptr; +DIR *(*sysCallsOpendir)(const char *name) = nullptr; +struct dirent *(*sysCallsReaddir)(DIR *dir) = nullptr; +int (*sysCallsClosedir)(DIR *dir) = nullptr; int mkdir(const std::string &path) { if (sysCallsMkdir != nullptr) { @@ -413,5 +419,32 @@ int stat(const std::string &filePath, struct stat *statbuf) { return 0; } +DIR *opendir(const char *name) { + opendirCalled++; + if (sysCallsOpendir != nullptr) { + return sysCallsOpendir(name); + } + + return nullptr; +} + +struct dirent *readdir(DIR *dir) { + readdirCalled++; + if (sysCallsReaddir != nullptr) { + return sysCallsReaddir(dir); + } + + return nullptr; +} + +int closedir(DIR *dir) { + closedirCalled++; + if (sysCallsClosedir != nullptr) { + return sysCallsClosedir(dir); + } + + return 0; +} + } // namespace SysCalls } // namespace NEO diff --git a/shared/test/common/os_interface/linux/sys_calls_linux_ult.h b/shared/test/common/os_interface/linux/sys_calls_linux_ult.h index 1bc78d3335..55fcc67d84 100644 --- a/shared/test/common/os_interface/linux/sys_calls_linux_ult.h +++ b/shared/test/common/os_interface/linux/sys_calls_linux_ult.h @@ -41,6 +41,9 @@ extern int (*sysCallsUnlink)(const std::string &pathname); extern int (*sysCallsStat)(const std::string &filePath, struct stat *statbuf); extern int (*sysCallsMkstemp)(char *fileName); extern bool (*sysCallsPathExists)(const std::string &path); +extern DIR *(*sysCallsOpendir)(const char *name); +extern struct dirent *(*sysCallsReaddir)(DIR *dir); +extern int (*sysCallsClosedir)(DIR *dir); extern int flockRetVal; extern int closeFuncRetVal;