From 68e1f81a83f40dc1895ae8a688a70f0918186799 Mon Sep 17 00:00:00 2001 From: Jitendra Sharma Date: Tue, 1 Aug 2023 15:14:18 +0000 Subject: [PATCH] feature: Add XE driver support for sysman processGetStateAPI This change adds support to get information about process via fdInfo Related-To: LOCI-4401 Signed-off-by: Jitendra Sharma --- .../linux/sysman_os_global_operations_imp.cpp | 199 ++++++++++++++++-- .../linux/sysman_os_global_operations_imp.h | 14 ++ .../sysman/source/linux/zes_os_sysman_imp.cpp | 4 +- .../sysman/source/linux/zes_os_sysman_imp.h | 2 +- .../shared/linux/sysman_kmd_interface.cpp | 8 + .../shared/linux/sysman_kmd_interface.h | 3 + .../linux/mock_zes_sysman_diagnostics.h | 2 +- .../linux/mock_global_operations.h | 53 ++++- .../linux/test_zes_global_operations.cpp | 22 ++ 9 files changed, 287 insertions(+), 20 deletions(-) diff --git a/level_zero/sysman/source/global_operations/linux/sysman_os_global_operations_imp.cpp b/level_zero/sysman/source/global_operations/linux/sysman_os_global_operations_imp.cpp index 373c78c1f3..afa960a1db 100644 --- a/level_zero/sysman/source/global_operations/linux/sysman_os_global_operations_imp.cpp +++ b/level_zero/sysman/source/global_operations/linux/sysman_os_global_operations_imp.cpp @@ -9,6 +9,7 @@ #include "shared/source/debug_settings/debug_settings_manager.h" #include "shared/source/execution_environment/root_device_environment.h" +#include "shared/source/helpers/constants.h" #include "shared/source/helpers/ptr_math.h" #include "shared/source/helpers/string.h" #include "shared/source/os_interface/device_factory.h" @@ -19,6 +20,7 @@ #include "level_zero/sysman/source/global_operations/sysman_global_operations_imp.h" #include "level_zero/sysman/source/linux/pmt/sysman_pmt.h" #include "level_zero/sysman/source/linux/sysman_fs_access.h" +#include "level_zero/sysman/source/shared/linux/sysman_kmd_interface.h" #include "level_zero/sysman/source/sysman_const.h" #include @@ -294,7 +296,7 @@ ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) { } for (auto &&pid : processes) { std::vector fds; - pLinuxSysmanImp->getPidFdsForOpenDevice(pProcfsAccess, pSysfsAccess, pid, fds); + pLinuxSysmanImp->getPidFdsForOpenDevice(pid, fds); if (pid == myPid) { // L0 is expected to have this file open. // Keep list of fds. Close before unbind. @@ -342,7 +344,7 @@ ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) { deviceUsingPids.clear(); for (auto &&pid : processes) { std::vector fds; - pLinuxSysmanImp->getPidFdsForOpenDevice(pProcfsAccess, pSysfsAccess, pid, fds); + pLinuxSysmanImp->getPidFdsForOpenDevice(pid, fds); if (!fds.empty()) { // Kill all processes that have the device open. pProcfsAccess->kill(pid); @@ -394,6 +396,176 @@ ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) { return pLinuxSysmanImp->reInitSysmanDeviceResources(); } +ze_result_t LinuxGlobalOperationsImp::getMemoryStatsUsedByProcess(std::vector &fdFileContents, uint64_t &memSize, uint64_t &sharedSize) { + const std::string memSizeString("drm-total-vram"); + const std::string sharedSizeString("drm-shared-vram"); + + auto convertToBytes = [](std::string unitOfSize) -> std::uint64_t { + if (unitOfSize.empty()) { + return 1; + } else if (unitOfSize == "KiB") { + return MemoryConstants::kiloByte; + } else if (unitOfSize == "MiB") { + return MemoryConstants::megaByte; + } + DEBUG_BREAK_IF(1); // Some unknowm unit is exposed by KMD, need a debug + return 0; + }; + + for (const auto &fileContents : fdFileContents) { + std::istringstream iss(fileContents); + std::string label; + uint64_t value = 0; + std::string unitOfSize; + iss >> label >> value >> unitOfSize; + + // Example: consider "fileContents = "drm-total-vram0: 120 MiB"" + // Then if we are here, then label would be "drm-total-vram0:". So remove `:` from label + label = label.substr(0, label.length() - 1); + if (label.substr(0, memSizeString.length()) == memSizeString) { + // Convert Memory obtained to bytes + value = value * convertToBytes(unitOfSize); + memSize += value; + } else if (label.substr(0, sharedSizeString.length()) == sharedSizeString) { + // Convert Memory obtained to bytes + value = value * convertToBytes(unitOfSize); + sharedSize += value; + } + } + + return ZE_RESULT_SUCCESS; +} + +ze_result_t LinuxGlobalOperationsImp::getListOfEnginesUsedByProcess(std::vector &fdFileContents, uint32_t &activeEngines) { + // Map engine entries present in /proc/>/fdinfo/, + // with engine enum defined in leve-zero spec + // Note that entries with int "video" and "video_enhance"(represented as CLASS_VIDEO and CLASS_VIDEO_ENHANCE) + // are both mapped to MEDIA, as CLASS_VIDEO represents any media fixed-function hardware. + const std::map engineMap = { + {"drm-engine-render", ZES_ENGINE_TYPE_FLAG_RENDER}, + {"drm-engine-copy", ZES_ENGINE_TYPE_FLAG_DMA}, + {"drm-engine-video", ZES_ENGINE_TYPE_FLAG_MEDIA}, + {"drm-engine-video-enhance", ZES_ENGINE_TYPE_FLAG_MEDIA}, + {"drm-engine-compute", ZES_ENGINE_TYPE_FLAG_COMPUTE}}; + + const std::string engineStringPrefix("drm-engine-"); + for (const auto &fileContents : fdFileContents) { + std::istringstream iss(fileContents); + std::string label; + uint64_t value; + iss >> label >> value; + // Example: consider "fileContents = "drm-engine-render: 25662044495 ns"" + // Then if we are here, then label would be "drm-engine-render:". So remove `:` from label + label = label.substr(0, label.length() - 1); + + if ((label.substr(0, engineStringPrefix.length()) == engineStringPrefix) && (value != 0)) { + auto it = engineMap.find(label); + if (it == engineMap.end()) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Error@ %s(): unknown engine type: %s and returning error:0x%x \n", __FUNCTION__, label.c_str(), + ZE_RESULT_ERROR_UNKNOWN); + DEBUG_BREAK_IF(1); + return ZE_RESULT_ERROR_UNKNOWN; + } + activeEngines = activeEngines | it->second; + } + } + return ZE_RESULT_SUCCESS; +} + +// Example fdinfo format: +// +// # cat /proc/1383/fdinfo/8 +// pos: 0 +// flags: 02100002 +// mnt_id: 21 +// ino: 397 +// drm-driver: i915 +// drm-client-id: 18 +// drm-pdev: 0000:00:02.0 +// drm-total-vram0: 512 +// drm-total-vram1: 512 KiB +// drm-shared-vram0: 512 KiB +// drm-shared-vram1: 128 MiB +// drm-total-system: 125 MiB +// drm-shared-system: 16 MiB +// drm-active-system: 110 MiB +// drm-resident-system: 125 MiB +// drm-purgeable-system: 2 MiB +// drm-total-stolen-system: 0 +// drm-shared-stolen-system: 0 +// drm-active-stolen-system: 0 +// drm-resident-stolen-system: 0 +// drm-purgeable-stolen-system: 0 +// drm-engine-render: 25662044495 ns +// drm-engine-copy: 0 ns +// drm-engine-video: 0 ns +// drm-engine-video-enhance: 0 ns +ze_result_t LinuxGlobalOperationsImp::readClientInfoFromFdInfo(std::map &pidClientMap) { + std::map<::pid_t, std::vector> gpuClientProcessMap; // This map contains processes and their opened gpu File descriptors + ze_result_t result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + + { + std::vector<::pid_t> processes; + result = pProcfsAccess->listProcesses(processes); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Unable to list processes and returning error:0x%x \n", __FUNCTION__, result); + return result; + } + + for (auto &&pid : processes) { + std::vector fds; + pLinuxSysmanImp->getPidFdsForOpenDevice(pid, fds); + if (!fds.empty()) { + gpuClientProcessMap.insert({pid, fds}); + } + } + } + + // iterate for each process + for (const auto &gpuClientProcess : gpuClientProcessMap) { + // iterate over all the opened GPU device file descriptors + uint64_t pid = static_cast(gpuClientProcess.first); + uint32_t activeEngines = 0u; // This contains bit fields of engines used by processes + uint64_t memSize = 0u; + uint64_t sharedSize = 0u; + for (const auto &fd : gpuClientProcess.second) { + std::string fdInfoPath = "/proc/" + std::to_string(static_cast(pid)) + "/fdinfo/" + std::to_string(fd); + std::vector fdFileContents; + result = pFsAccess->read(fdInfoPath, fdFileContents); + if (ZE_RESULT_SUCCESS != result) { + if (ZE_RESULT_ERROR_NOT_AVAILABLE == result) { + // update the result as Success as ZE_RESULT_ERROR_NOT_AVAILABLE is expected if process exited by the time we are readig it. + result = ZE_RESULT_SUCCESS; + continue; + } else { + return result; + } + } + + result = getListOfEnginesUsedByProcess(fdFileContents, activeEngines); + if (result != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Error@ %s(): List of engines used by process(%d) with fd(%d) could not be retrieved.\n", __FUNCTION__, + pid, fd); + return result; + } + + result = getMemoryStatsUsedByProcess(fdFileContents, memSize, sharedSize); + if (result != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Error@ %s(): Memory used by process(%d) with fd(%d) could not be retrieved.\n", __FUNCTION__, + pid, fd); + return result; + } + } + DeviceMemStruct totalDeviceMem = {memSize, sharedSize}; + EngineMemoryPairType engineMemoryPair = {static_cast(activeEngines), totalDeviceMem}; + pidClientMap.insert(std::make_pair(pid, engineMemoryPair)); + } + return result; +} + // Processes in the form of clients are present in sysfs like this: // # /sys/class/drm/card0/clients$ ls // 4 5 @@ -411,25 +583,14 @@ ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) { // accumulated nanoseconds each client spent on engines. // Thus we traverse each file in busy dir for non-zero time and if we find that file say 0,then we could say that // this engine 0 is used by process. -ze_result_t LinuxGlobalOperationsImp::scanProcessesState(std::vector &pProcessList) { +ze_result_t LinuxGlobalOperationsImp::readClientInfoFromSysfs(std::map &pidClientMap) { std::vector clientIds; - struct DeviceMemStruct { - uint64_t deviceMemorySize; - uint64_t deviceSharedMemorySize; - }; - struct EngineMemoryPairType { - int64_t engineTypeField; - DeviceMemStruct deviceMemStructField; - }; - ze_result_t result = pSysfsAccess->scanDirEntries(clientsDir, clientIds); if (ZE_RESULT_SUCCESS != result) { NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to scan directory entries from %s and returning error:0x%x \n", __FUNCTION__, clientsDir.c_str(), ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } - // Create a map with unique pid as key and engineType as value - std::map pidClientMap; for (const auto &clientId : clientIds) { // realClientPidPath will be something like: clients//pid std::string realClientPidPath = clientsDir + "/" + clientId + "/" + "pid"; @@ -538,6 +699,16 @@ ze_result_t LinuxGlobalOperationsImp::scanProcessesState(std::vector &pProcessList) { + ze_result_t result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + // Create a map with unique pid as key and EngineMemoryPairType as value + std::map pidClientMap; + + result = pLinuxSysmanImp->getSysmanKmdInterface()->clientInfoAvailableInFdInfo() ? readClientInfoFromFdInfo(pidClientMap) : readClientInfoFromSysfs(pidClientMap); + // iterate through all elements of pidClientMap for (auto itr = pidClientMap.begin(); itr != pidClientMap.end(); ++itr) { zes_process_state_t process; diff --git a/level_zero/sysman/source/global_operations/linux/sysman_os_global_operations_imp.h b/level_zero/sysman/source/global_operations/linux/sysman_os_global_operations_imp.h index fa04325225..272458e8e9 100644 --- a/level_zero/sysman/source/global_operations/linux/sysman_os_global_operations_imp.h +++ b/level_zero/sysman/source/global_operations/linux/sysman_os_global_operations_imp.h @@ -18,6 +18,7 @@ namespace L0 { namespace Sysman { class SysfsAccess; +class SysmanKmdInterface; class LinuxGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMovableClass { public: @@ -44,6 +45,15 @@ class LinuxGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMo } uuid; protected: + struct DeviceMemStruct { + uint64_t deviceMemorySize; + uint64_t deviceSharedMemorySize; + }; + struct EngineMemoryPairType { + int64_t engineTypeField; + DeviceMemStruct deviceMemStructField; + }; + FsAccess *pFsAccess = nullptr; ProcfsAccess *pProcfsAccess = nullptr; SysfsAccess *pSysfsAccess = nullptr; @@ -53,6 +63,8 @@ class LinuxGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMo void releaseDeviceResources(); ze_result_t initDevice(); void reInitSysmanDeviceResources(); + ze_result_t readClientInfoFromSysfs(std::map &pidClientMap); + ze_result_t readClientInfoFromFdInfo(std::map &pidClientMap); private: static const std::string deviceDir; @@ -68,6 +80,8 @@ class LinuxGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMo std::string devicePciBdf = ""; NEO::ExecutionEnvironment *executionEnvironment = nullptr; uint32_t rootDeviceIndex = 0u; + ze_result_t getListOfEnginesUsedByProcess(std::vector &fdFileContents, uint32_t &activeEngines); + ze_result_t getMemoryStatsUsedByProcess(std::vector &fdFileContents, uint64_t &memSize, uint64_t &sharedSize); }; } // namespace Sysman diff --git a/level_zero/sysman/source/linux/zes_os_sysman_imp.cpp b/level_zero/sysman/source/linux/zes_os_sysman_imp.cpp index 19b888773c..991cb9500f 100644 --- a/level_zero/sysman/source/linux/zes_os_sysman_imp.cpp +++ b/level_zero/sysman/source/linux/zes_os_sysman_imp.cpp @@ -236,7 +236,7 @@ LinuxSysmanImp::~LinuxSysmanImp() { releasePmtObject(); } -void LinuxSysmanImp::getPidFdsForOpenDevice(ProcfsAccess *pProcfsAccess, SysfsAccess *pSysfsAccess, const ::pid_t pid, std::vector &deviceFds) { +void LinuxSysmanImp::getPidFdsForOpenDevice(const ::pid_t pid, std::vector &deviceFds) { // Return a list of all the file descriptors of this process that point to this device std::vector fds; deviceFds.clear(); @@ -269,7 +269,7 @@ ze_result_t LinuxSysmanImp::gpuProcessCleanup() { for (auto &&pid : processes) { std::vector fds; - getPidFdsForOpenDevice(pProcfsAccess, pSysfsAccess, pid, fds); + getPidFdsForOpenDevice(pid, fds); if (pid == myPid) { // L0 is expected to have this file open. // Keep list of fds. Close before unbind. diff --git a/level_zero/sysman/source/linux/zes_os_sysman_imp.h b/level_zero/sysman/source/linux/zes_os_sysman_imp.h index 9eae8229c8..905efb1a1c 100644 --- a/level_zero/sysman/source/linux/zes_os_sysman_imp.h +++ b/level_zero/sysman/source/linux/zes_os_sysman_imp.h @@ -56,7 +56,7 @@ class LinuxSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass { void releasePmtObject(); MOCKABLE_VIRTUAL void releaseSysmanDeviceResources(); MOCKABLE_VIRTUAL ze_result_t reInitSysmanDeviceResources(); - MOCKABLE_VIRTUAL void getPidFdsForOpenDevice(ProcfsAccess *, SysfsAccess *, const ::pid_t, std::vector &); + MOCKABLE_VIRTUAL void getPidFdsForOpenDevice(const ::pid_t, std::vector &); MOCKABLE_VIRTUAL ze_result_t osWarmReset(); MOCKABLE_VIRTUAL ze_result_t osColdReset(); ze_result_t gpuProcessCleanup(); 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 3155ab5eb7..a25edb927e 100644 --- a/level_zero/sysman/source/shared/linux/sysman_kmd_interface.cpp +++ b/level_zero/sysman/source/shared/linux/sysman_kmd_interface.cpp @@ -155,5 +155,13 @@ std::string SysmanKmdInterfaceXe::getHwmonName(uint32_t subDeviceId, bool isSubd return filePath; } +bool SysmanKmdInterfaceI915::clientInfoAvailableInFdInfo() { + return false; +} + +bool SysmanKmdInterfaceXe::clientInfoAvailableInFdInfo() { + return true; +} + } // namespace Sysman } // namespace L0 \ No newline at end of file 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 f40f2bbbe4..f463c83b8c 100644 --- a/level_zero/sysman/source/shared/linux/sysman_kmd_interface.h +++ b/level_zero/sysman/source/shared/linux/sysman_kmd_interface.h @@ -88,6 +88,7 @@ class SysmanKmdInterface { virtual int64_t getEngineActivityFd(zes_engine_group_t engineGroup, uint32_t engineInstance, uint32_t subDeviceId, PmuInterface *const &pmuInterface) = 0; virtual std::string getHwmonName(uint32_t subDeviceId, bool isSubdevice) const = 0; virtual bool isStandbyModeControlAvailable() const = 0; + virtual bool clientInfoAvailableInFdInfo() = 0; }; class SysmanKmdInterfaceI915 : public SysmanKmdInterface { @@ -101,6 +102,7 @@ class SysmanKmdInterfaceI915 : public SysmanKmdInterface { int64_t getEngineActivityFd(zes_engine_group_t engineGroup, uint32_t engineInstance, uint32_t subDeviceId, PmuInterface *const &pmuInterface) override; std::string getHwmonName(uint32_t subDeviceId, bool isSubdevice) const override; bool isStandbyModeControlAvailable() const override { return true; } + bool clientInfoAvailableInFdInfo() override; protected: std::map sysfsNameToFileMap; @@ -118,6 +120,7 @@ class SysmanKmdInterfaceXe : public SysmanKmdInterface { int64_t getEngineActivityFd(zes_engine_group_t engineGroup, uint32_t engineInstance, uint32_t subDeviceId, PmuInterface *const &pmuInterface) override; std::string getHwmonName(uint32_t subDeviceId, bool isSubdevice) const override; bool isStandbyModeControlAvailable() const override { return false; } + bool clientInfoAvailableInFdInfo() override; protected: std::map sysfsNameToFileMap; diff --git a/level_zero/sysman/test/unit_tests/sources/diagnostics/linux/mock_zes_sysman_diagnostics.h b/level_zero/sysman/test/unit_tests/sources/diagnostics/linux/mock_zes_sysman_diagnostics.h index 4136dbfc08..20923d9383 100644 --- a/level_zero/sysman/test/unit_tests/sources/diagnostics/linux/mock_zes_sysman_diagnostics.h +++ b/level_zero/sysman/test/unit_tests/sources/diagnostics/linux/mock_zes_sysman_diagnostics.h @@ -222,7 +222,7 @@ struct MockDiagLinuxSysmanImp : public L0::Sysman::LinuxSysmanImp { int ourDeviceFd = 0; ze_result_t mockError = ZE_RESULT_SUCCESS; ze_result_t mockReInitSysmanDeviceError = ZE_RESULT_SUCCESS; - void getPidFdsForOpenDevice(L0::Sysman::ProcfsAccess *pProcfsAccess, L0::Sysman::SysfsAccess *pSysfsAccess, const ::pid_t pid, std::vector &deviceFds) override { + void getPidFdsForOpenDevice(const ::pid_t pid, std::vector &deviceFds) override { if (ourDevicePid) { deviceFds.push_back(ourDeviceFd); } diff --git a/level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h index 803b95269e..cf4af31c2e 100644 --- a/level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h +++ b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h @@ -361,10 +361,12 @@ struct MockGlobalOperationsProcfsAccess : public L0::Sysman::ProcfsAccess { const ::pid_t extraPid = 4; const int extraFd = 5; + const int extraFd1 = 6; std::vector<::pid_t> pidList = {1, 2, 3}; std::vector fdList = {0, 1, 2}; ::pid_t ourDevicePid = 0; int ourDeviceFd = 0; + int ourDeviceFd1 = 0; std::vector mockListProcessCall{}; std::vector isRepeated{}; @@ -417,6 +419,9 @@ struct MockGlobalOperationsProcfsAccess : public L0::Sysman::ProcfsAccess { list = fdList; if (ourDevicePid == pid) { list.push_back(ourDeviceFd); + if (ourDeviceFd1) { + list.push_back(ourDeviceFd1); + } } return getFileDescriptorsResult; } @@ -428,7 +433,7 @@ struct MockGlobalOperationsProcfsAccess : public L0::Sysman::ProcfsAccess { return mockGetFileNameError; } - if (pid == ourDevicePid && fd == ourDeviceFd) { + if (pid == ourDevicePid && ((fd == ourDeviceFd) || (fd == ourDeviceFd1))) { val = mockDeviceName; } else { // return fake filenames for other file descriptors @@ -482,6 +487,50 @@ struct MockGlobalOperationsFsAccess : public L0::Sysman::FsAccess { return readResult; } + ze_result_t read(std::string file, std::vector &val) override { + if (mockReadError != ZE_RESULT_SUCCESS) { + return mockReadError; + } + + if (file == "/proc/4/fdinfo/5") { + val.push_back("pos: 0"); + val.push_back("flags: 02100002"); + val.push_back("drm-total-vram0: 120 MiB"); + val.push_back("drm-total-vram1: 50 KiB"); + val.push_back("drm-total-system: 125 MiB"); + val.push_back("drm-shared-vram0: 120 MiB"); + val.push_back("drm-shared-vram1: 80 MiB"); + val.push_back("drm-shared-system: 16 MiB"); + val.push_back("drm-active-system: 110 MiB"); + val.push_back("drm-resident-system: 125 MiB"); + val.push_back("drm-total-stolen-system: 0"); + val.push_back("drm-shared-stolen-system: 0"); + val.push_back("drm-engine-render: 25662044495 ns"); + val.push_back("drm-engine-copy: 0 ns"); + val.push_back("drm-engine-video: 0 ns"); + val.push_back("drm-engine-video-enhance: 0 ns"); + } + if (file == "/proc/4/fdinfo/6") { + val.push_back("pos: 0"); + val.push_back("flags: 02100002"); + val.push_back("drm-total-vram0: 534 "); + val.push_back("drm-total-vram1: 50 MiB"); + val.push_back("drm-total-system: 125 MiB"); + val.push_back("drm-shared-vram0: 120 KiB"); + val.push_back("drm-shared-vram1: 689"); + val.push_back("drm-shared-system: 16 MiB"); + val.push_back("drm-active-system: 110 MiB"); + val.push_back("drm-resident-system: 125 MiB"); + val.push_back("drm-total-stolen-system: 0"); + val.push_back("drm-shared-stolen-system: 0"); + val.push_back("drm-engine-render: 25662044495 ns"); + val.push_back("drm-engine-copy: 0 ns"); + val.push_back("drm-engine-video: 5645843250 ns"); + val.push_back("drm-engine-video-enhance: 0 ns"); + } + return ZE_RESULT_SUCCESS; + } + ze_result_t mockWriteError = ZE_RESULT_SUCCESS; ze_result_t writeResult = ZE_RESULT_SUCCESS; ze_result_t write(const std::string file, const std::string val) override { @@ -533,7 +582,7 @@ struct MockGlobalOpsLinuxSysmanImp : public L0::Sysman::LinuxSysmanImp { int ourDeviceFd = 0; ze_result_t mockError = ZE_RESULT_SUCCESS; ze_result_t mockInitDeviceError = ZE_RESULT_SUCCESS; - void getPidFdsForOpenDevice(L0::Sysman::ProcfsAccess *pProcfsAccess, L0::Sysman::SysfsAccess *pSysfsAccess, const ::pid_t pid, std::vector &deviceFds) override { + void getPidFdsForOpenDevice(const ::pid_t pid, std::vector &deviceFds) override { if (ourDevicePid) { deviceFds.push_back(ourDeviceFd); } diff --git a/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations.cpp b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations.cpp index b45128d1f5..cbf77842ca 100644 --- a/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations.cpp +++ b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations.cpp @@ -9,6 +9,7 @@ #include "shared/test/common/helpers/ult_hw_config.h" #include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" +#include "level_zero/sysman/source/shared/linux/sysman_kmd_interface.h" #include "level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h" #include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h" @@ -577,6 +578,27 @@ TEST_F(SysmanGlobalOperationsFixture, EXPECT_TRUE(0 == unknown.compare(properties.driverVersion)); } +TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleAndXeDriverUsedWhileRetrievingInformationAboutHostProcessesUsingDeviceThenSuccessIsReturned) { + pLinuxSysmanImp->pSysmanKmdInterface = std::make_unique(pLinuxSysmanImp->getProductFamily()); + pProcfsAccess->ourDevicePid = pProcfsAccess->extraPid; + // Assume two File descriptors of gpu are obtained by process + pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd; + pProcfsAccess->ourDeviceFd1 = pProcfsAccess->extraFd1; + pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE); + uint32_t count = 0; + ASSERT_EQ(ZE_RESULT_SUCCESS, zesDeviceProcessesGetState(device, &count, nullptr)); + EXPECT_EQ(count, 1u); + std::vector processes(count); + ASSERT_EQ(ZE_RESULT_SUCCESS, zesDeviceProcessesGetState(device, &count, processes.data())); + EXPECT_EQ(processes[0].processId, static_cast(pProcfsAccess->extraPid)); + constexpr int64_t expectedEngines = ZES_ENGINE_TYPE_FLAG_RENDER | ZES_ENGINE_TYPE_FLAG_MEDIA; + EXPECT_EQ(processes[0].engines, expectedEngines); + uint64_t expectedMemSize = (120 * MemoryConstants::megaByte) + (50 * MemoryConstants::kiloByte) + 534 + ((50 * MemoryConstants::megaByte)); + uint64_t expectedSharedSize = (120 * MemoryConstants::megaByte) + (80 * MemoryConstants::megaByte) + (120 * MemoryConstants::kiloByte) + 689; + EXPECT_EQ(processes[0].memSize, expectedMemSize); + EXPECT_EQ(processes[0].sharedSize, expectedSharedSize); +} + TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileRetrievingInformationAboutHostProcessesUsingDeviceThenSuccessIsReturned) { uint32_t count = 0; ASSERT_EQ(ZE_RESULT_SUCCESS, zesDeviceProcessesGetState(device, &count, nullptr));