diff --git a/level_zero/sysman/source/api/performance/linux/sysman_os_performance_imp.cpp b/level_zero/sysman/source/api/performance/linux/sysman_os_performance_imp.cpp index 5393d44b00..da641cf7de 100644 --- a/level_zero/sysman/source/api/performance/linux/sysman_os_performance_imp.cpp +++ b/level_zero/sysman/source/api/performance/linux/sysman_os_performance_imp.cpp @@ -9,23 +9,240 @@ #include "shared/source/debug_settings/debug_settings_manager.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 namespace L0 { namespace Sysman { +static constexpr double maxSysPowerBalanceReading = 63.0; +static constexpr double minSysPowerBalanceReading = 0.0; +static constexpr double defaultSysPowerBalanceReading = 16.0; + +ze_result_t LinuxPerformanceImp::getErrorCode(ze_result_t result) { + if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + return result; +} + ze_result_t LinuxPerformanceImp::osPerformanceGetProperties(zes_perf_properties_t &pProperties) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + pProperties.onSubdevice = isSubdevice; + pProperties.subdeviceId = subdeviceId; + pProperties.engines = domain; + return ZE_RESULT_SUCCESS; } ze_result_t LinuxPerformanceImp::osPerformanceGetConfig(double *pFactor) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + ze_result_t result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + double baseFactorReading = 0; + double mediaFactorReading = 0; + double sysPwrBalanceReading = 0; + double multiplier = 0; + switch (domain) { + case ZES_ENGINE_TYPE_FLAG_OTHER: + + if (pSysmanKmdInterface->isSystemPowerBalanceAvailable() == false) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): The System Power Balance is not available and hence returns UNSUPPORTED_FEATURE \n", __FUNCTION__); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + result = pSysFsAccess->read(systemPowerBalance, sysPwrBalanceReading); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s and returning error:0x%x \n", __FUNCTION__, systemPowerBalance.c_str(), getErrorCode(result)); + return getErrorCode(result); + } + if (sysPwrBalanceReading >= minSysPowerBalanceReading && sysPwrBalanceReading <= defaultSysPowerBalanceReading) { + *pFactor = halfOfMaxPerformanceFactor + std::round((defaultSysPowerBalanceReading - sysPwrBalanceReading) * halfOfMaxPerformanceFactor / defaultSysPowerBalanceReading); + } else if (sysPwrBalanceReading > defaultSysPowerBalanceReading && sysPwrBalanceReading <= maxSysPowerBalanceReading) { + *pFactor = std::round((maxSysPowerBalanceReading - sysPwrBalanceReading) * halfOfMaxPerformanceFactor / (maxSysPowerBalanceReading - defaultSysPowerBalanceReading)); + } else { + result = ZE_RESULT_ERROR_UNKNOWN; + } + break; + + case ZES_ENGINE_TYPE_FLAG_MEDIA: + + result = pSysFsAccess->read(mediaFreqFactor, mediaFactorReading); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s and returning error:0x%x \n", __FUNCTION__, mediaFreqFactor.c_str(), getErrorCode(result)); + return getErrorCode(result); + } + multiplier = (mediaFactorReading * mediaScaleReading); // Value retrieved from media_freq_factor file is in U(fixed point decimal) format convert it into decimal by multiplication with scale factor + if (multiplier == 1) { + *pFactor = maxPerformanceFactor; + } else if (multiplier == 0.5) { + *pFactor = halfOfMaxPerformanceFactor; + } else if (multiplier == 0) { + *pFactor = minPerformanceFactor; + } else { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): multiplier for MEDIA is not matching with given presets and returning UNKNOWN ERROR \n", __FUNCTION__); + result = ZE_RESULT_ERROR_UNKNOWN; + } + break; + + case ZES_ENGINE_TYPE_FLAG_COMPUTE: + + if (pSysmanKmdInterface->isBaseFrequencyFactorAvailable() == false) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): The Base Frequency Factor is not available and hence returns UNSUPPORTED_FEATURE \n", __FUNCTION__); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + result = pSysFsAccess->read(baseFreqFactor, baseFactorReading); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): SysfsAccess->read() failed to read %s and returning error:0x%x \n", __FUNCTION__, baseFreqFactor.c_str(), getErrorCode(result)); + return getErrorCode(result); + } + multiplier = (baseFactorReading * baseScaleReading); // Value retrieved from base_freq_factor file is in U(fixed point decimal) format convert it into decimal by multiplication with scale factor + if (multiplier >= 0.5 && multiplier <= 1) { + *pFactor = (1 - multiplier) * maxPerformanceFactor + halfOfMaxPerformanceFactor; + } else if (multiplier > 1 && multiplier <= 2) { + *pFactor = (2 - multiplier) * halfOfMaxPerformanceFactor; + } else { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): multiplier for COMPUTE is not matching with given presets and returning UNKNOWN ERROR\n", __FUNCTION__); + result = ZE_RESULT_ERROR_UNKNOWN; + } + break; + + default: + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s() returning UNSUPPORTED_FEATURE as osPerformanceGetConfig is not supported\n", __FUNCTION__); + break; + } + + return result; } ze_result_t LinuxPerformanceImp::osPerformanceSetConfig(double pFactor) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + double multiplier = 0; + ze_result_t result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + if (pFactor < minPerformanceFactor || pFactor > maxPerformanceFactor) { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + + switch (domain) { + case ZES_ENGINE_TYPE_FLAG_OTHER: + + if (pSysmanKmdInterface->isSystemPowerBalanceAvailable() == false) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): The System Power Balance is not available and hence returns UNSUPPORTED_FEATURE \n", __FUNCTION__); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + if (pFactor <= halfOfMaxPerformanceFactor) { + multiplier = maxSysPowerBalanceReading - std::round(pFactor * (maxSysPowerBalanceReading - defaultSysPowerBalanceReading) / halfOfMaxPerformanceFactor); + } else { + multiplier = defaultSysPowerBalanceReading - std::round((pFactor - halfOfMaxPerformanceFactor) * defaultSysPowerBalanceReading / halfOfMaxPerformanceFactor); + } + result = pSysFsAccess->write(systemPowerBalance, multiplier); + break; + + case ZES_ENGINE_TYPE_FLAG_MEDIA: + + if (pFactor > halfOfMaxPerformanceFactor) { + multiplier = 1; + } else { + multiplier = 0.5; + } + + multiplier = multiplier / mediaScaleReading; + multiplier = std::round(multiplier); + result = pSysFsAccess->write(mediaFreqFactor, multiplier); + break; + + case ZES_ENGINE_TYPE_FLAG_COMPUTE: + + if (pSysmanKmdInterface->isBaseFrequencyFactorAvailable() == false) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): The Base Frequency Factor is not available and hence returns UNSUPPORTED_FEATURE \n", __FUNCTION__); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + if (pFactor < halfOfMaxPerformanceFactor) { + multiplier = 2 - (pFactor / halfOfMaxPerformanceFactor); + } else { + multiplier = 1 - ((pFactor - halfOfMaxPerformanceFactor) / maxPerformanceFactor); + } + multiplier = multiplier / baseScaleReading; // Divide by scale factor and then round off to convert from decimal to U format + multiplier = std::round(multiplier); + result = pSysFsAccess->write(baseFreqFactor, multiplier); + break; + + default: + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s() returning UNSUPPORTED_FEATURE as osPerformanceSetConfig is not supported\n", __FUNCTION__); + break; + } + + return result; +} + +ze_result_t LinuxPerformanceImp::getBaseFrequencyScaleFactor() { + return pSysFsAccess->read(baseFreqFactorScale, baseScaleReading); +} + +ze_result_t LinuxPerformanceImp::getMediaFrequencyScaleFactor() { + return pSysFsAccess->read(mediaFreqFactorScale, mediaScaleReading); } bool LinuxPerformanceImp::isPerformanceSupported(void) { - return false; + switch (domain) { + case ZES_ENGINE_TYPE_FLAG_OTHER: + + if (pSysmanKmdInterface->isSystemPowerBalanceAvailable() == false) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): ZES_ENGINE_TYPE_FLAG_OTHER returns false as System Power Balance is not Available\n", __FUNCTION__); + return false; + } + if (pSysFsAccess->canRead(systemPowerBalance) != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): ZES_ENGINE_TYPE_FLAG_OTHER returns false SysfsAccess->canRead() failed for %s\n", __FUNCTION__, systemPowerBalance.c_str()); + return false; + } + break; + + case ZES_ENGINE_TYPE_FLAG_MEDIA: + + if (pSysFsAccess->canRead(mediaFreqFactor) != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): ZES_ENGINE_TYPE_FLAG_MEDIA returns false as SysfsAccess->canRead() failed for %s\n", __FUNCTION__, mediaFreqFactor.c_str()); + return false; + } + if (getMediaFrequencyScaleFactor() != ZE_RESULT_SUCCESS) { + return false; + } + break; + + case ZES_ENGINE_TYPE_FLAG_COMPUTE: + + if (pSysmanKmdInterface->isBaseFrequencyFactorAvailable() == false) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): ZES_ENGINE_TYPE_FLAG_COMPUTE returns false as Base Frequency is not Available\n", __FUNCTION__); + return false; + } + if (pSysFsAccess->canRead(baseFreqFactor) != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): ZES_ENGINE_TYPE_FLAG_COMPUTE returns false as SysfsAccess->canRead() failed for %s\n", __FUNCTION__, baseFreqFactor.c_str()); + return false; + } + if (getBaseFrequencyScaleFactor() != ZE_RESULT_SUCCESS) { + return false; + } + break; + + default: + return false; + break; + } + return true; +} + +LinuxPerformanceImp::LinuxPerformanceImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, + zes_engine_type_flag_t domain) : domain(domain), subdeviceId(subdeviceId), isSubdevice(onSubdevice) { + LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + productFamily = pLinuxSysmanImp->getProductFamily(); + pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface(); + pSysFsAccess = pSysmanKmdInterface->getSysFsAccess(); + + if (pSysmanKmdInterface->isBaseFrequencyFactorAvailable() == true) { + baseFreqFactor = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceBaseFrequencyFactor, subdeviceId, true); + baseFreqFactorScale = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceBaseFrequencyFactorScale, subdeviceId, true); + } + + if (pSysmanKmdInterface->isSystemPowerBalanceAvailable() == true) { + systemPowerBalance = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceSystemPowerBalance, subdeviceId, true); + } + + mediaFreqFactor = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceMediaFrequencyFactor, subdeviceId, true); + mediaFreqFactorScale = pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceMediaFrequencyFactorScale, subdeviceId, true); } OsPerformance *OsPerformance::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_engine_type_flag_t domain) { diff --git a/level_zero/sysman/source/api/performance/linux/sysman_os_performance_imp.h b/level_zero/sysman/source/api/performance/linux/sysman_os_performance_imp.h index 67d96b30ae..b0a89d25d6 100644 --- a/level_zero/sysman/source/api/performance/linux/sysman_os_performance_imp.h +++ b/level_zero/sysman/source/api/performance/linux/sysman_os_performance_imp.h @@ -15,6 +15,8 @@ namespace L0 { namespace Sysman { +class SysmanKmdInterface; +class SysFsAccessInterface; class LinuxPerformanceImp : public OsPerformance, NEO::NonCopyableOrMovableClass { public: ze_result_t osPerformanceGetProperties(zes_perf_properties_t &pProperties) override; @@ -25,8 +27,26 @@ class LinuxPerformanceImp : public OsPerformance, NEO::NonCopyableOrMovableClass LinuxPerformanceImp() = delete; LinuxPerformanceImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, - zes_engine_type_flag_t domain) {} + zes_engine_type_flag_t domain); ~LinuxPerformanceImp() override = default; + + protected: + ze_result_t getMediaFrequencyScaleFactor(); + ze_result_t getBaseFrequencyScaleFactor(); + ze_result_t getErrorCode(ze_result_t result); + SysmanKmdInterface *pSysmanKmdInterface = nullptr; + SysFsAccessInterface *pSysFsAccess = nullptr; + PRODUCT_FAMILY productFamily{}; + zes_engine_type_flag_t domain = ZES_ENGINE_TYPE_FLAG_OTHER; + double baseScaleReading = 0; + double mediaScaleReading = 0; + uint32_t subdeviceId = 0; + ze_bool_t isSubdevice = 0; + std::string mediaFreqFactor = ""; + std::string baseFreqFactor = ""; + std::string systemPowerBalance = ""; + std::string baseFreqFactorScale = ""; + std::string mediaFreqFactorScale = ""; }; } // namespace Sysman diff --git a/level_zero/sysman/source/api/scheduler/linux/sysman_os_scheduler_imp.cpp b/level_zero/sysman/source/api/scheduler/linux/sysman_os_scheduler_imp.cpp index 8af0a10b2f..81d26de253 100644 --- a/level_zero/sysman/source/api/scheduler/linux/sysman_os_scheduler_imp.cpp +++ b/level_zero/sysman/source/api/scheduler/linux/sysman_os_scheduler_imp.cpp @@ -55,7 +55,7 @@ static ze_result_t readSchedulerValueFromSysfs(SysfsName schedulerSysfsName, } // For compute engines with different timeout values, use the maximum value - if (schedulerSysfsName == SysfsName::syfsNameSchedulerTimeout && engineType == ZES_ENGINE_TYPE_FLAG_COMPUTE) { + if (schedulerSysfsName == SysfsName::sysfsNameSchedulerTimeout && engineType == ZES_ENGINE_TYPE_FLAG_COMPUTE) { readValue = *std::max_element(readValueVec.begin(), readValueVec.end()); return result; } @@ -125,7 +125,7 @@ ze_result_t LinuxSchedulerImp::getCurrentMode(zes_sched_mode_t *pMode) { if (pSysmanKmdInterface->useDefaultMaximumWatchdogTimeoutForExclusiveMode()) { uint64_t defaultHeartbeatInterval = 0; - result = readSchedulerValueFromSysfs(SysfsName::syfsNameSchedulerWatchDogTimeoutMaximum, + result = readSchedulerValueFromSysfs(SysfsName::sysfsNameSchedulerWatchDogTimeoutMaximum, pLinuxSysmanImp, subdeviceId, true, listOfEngines, engineType, defaultHeartbeatInterval); if (result != ZE_RESULT_SUCCESS) { @@ -173,7 +173,7 @@ ze_result_t LinuxSchedulerImp::setExclusiveModeImp() { auto pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface(); if (pSysmanKmdInterface->useDefaultMaximumWatchdogTimeoutForExclusiveMode()) { - result = readSchedulerValueFromSysfs(SysfsName::syfsNameSchedulerWatchDogTimeoutMaximum, + result = readSchedulerValueFromSysfs(SysfsName::sysfsNameSchedulerWatchDogTimeoutMaximum, pLinuxSysmanImp, subdeviceId, true, listOfEngines, engineType, heartbeat); if (result != ZE_RESULT_SUCCESS) { @@ -332,42 +332,42 @@ ze_result_t LinuxSchedulerImp::getProperties(zes_sched_properties_t &schedProper ze_result_t LinuxSchedulerImp::getPreemptTimeout(uint64_t &timeout, ze_bool_t getDefault) { - return readSchedulerValueFromSysfs(SysfsName::syfsNameSchedulerTimeout, + return readSchedulerValueFromSysfs(SysfsName::sysfsNameSchedulerTimeout, pLinuxSysmanImp, subdeviceId, getDefault, listOfEngines, engineType, timeout); } ze_result_t LinuxSchedulerImp::getTimesliceDuration(uint64_t ×lice, ze_bool_t getDefault) { - return readSchedulerValueFromSysfs(SysfsName::syfsNameSchedulerTimeslice, + return readSchedulerValueFromSysfs(SysfsName::sysfsNameSchedulerTimeslice, pLinuxSysmanImp, subdeviceId, getDefault, listOfEngines, engineType, timeslice); } ze_result_t LinuxSchedulerImp::getHeartbeatInterval(uint64_t &heartbeat, ze_bool_t getDefault) { - return readSchedulerValueFromSysfs(SysfsName::syfsNameSchedulerWatchDogTimeout, + return readSchedulerValueFromSysfs(SysfsName::sysfsNameSchedulerWatchDogTimeout, pLinuxSysmanImp, subdeviceId, getDefault, listOfEngines, engineType, heartbeat); } ze_result_t LinuxSchedulerImp::setPreemptTimeout(uint64_t timeout) { - return writeSchedulerValueToSysfs(SysfsName::syfsNameSchedulerTimeout, + return writeSchedulerValueToSysfs(SysfsName::sysfsNameSchedulerTimeout, pLinuxSysmanImp, subdeviceId, listOfEngines, engineType, timeout); } ze_result_t LinuxSchedulerImp::setTimesliceDuration(uint64_t timeslice) { - return writeSchedulerValueToSysfs(SysfsName::syfsNameSchedulerTimeslice, + return writeSchedulerValueToSysfs(SysfsName::sysfsNameSchedulerTimeslice, pLinuxSysmanImp, subdeviceId, listOfEngines, engineType, timeslice); } ze_result_t LinuxSchedulerImp::setHeartbeatInterval(uint64_t heartbeat) { - return writeSchedulerValueToSysfs(SysfsName::syfsNameSchedulerWatchDogTimeout, + return writeSchedulerValueToSysfs(SysfsName::sysfsNameSchedulerWatchDogTimeout, pLinuxSysmanImp, subdeviceId, listOfEngines, engineType, heartbeat); } 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 index c4f74facd9..d3e66b1f35 100644 --- a/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.cpp +++ b/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.cpp @@ -185,7 +185,7 @@ ze_result_t FsAccessInterface::write(const std::string file, const std::string v ze_result_t FsAccessInterface::canRead(const std::string file) { struct stat sb; - if (statSyscall(file.c_str(), &sb) != 0) { + if (NEO::SysCalls::stat(file.c_str(), &sb) != 0) { return ZE_RESULT_ERROR_UNKNOWN; } if (sb.st_mode & S_IRUSR) { @@ -196,7 +196,7 @@ ze_result_t FsAccessInterface::canRead(const std::string file) { ze_result_t FsAccessInterface::canWrite(const std::string file) { struct stat sb; - if (statSyscall(file.c_str(), &sb) != 0) { + if (NEO::SysCalls::stat(file.c_str(), &sb) != 0) { return ZE_RESULT_ERROR_UNKNOWN; } if (sb.st_mode & S_IWUSR) { @@ -214,7 +214,7 @@ bool FsAccessInterface::fileExists(const std::string file) { ze_result_t FsAccessInterface::getFileMode(const std::string file, ::mode_t &mode) { struct stat sb; - if (0 != statSyscall(file.c_str(), &sb)) { + if (0 != NEO::SysCalls::stat(file.c_str(), &sb)) { return getResult(errno); } mode = sb.st_mode; @@ -296,7 +296,7 @@ bool FsAccessInterface::isRootUser() { } bool FsAccessInterface::directoryExists(const std::string path) { - if (accessSyscall(path.c_str(), F_OK)) { + if (NEO::SysCalls::access(path.c_str(), F_OK)) { return false; } return true; 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 index e02ecd3341..e8dc5826ec 100644 --- a/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h +++ b/level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h @@ -63,8 +63,6 @@ class FsAccessInterface { protected: FsAccessInterface(); - decltype(&NEO::SysCalls::access) accessSyscall = NEO::SysCalls::access; - decltype(&stat) statSyscall = stat; private: template 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 557c056e86..7553f36053 100644 --- a/level_zero/sysman/source/shared/linux/sysman_kmd_interface.cpp +++ b/level_zero/sysman/source/shared/linux/sysman_kmd_interface.cpp @@ -137,9 +137,11 @@ void SysmanKmdInterfaceI915::initSysfsNameToFileMap(const PRODUCT_FAMILY product sysfsNameToFileMap[SysfsName::sysfsNameMemoryAddressRange] = std::make_pair("addr_range", ""); sysfsNameToFileMap[SysfsName::sysfsNameMaxMemoryFrequency] = std::make_pair("mem_RP0_freq_mhz", ""); sysfsNameToFileMap[SysfsName::sysfsNameMinMemoryFrequency] = std::make_pair("mem_RPn_freq_mhz", ""); - sysfsNameToFileMap[SysfsName::syfsNameSchedulerTimeout] = std::make_pair("", "preempt_timeout_ms"); - sysfsNameToFileMap[SysfsName::syfsNameSchedulerTimeslice] = std::make_pair("", "timeslice_duration_ms"); - sysfsNameToFileMap[SysfsName::syfsNameSchedulerWatchDogTimeout] = std::make_pair("", "heartbeat_interval_ms"); + sysfsNameToFileMap[SysfsName::sysfsNameSchedulerTimeout] = std::make_pair("", "preempt_timeout_ms"); + sysfsNameToFileMap[SysfsName::sysfsNameSchedulerTimeslice] = std::make_pair("", "timeslice_duration_ms"); + sysfsNameToFileMap[SysfsName::sysfsNameSchedulerWatchDogTimeout] = std::make_pair("", "heartbeat_interval_ms"); + sysfsNameToFileMap[SysfsName::sysfsNamePerformanceMediaFrequencyFactor] = std::make_pair("media_freq_factor", ""); + sysfsNameToFileMap[SysfsName::sysfsNamePerformanceMediaFrequencyFactorScale] = std::make_pair("media_freq_factor.scale", ""); } void SysmanKmdInterfaceXe::initSysfsNameToFileMap(const PRODUCT_FAMILY productFamily) { @@ -167,10 +169,15 @@ void SysmanKmdInterfaceXe::initSysfsNameToFileMap(const PRODUCT_FAMILY productFa sysfsNameToFileMap[SysfsName::sysfsNameMemoryAddressRange] = std::make_pair("physical_vram_size_bytes", ""); sysfsNameToFileMap[SysfsName::sysfsNameMaxMemoryFrequency] = std::make_pair("freq_vram_rp0", ""); sysfsNameToFileMap[SysfsName::sysfsNameMinMemoryFrequency] = std::make_pair("freq_vram_rpn", ""); - sysfsNameToFileMap[SysfsName::syfsNameSchedulerTimeout] = std::make_pair("", "preempt_timeout_us"); - sysfsNameToFileMap[SysfsName::syfsNameSchedulerTimeslice] = std::make_pair("", "timeslice_duration_us"); - sysfsNameToFileMap[SysfsName::syfsNameSchedulerWatchDogTimeout] = std::make_pair("", "job_timeout_ms"); - sysfsNameToFileMap[SysfsName::syfsNameSchedulerWatchDogTimeoutMaximum] = std::make_pair("", "job_timeout_max"); + sysfsNameToFileMap[SysfsName::sysfsNameSchedulerTimeout] = std::make_pair("", "preempt_timeout_us"); + sysfsNameToFileMap[SysfsName::sysfsNameSchedulerTimeslice] = std::make_pair("", "timeslice_duration_us"); + sysfsNameToFileMap[SysfsName::sysfsNameSchedulerWatchDogTimeout] = std::make_pair("", "job_timeout_ms"); + sysfsNameToFileMap[SysfsName::sysfsNameSchedulerWatchDogTimeoutMaximum] = std::make_pair("", "job_timeout_max"); + sysfsNameToFileMap[SysfsName::sysfsNamePerformanceBaseFrequencyFactor] = std::make_pair("base_freq_factor", ""); + sysfsNameToFileMap[SysfsName::sysfsNamePerformanceBaseFrequencyFactorScale] = std::make_pair("base_freq_factor.scale", ""); + sysfsNameToFileMap[SysfsName::sysfsNamePerformanceMediaFrequencyFactor] = std::make_pair("media_freq_factor", ""); + sysfsNameToFileMap[SysfsName::sysfsNamePerformanceMediaFrequencyFactorScale] = std::make_pair("media_freq_factor.scale", ""); + sysfsNameToFileMap[SysfsName::sysfsNamePerformanceSystemPowerBalance] = std::make_pair("sys_pwr_balance", ""); } std::string SysmanKmdInterfaceXe::getSysfsFilePath(SysfsName sysfsName, uint32_t subDeviceId, bool prefixBaseDirectory) { @@ -246,14 +253,6 @@ std::string SysmanKmdInterfaceXe::getHwmonName(uint32_t subDeviceId, bool isSubd return filePath; } -bool SysmanKmdInterfaceI915::clientInfoAvailableInFdInfo() { - return false; -} - -bool SysmanKmdInterfaceXe::clientInfoAvailableInFdInfo() { - return true; -} - std::optional SysmanKmdInterfaceXe::getEngineClassString(uint16_t engineClass) { auto sysfEngineString = xeEngineClassToSysfsEngineMap.find(engineClass); if (sysfEngineString == xeEngineClassToSysfsEngineMap.end()) { 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 e75aca086d..b16ef8b7e7 100644 --- a/level_zero/sysman/source/shared/linux/sysman_kmd_interface.h +++ b/level_zero/sysman/source/shared/linux/sysman_kmd_interface.h @@ -84,10 +84,15 @@ enum class SysfsName { sysfsNameMemoryAddressRange, sysfsNameMaxMemoryFrequency, sysfsNameMinMemoryFrequency, - syfsNameSchedulerTimeout, - syfsNameSchedulerTimeslice, - syfsNameSchedulerWatchDogTimeout, - syfsNameSchedulerWatchDogTimeoutMaximum, + sysfsNameSchedulerTimeout, + sysfsNameSchedulerTimeslice, + sysfsNameSchedulerWatchDogTimeout, + sysfsNameSchedulerWatchDogTimeoutMaximum, + sysfsNamePerformanceBaseFrequencyFactor, + sysfsNamePerformanceMediaFrequencyFactor, + sysfsNamePerformanceBaseFrequencyFactorScale, + sysfsNamePerformanceMediaFrequencyFactorScale, + sysfsNamePerformanceSystemPowerBalance, }; class SysmanKmdInterface { @@ -107,9 +112,11 @@ 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; + virtual bool clientInfoAvailableInFdInfo() const = 0; virtual bool isGroupEngineInterfaceAvailable() const = 0; void initFsAccessInterface(const NEO::Drm &drm); + virtual bool isBaseFrequencyFactorAvailable() const = 0; + virtual bool isSystemPowerBalanceAvailable() const = 0; FsAccessInterface *getFsAccess(); ProcFsAccessInterface *getProcFsAccess(); SysFsAccessInterface *getSysFsAccess(); @@ -145,7 +152,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; + bool clientInfoAvailableInFdInfo() const override { return false; } bool isGroupEngineInterfaceAvailable() const override { return false; } std::string getEngineBasePath(uint32_t subDeviceId) const override { return "engine"; }; bool useDefaultMaximumWatchdogTimeoutForExclusiveMode() override { return false; }; @@ -156,6 +163,8 @@ class SysmanKmdInterfaceI915 : public SysmanKmdInterface { uint32_t subdeviceId) override; std::optional getEngineClassString(uint16_t engineClass) override; uint32_t getEventType(const bool isIntegratedDevice) override; + bool isBaseFrequencyFactorAvailable() const override { return false; } + bool isSystemPowerBalanceAvailable() const override { return false; } protected: std::map sysfsNameToFileMap; @@ -164,9 +173,9 @@ class SysmanKmdInterfaceI915 : public SysmanKmdInterface { return sysfsNameToNativeUnitMap; } const std::map sysfsNameToNativeUnitMap = { - {SysfsName::syfsNameSchedulerTimeout, milliSecond}, - {SysfsName::syfsNameSchedulerTimeslice, milliSecond}, - {SysfsName::syfsNameSchedulerWatchDogTimeout, milliSecond}, + {SysfsName::sysfsNameSchedulerTimeout, milliSecond}, + {SysfsName::sysfsNameSchedulerTimeslice, milliSecond}, + {SysfsName::sysfsNameSchedulerWatchDogTimeout, milliSecond}, }; }; @@ -182,7 +191,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; + bool clientInfoAvailableInFdInfo() const override { return true; } bool isGroupEngineInterfaceAvailable() const override { return true; } bool useDefaultMaximumWatchdogTimeoutForExclusiveMode() override { return true; }; ze_result_t getNumEngineTypeAndInstances(std::map> &mapOfEngines, @@ -192,6 +201,8 @@ class SysmanKmdInterfaceXe : public SysmanKmdInterface { uint32_t subdeviceId) override; std::optional getEngineClassString(uint16_t engineClass) override; uint32_t getEventType(const bool isIntegratedDevice) override; + bool isBaseFrequencyFactorAvailable() const override { return true; } + bool isSystemPowerBalanceAvailable() const override { return true; } protected: std::map sysfsNameToFileMap; @@ -200,10 +211,10 @@ class SysmanKmdInterfaceXe : public SysmanKmdInterface { return sysfsNameToNativeUnitMap; } const std::map sysfsNameToNativeUnitMap = { - {SysfsName::syfsNameSchedulerTimeout, microSecond}, - {SysfsName::syfsNameSchedulerTimeslice, microSecond}, - {SysfsName::syfsNameSchedulerWatchDogTimeout, milliSecond}, - {SysfsName::syfsNameSchedulerWatchDogTimeoutMaximum, milliSecond}, + {SysfsName::sysfsNameSchedulerTimeout, microSecond}, + {SysfsName::sysfsNameSchedulerTimeslice, microSecond}, + {SysfsName::sysfsNameSchedulerWatchDogTimeout, milliSecond}, + {SysfsName::sysfsNameSchedulerWatchDogTimeoutMaximum, milliSecond}, }; }; diff --git a/level_zero/sysman/test/unit_tests/sources/performance/linux/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/performance/linux/CMakeLists.txt index 460fca479b..707f8d313a 100644 --- a/level_zero/sysman/test/unit_tests/sources/performance/linux/CMakeLists.txt +++ b/level_zero/sysman/test/unit_tests/sources/performance/linux/CMakeLists.txt @@ -16,6 +16,7 @@ if(NEO_ENABLE_i915_PRELIM_DETECTION) else() list(APPEND L0_TESTS_SYSMAN_PERFORMANCE_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_performance.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_performance.h ) endif() diff --git a/level_zero/sysman/test/unit_tests/sources/performance/linux/mock_sysfs_performance.h b/level_zero/sysman/test/unit_tests/sources/performance/linux/mock_sysfs_performance.h new file mode 100644 index 0000000000..7dfcc81161 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/performance/linux/mock_sysfs_performance.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h" +#include "level_zero/sysman/source/shared/linux/sysman_kmd_interface.h" + +#include + +namespace L0 { +namespace Sysman { +namespace ult { + +class PublicLinuxPerformanceImp : public L0::Sysman::LinuxPerformanceImp { + public: + PublicLinuxPerformanceImp(L0::Sysman::OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_engine_type_flag_t domain) : L0::Sysman::LinuxPerformanceImp(pOsSysman, onSubdevice, subdeviceId, domain) {} + ~PublicLinuxPerformanceImp() override = default; + using L0::Sysman::LinuxPerformanceImp::pSysFsAccess; + using L0::Sysman::LinuxPerformanceImp::pSysmanKmdInterface; +}; + +class MockSysFsAccessInterface : public L0::Sysman::SysFsAccessInterface { + public: + MockSysFsAccessInterface() = default; + ~MockSysFsAccessInterface() override = default; +}; + +} // namespace ult +} // namespace Sysman +} // namespace L0 \ No newline at end of file diff --git a/level_zero/sysman/test/unit_tests/sources/performance/linux/test_zes_performance.cpp b/level_zero/sysman/test/unit_tests/sources/performance/linux/test_zes_performance.cpp index 22ade20587..c33ef8c7d4 100644 --- a/level_zero/sysman/test/unit_tests/sources/performance/linux/test_zes_performance.cpp +++ b/level_zero/sysman/test/unit_tests/sources/performance/linux/test_zes_performance.cpp @@ -9,71 +9,366 @@ #include "level_zero/sysman/source/api/performance/sysman_performance.h" #include "level_zero/sysman/source/api/performance/sysman_performance_imp.h" #include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h" +#include "level_zero/sysman/test/unit_tests/sources/performance/linux/mock_sysfs_performance.h" + +#include namespace L0 { namespace Sysman { namespace ult { -constexpr uint32_t mockHandleCount = 5; +static constexpr std::string_view i915MediaFreqFactorFileName0("gt/gt0/media_freq_factor"); +static constexpr std::string_view i915MediaFreqFactorScaleFileName0("gt/gt0/media_freq_factor.scale"); +static constexpr std::string_view i915BaseFreqFactorFileName0("gt/gt0/base_freq_factor"); +static constexpr std::string_view i915BaseFreqFactorScaleFileName0("gt/gt0/base_freq_factor.scale"); +static constexpr std::string_view i915MediaFreqFactorFileName1("gt/gt1/media_freq_factor"); +static constexpr std::string_view i915MediaFreqFactorScaleFileName1("gt/gt1/media_freq_factor.scale"); +static constexpr std::string_view i915BaseFreqFactorFileName1("gt/gt1/base_freq_factor"); +static constexpr std::string_view i915BaseFreqFactorScaleFileName1("gt/gt1/base_freq_factor.scale"); +static constexpr std::string_view sysPwrBalanceFileName("sys_pwr_balance"); + +static constexpr std::string_view xeMediaFreqFactorFileName0("device/tile0/gt0/media_freq_factor"); +static constexpr std::string_view xeMediaFreqFactorScaleFileName0("device/tile0/gt0/media_freq_factor.scale"); +static constexpr std::string_view xeBaseFreqFactorFileName0("device/tile0/gt0/base_freq_factor"); +static constexpr std::string_view xeBaseFreqFactorScaleFileName0("device/tile0/gt0/base_freq_factor.scale"); +static constexpr std::string_view xeSysPwrBalanceFileName0("device/tile0/gt0/sys_pwr_balance"); +static constexpr std::string_view xeMediaFreqFactorFileName1("device/tile1/gt1/media_freq_factor"); +static constexpr std::string_view xeMediaFreqFactorScaleFileName1("device/tile1/gt1/media_freq_factor.scale"); +static constexpr std::string_view xeBaseFreqFactorFileName1("device/tile1/gt1/base_freq_factor"); +static constexpr std::string_view xeBaseFreqFactorScaleFileName1("device/tile1/gt1/base_freq_factor.scale"); +static constexpr std::string_view xeSysPwrBalanceFileName1("device/tile1/gt1/sys_pwr_balance"); + +static double mockBaseFreq = 128.0; +static double mockMediaFreq = 256.0; +static double mockScale = 0.00390625; +static double mockSysPwrBalance = 0.0; +static double setFactor = 0; +static double getFactor = 0; + +static constexpr uint32_t mockI915HandleCount = 2; + +static int mockOpenSuccess(const char *pathname, int flags) { + int returnValue; + std::string strPathName(pathname); + if (strPathName == i915MediaFreqFactorFileName0 || strPathName == i915MediaFreqFactorFileName1 || strPathName == xeMediaFreqFactorFileName0 || strPathName == xeMediaFreqFactorFileName1) { + returnValue = 1; + } else if (strPathName == i915MediaFreqFactorScaleFileName0 || strPathName == i915MediaFreqFactorScaleFileName1 || strPathName == xeMediaFreqFactorScaleFileName0 || strPathName == xeMediaFreqFactorScaleFileName1) { + returnValue = 2; + } else if (strPathName == i915BaseFreqFactorFileName0 || strPathName == i915BaseFreqFactorFileName1 || strPathName == xeBaseFreqFactorFileName0 || strPathName == xeBaseFreqFactorFileName1) { + returnValue = 3; + } else if (strPathName == i915BaseFreqFactorScaleFileName0 || strPathName == i915BaseFreqFactorScaleFileName1 || strPathName == xeBaseFreqFactorScaleFileName0 || strPathName == xeBaseFreqFactorScaleFileName1) { + returnValue = 4; + } else if (strPathName == sysPwrBalanceFileName || strPathName == xeSysPwrBalanceFileName0 || strPathName == xeSysPwrBalanceFileName1) { + returnValue = 5; + } else { + returnValue = 0; + } + return returnValue; +} + +static ssize_t mockReadSuccess(int fd, void *buf, size_t count, off_t offset) { + std::ostringstream oStream; + if (fd == 1) { + oStream << mockMediaFreq; + } else if (fd == 2 || fd == 4) { + oStream << mockScale; + } else if (fd == 3) { + oStream << mockBaseFreq; + } else if (fd == 5) { + oStream << mockSysPwrBalance; + } else { + oStream << "0"; + } + std::string value = oStream.str(); + memcpy(buf, value.data(), count); + return count; +} + +static ssize_t mockReadFailure(int fd, void *buf, size_t count, off_t offset) { + errno = ENOENT; + return -1; +} + +static ssize_t mockWriteSuccess(int fd, const void *buf, size_t count, off_t offset) { + double multiplier = 0; + if (fd == 1) { + if (setFactor > halfOfMaxPerformanceFactor) { + multiplier = 1; + } else { + multiplier = 0.5; + } + } + multiplier = multiplier / mockScale; + multiplier = std::round(multiplier); + mockMediaFreq = multiplier; + return count; +} + +static int mockStatSuccess(const std::string &filePath, struct stat *statbuf) { + statbuf->st_mode = S_IRUSR | S_IWUSR; + return 0; +} + class ZesPerformanceFixture : public SysmanMultiDeviceFixture { protected: L0::Sysman::SysmanDevice *device = nullptr; +}; + +class ZesPerformanceFixtureI915 : public ZesPerformanceFixture { + protected: void SetUp() override { SysmanMultiDeviceFixture::SetUp(); device = pSysmanDevice; pSysmanDeviceImp->pPerformanceHandleContext->handleList.clear(); - getPerfHandles(0); } void TearDown() override { SysmanMultiDeviceFixture::TearDown(); } - std::vector getPerfHandles(uint32_t count) { + + std::vector getPerfHandlesForI915Version(uint32_t count) { std::vector handles(count, nullptr); + + VariableBackup mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess); + VariableBackup mockPread(&NEO::SysCalls::sysCallsPread, &mockReadSuccess); + VariableBackup mockPwrite(&NEO::SysCalls::sysCallsPwrite, &mockWriteSuccess); + EXPECT_EQ(zesDeviceEnumPerformanceFactorDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); return handles; } }; -TEST_F(ZesPerformanceFixture, GivenValidSysmanHandleWhenRetrievingPerfThenZeroHandlesInReturn) { - uint32_t handleCount = 0; +TEST_F(ZesPerformanceFixtureI915, GivenKmdInterfaceWhenGettingSysFsFilenamesForPerformanceForI915VersionThenProperPathsAreReturned) { + auto pSysmanKmdInterface = std::make_unique(pLinuxSysmanImp->getProductFamily()); + EXPECT_STREQ(std::string(i915MediaFreqFactorFileName0).c_str(), pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceMediaFrequencyFactor, 0, true).c_str()); + EXPECT_STREQ(std::string(i915MediaFreqFactorScaleFileName0).c_str(), pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceMediaFrequencyFactorScale, 0, true).c_str()); +} + +TEST_F(ZesPerformanceFixtureI915, GivenValidSysmanHandleWhenRetrievingPerfThenValidHandlesAreReturned) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + uint32_t count = 0; + getPerfHandlesForI915Version(count); + ze_result_t result = zesDeviceEnumPerformanceFactorDomains(device->toHandle(), &count, NULL); EXPECT_EQ(ZE_RESULT_SUCCESS, result); - EXPECT_EQ(count, handleCount); + EXPECT_EQ(count, mockI915HandleCount); uint32_t testcount = count + 1; result = zesDeviceEnumPerformanceFactorDomains(device->toHandle(), &testcount, NULL); EXPECT_EQ(ZE_RESULT_SUCCESS, result); - EXPECT_EQ(testcount, handleCount); + EXPECT_EQ(testcount, mockI915HandleCount); count = 0; std::vector handles(count, nullptr); EXPECT_EQ(zesDeviceEnumPerformanceFactorDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); - EXPECT_EQ(count, handleCount); + EXPECT_EQ(count, mockI915HandleCount); } -TEST_F(ZesPerformanceFixture, GivenValidOsSysmanPointerWhenCreatingOsPerformanceAndCallingPerformancePropertiesThenErrorIsReturned) { - uint32_t handleId = 0; - for (handleId = 0; handleId < mockHandleCount; handleId++) { - auto pPerformance = std::make_unique(pOsSysman, true, handleId, ZES_ENGINE_TYPE_FLAG_MEDIA); +TEST_F(ZesPerformanceFixtureI915, GivenValidPerfHandleWhenGettingPerformancePropertiesThenValidPropertiesReturned) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + + auto subDeviceCount = pLinuxSysmanImp->getSubDeviceCount(); + ze_bool_t onSubdevice = (subDeviceCount == 0) ? false : true; + uint32_t subdeviceId = 0; + + auto handle = getPerfHandlesForI915Version(mockI915HandleCount); + zes_perf_properties_t properties = {}; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetProperties(handle[0], &properties)); + EXPECT_TRUE(onSubdevice); + EXPECT_EQ(properties.engines, ZES_ENGINE_TYPE_FLAG_MEDIA); + EXPECT_EQ(properties.subdeviceId, subdeviceId); +} + +TEST_F(ZesPerformanceFixtureI915, GivenBaseAndOtherDomainTypeWhenGettingPerfHandlesThenZeroHandlesAreRetrieved) { + + PublicLinuxPerformanceImp *pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_COMPUTE); + EXPECT_FALSE(pLinuxPerformanceImp->isPerformanceSupported()); + delete pLinuxPerformanceImp; + + pLinuxPerformanceImp = nullptr; + pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_OTHER); + EXPECT_FALSE(pLinuxPerformanceImp->isPerformanceSupported()); + delete pLinuxPerformanceImp; +} + +TEST_F(ZesPerformanceFixtureI915, GivenMediaDomainTypeWhenGettingPerfHandlesThenValidHandleIsRetrieved) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + VariableBackup mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess); + VariableBackup mockPread(&NEO::SysCalls::sysCallsPread, &mockReadSuccess); + + auto pSysmanKmdInterface = std::make_unique(pLinuxSysmanImp->getProductFamily()); + auto pSysFsAccess = std::make_unique(); + + PublicLinuxPerformanceImp *pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_MEDIA); + pLinuxPerformanceImp->pSysmanKmdInterface = pSysmanKmdInterface.get(); + pLinuxPerformanceImp->pSysFsAccess = pSysFsAccess.get(); + EXPECT_TRUE(pLinuxPerformanceImp->isPerformanceSupported()); + delete pLinuxPerformanceImp; +} + +TEST_F(ZesPerformanceFixtureI915, GivenComputeDomainTypeWhenGettingPerfHandlesThenNotSupportedIsReturned) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + + auto pSysmanKmdInterface = std::make_unique(pLinuxSysmanImp->getProductFamily()); + auto pSysFsAccess = std::make_unique(); + + PublicLinuxPerformanceImp *pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_COMPUTE); + pLinuxPerformanceImp->pSysmanKmdInterface = pSysmanKmdInterface.get(); + pLinuxPerformanceImp->pSysFsAccess = pSysFsAccess.get(); + EXPECT_FALSE(pLinuxPerformanceImp->isPerformanceSupported()); + delete pLinuxPerformanceImp; + + pLinuxPerformanceImp = nullptr; + pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_OTHER); + pLinuxPerformanceImp->pSysmanKmdInterface = pSysmanKmdInterface.get(); + pLinuxPerformanceImp->pSysFsAccess = pSysFsAccess.get(); + EXPECT_FALSE(pLinuxPerformanceImp->isPerformanceSupported()); + delete pLinuxPerformanceImp; +} + +TEST_F(ZesPerformanceFixtureI915, GivenComputeDomainTypeWhenCallingPerformanceSetAndGetConfigThenNotSupportedIsReturned) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + + auto pSysmanKmdInterface = std::make_unique(pLinuxSysmanImp->getProductFamily()); + auto pSysFsAccess = std::make_unique(); + double pFactor = 0.0; + PublicLinuxPerformanceImp *pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_COMPUTE); + pLinuxPerformanceImp->pSysmanKmdInterface = pSysmanKmdInterface.get(); + pLinuxPerformanceImp->pSysFsAccess = pSysFsAccess.get(); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pLinuxPerformanceImp->osPerformanceSetConfig(pFactor)); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pLinuxPerformanceImp->osPerformanceGetConfig(&pFactor)); + delete pLinuxPerformanceImp; + + pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_OTHER); + pLinuxPerformanceImp->pSysmanKmdInterface = pSysmanKmdInterface.get(); + pLinuxPerformanceImp->pSysFsAccess = pSysFsAccess.get(); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pLinuxPerformanceImp->osPerformanceSetConfig(pFactor)); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pLinuxPerformanceImp->osPerformanceGetConfig(&pFactor)); + delete pLinuxPerformanceImp; +} + +TEST_F(ZesPerformanceFixtureI915, GivenValidPerfHandleAndPreadFailsWhenGettingPerformanceHandlesThenNoHandlesAreReturned) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + VariableBackup mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess); + VariableBackup mockPread(&NEO::SysCalls::sysCallsPread, &mockReadFailure); + + uint32_t mockCount = 0; + uint32_t count = 0; + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPerformanceFactorDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, mockCount); +} + +HWTEST2_F(ZesPerformanceFixtureI915, GivenValidPerfHandleAndInvalidArgumentWhenSettingMediaConfigForProductFamilyPVCThenErrorIsReturned, IsPVC) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + VariableBackup mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess); + VariableBackup mockPread(&NEO::SysCalls::sysCallsPread, &mockReadSuccess); + VariableBackup mockPwrite(&NEO::SysCalls::sysCallsPwrite, &mockWriteSuccess); + + uint32_t count = mockI915HandleCount; + setFactor = 500; + std::vector handles(count, nullptr); + zes_perf_properties_t properties = {}; + EXPECT_EQ(zesDeviceEnumPerformanceFactorDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetProperties(handles[0], &properties)); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, zesPerformanceFactorSetConfig(handles[0], setFactor)); +} + +HWTEST2_F(ZesPerformanceFixtureI915, GivenValidPerfHandleWhenSettingMediaConfigAndGettingMediaConfigWhenProductFamilyIsPVCThenValidConfigIsReturned, IsPVC) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + VariableBackup mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess); + VariableBackup mockPread(&NEO::SysCalls::sysCallsPread, &mockReadSuccess); + VariableBackup mockPwrite(&NEO::SysCalls::sysCallsPwrite, &mockWriteSuccess); + + uint32_t count = mockI915HandleCount; + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPerformanceFactorDomains(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + + for (const auto &handle : handles) { zes_perf_properties_t properties = {}; - EXPECT_FALSE(pPerformance->pOsPerformance->isPerformanceSupported()); - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pPerformance->pOsPerformance->osPerformanceGetProperties(properties)); - zes_perf_handle_t perfHandle = pPerformance->toPerformanceHandle(); - EXPECT_EQ(pPerformance.get(), L0::Sysman::Performance::fromHandle(perfHandle)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetProperties(handle, &properties)); + if (properties.engines == ZES_ENGINE_TYPE_FLAG_MEDIA) { + setFactor = 49; + getFactor = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), halfOfMaxPerformanceFactor); + + setFactor = 60; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), maxPerformanceFactor); + + setFactor = 100; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), maxPerformanceFactor); + + setFactor = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorSetConfig(handle, setFactor)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPerformanceFactorGetConfig(handle, &getFactor)); + EXPECT_DOUBLE_EQ(std::round(getFactor), halfOfMaxPerformanceFactor); + } } } -TEST_F(ZesPerformanceFixture, GivenValidOsSysmanPointerWhenCreatingOsPerformanceAndCallingPerformanceGetAndSetConfigThenErrorIsReturned) { - uint32_t handleId = 0; - for (handleId = 0; handleId < mockHandleCount; handleId++) { - auto pPerformance = std::make_unique(pOsSysman, true, handleId, ZES_ENGINE_TYPE_FLAG_MEDIA); - double factor = 0; - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pPerformance->performanceGetConfig(&factor)); - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pPerformance->performanceSetConfig(factor)); - zes_perf_handle_t perfHandle = pPerformance->toPerformanceHandle(); - EXPECT_EQ(pPerformance.get(), L0::Sysman::Performance::fromHandle(perfHandle)); +class ZesPerformanceFixtureXe : public ZesPerformanceFixture { + protected: + void SetUp() override { + SysmanMultiDeviceFixture::SetUp(); + device = pSysmanDevice; + pSysmanDeviceImp->pPerformanceHandleContext->handleList.clear(); } + void TearDown() override { + SysmanMultiDeviceFixture::TearDown(); + } +}; + +TEST_F(ZesPerformanceFixtureXe, GivenKmdInterfaceWhenGettingSysFsFilenamesForPerformanceForXeVersionThenProperPathsAreReturned) { + auto pSysmanKmdInterface = std::make_unique(pLinuxSysmanImp->getProductFamily()); + EXPECT_STREQ(std::string(xeMediaFreqFactorFileName0).c_str(), pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceMediaFrequencyFactor, 0, true).c_str()); + EXPECT_STREQ(std::string(xeMediaFreqFactorScaleFileName0).c_str(), pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceMediaFrequencyFactorScale, 0, true).c_str()); + EXPECT_STREQ(std::string(xeBaseFreqFactorFileName0).c_str(), pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceBaseFrequencyFactor, 0, true).c_str()); + EXPECT_STREQ(std::string(xeBaseFreqFactorScaleFileName0).c_str(), pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceBaseFrequencyFactorScale, 0, true).c_str()); + EXPECT_STREQ(std::string(xeSysPwrBalanceFileName0).c_str(), pSysmanKmdInterface->getSysfsFilePath(SysfsName::sysfsNamePerformanceSystemPowerBalance, 0, true).c_str()); +} + +TEST_F(ZesPerformanceFixtureXe, GivenComputeDomainTypeWhenGettingPerfHandlesThenCorrespondingHandlesAreRetrieved) { + + VariableBackup mockStat(&NEO::SysCalls::sysCallsStat, &mockStatSuccess); + VariableBackup mockOpen(&NEO::SysCalls::sysCallsOpen, &mockOpenSuccess); + VariableBackup mockPread(&NEO::SysCalls::sysCallsPread, &mockReadSuccess); + + auto pSysmanKmdInterface = std::make_unique(pLinuxSysmanImp->getProductFamily()); + auto pSysFsAccess = std::make_unique(); + + PublicLinuxPerformanceImp *pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_COMPUTE); + pLinuxPerformanceImp->pSysmanKmdInterface = pSysmanKmdInterface.get(); + pLinuxPerformanceImp->pSysFsAccess = pSysFsAccess.get(); + EXPECT_TRUE(pLinuxPerformanceImp->isPerformanceSupported()); + delete pLinuxPerformanceImp; + + pLinuxPerformanceImp = nullptr; + pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_MEDIA); + pLinuxPerformanceImp->pSysmanKmdInterface = pSysmanKmdInterface.get(); + pLinuxPerformanceImp->pSysFsAccess = pSysFsAccess.get(); + EXPECT_TRUE(pLinuxPerformanceImp->isPerformanceSupported()); + delete pLinuxPerformanceImp; + + pLinuxPerformanceImp = nullptr; + pLinuxPerformanceImp = new PublicLinuxPerformanceImp(pOsSysman, 1, 0u, ZES_ENGINE_TYPE_FLAG_OTHER); + pLinuxPerformanceImp->pSysmanKmdInterface = pSysmanKmdInterface.get(); + pLinuxPerformanceImp->pSysFsAccess = pSysFsAccess.get(); + EXPECT_TRUE(pLinuxPerformanceImp->isPerformanceSupported()); + delete pLinuxPerformanceImp; } } // namespace ult diff --git a/level_zero/sysman/test/unit_tests/sources/shared/linux/sysman_kmd_interface_tests.cpp b/level_zero/sysman/test/unit_tests/sources/shared/linux/sysman_kmd_interface_tests.cpp index 59c3f55b34..e3bfd0c4cf 100644 --- a/level_zero/sysman/test/unit_tests/sources/shared/linux/sysman_kmd_interface_tests.cpp +++ b/level_zero/sysman/test/unit_tests/sources/shared/linux/sysman_kmd_interface_tests.cpp @@ -49,6 +49,12 @@ TEST_F(SysmanFixtureDeviceI915, GivenSysmanKmdInterfaceInstanceWhenIsGroupEngine EXPECT_FALSE(pSysmanKmdInterface->isGroupEngineInterfaceAvailable()); } +TEST_F(SysmanFixtureDeviceI915, GivenSysmanKmdInterfaceInstanceWhenCheckingAvailabilityOfBaseFrequencyFactorAndSystemPowerBalanceThenFalseValueIsReturned) { + auto pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get(); + EXPECT_FALSE(pSysmanKmdInterface->isBaseFrequencyFactorAvailable()); + EXPECT_FALSE(pSysmanKmdInterface->isSystemPowerBalanceAvailable()); +} + TEST_F(SysmanFixtureDeviceI915, GivenGroupEngineTypeAndSysmanKmdInterfaceInstanceWhenGetEngineActivityFdIsCalledThenInvalidFdIsReturned) { VariableBackup mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int { @@ -180,6 +186,12 @@ TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceInstanceWhenIsGroupEngineIn EXPECT_TRUE(pSysmanKmdInterface->isGroupEngineInterfaceAvailable()); } +TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceInstanceWhenCheckingAvailabilityOfBaseFrequencyFactorAndSystemPowerBalanceThenTrueValueIsReturned) { + auto pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get(); + EXPECT_TRUE(pSysmanKmdInterface->isBaseFrequencyFactorAvailable()); + EXPECT_TRUE(pSysmanKmdInterface->isSystemPowerBalanceAvailable()); +} + TEST_F(SysmanFixtureDeviceXe, GivenGroupEngineTypeAndSysmanKmdInterfaceInstanceWhenGetEngineActivityFdIsCalledThenValidFdIsReturned) { auto pSysmanKmdInterface = std::make_unique(pLinuxSysmanImp->getProductFamily());