From e5036ce9f088a976bf59b1292a0caf25105be266 Mon Sep 17 00:00:00 2001 From: shubham kumar Date: Tue, 2 Jul 2024 08:07:34 +0000 Subject: [PATCH] feature(sysman): windows add support for card and package power Related-To: NEO-11820 Signed-off-by: shubham kumar --- .../api/power/linux/sysman_os_power_imp.cpp | 13 ++- .../api/power/linux/sysman_os_power_imp.h | 3 +- .../sysman/source/api/power/sysman_os_power.h | 8 +- .../sysman/source/api/power/sysman_power.cpp | 19 ++-- .../sysman/source/api/power/sysman_power.h | 4 +- .../source/api/power/sysman_power_imp.cpp | 4 +- .../source/api/power/sysman_power_imp.h | 2 +- .../api/power/windows/sysman_os_power_imp.cpp | 87 ++++++++++++++- .../api/power/windows/sysman_os_power_imp.h | 3 +- .../source/shared/windows/sysman_kmd_sys.h | 9 +- .../sources/power/linux/mock_sysfs_power.h | 2 +- .../sources/power/linux/test_zes_power.cpp | 4 +- .../power/linux/test_zes_power_helper.cpp | 2 +- .../sources/power/windows/mock_power.h | 21 ++-- .../power/windows/test_zes_sysman_power.cpp | 102 ++++++++++++++++-- .../test/black_box_tests/zello_sysman.cpp | 30 +++++- 16 files changed, 262 insertions(+), 51 deletions(-) diff --git a/level_zero/sysman/source/api/power/linux/sysman_os_power_imp.cpp b/level_zero/sysman/source/api/power/linux/sysman_os_power_imp.cpp index 2b952bbd29..69ce985b42 100644 --- a/level_zero/sysman/source/api/power/linux/sysman_os_power_imp.cpp +++ b/level_zero/sysman/source/api/power/linux/sysman_os_power_imp.cpp @@ -58,7 +58,7 @@ ze_result_t LinuxPowerImp::getDefaultLimit(int32_t &defaultLimit) { } ze_result_t LinuxPowerImp::getPropertiesExt(zes_power_ext_properties_t *pExtPoperties) { - pExtPoperties->domain = isSubdevice ? ZES_POWER_DOMAIN_PACKAGE : ZES_POWER_DOMAIN_CARD; + pExtPoperties->domain = isSubdevice ? ZES_POWER_DOMAIN_PACKAGE : powerDomain; if (pExtPoperties->defaultLimit) { if (!isSubdevice) { uint64_t val = 0; @@ -320,7 +320,7 @@ bool LinuxPowerImp::isPowerModuleSupported() { return true; } -LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) : isSubdevice(onSubdevice), subdeviceId(subdeviceId) { +LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain) : isSubdevice(onSubdevice), subdeviceId(subdeviceId), powerDomain(powerDomain) { LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); pPmt = pLinuxSysmanImp->getPlatformMonitoringTechAccess(subdeviceId); pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface(); @@ -328,8 +328,13 @@ LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_ pSysmanProductHelper = pLinuxSysmanImp->getSysmanProductHelper(); } -OsPower *OsPower::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { - LinuxPowerImp *pLinuxPowerImp = new LinuxPowerImp(pOsSysman, onSubdevice, subdeviceId); +std::vector OsPower::getNumberOfPowerDomainsSupported(OsSysman *pOsSysman) { + std::vector powerDomains = {ZES_POWER_DOMAIN_CARD}; + return powerDomains; +} + +OsPower *OsPower::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain) { + LinuxPowerImp *pLinuxPowerImp = new LinuxPowerImp(pOsSysman, onSubdevice, subdeviceId, powerDomain); return static_cast(pLinuxPowerImp); } } // namespace Sysman diff --git a/level_zero/sysman/source/api/power/linux/sysman_os_power_imp.h b/level_zero/sysman/source/api/power/linux/sysman_os_power_imp.h index 5bcca2af1f..6c37a6c5ce 100644 --- a/level_zero/sysman/source/api/power/linux/sysman_os_power_imp.h +++ b/level_zero/sysman/source/api/power/linux/sysman_os_power_imp.h @@ -36,7 +36,7 @@ class LinuxPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { bool isPowerModuleSupported() override; bool isIntelGraphicsHwmonDir(const std::string &name); ze_result_t getPmtEnergyCounter(zes_power_energy_counter_t *pEnergy); - LinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); + LinuxPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain); LinuxPowerImp() = default; ~LinuxPowerImp() override = default; @@ -55,6 +55,7 @@ class LinuxPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { bool isSubdevice = false; uint32_t subdeviceId = 0; uint32_t powerLimitCount = 0; + zes_power_domain_t powerDomain = ZES_POWER_DOMAIN_CARD; ze_result_t getErrorCode(ze_result_t result) { if (result == ZE_RESULT_ERROR_NOT_AVAILABLE) { diff --git a/level_zero/sysman/source/api/power/sysman_os_power.h b/level_zero/sysman/source/api/power/sysman_os_power.h index 11b7d0cb3f..0b0a153b82 100644 --- a/level_zero/sysman/source/api/power/sysman_os_power.h +++ b/level_zero/sysman/source/api/power/sysman_os_power.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -9,6 +9,8 @@ #include +#include + namespace L0 { namespace Sysman { @@ -26,7 +28,9 @@ class OsPower { virtual ze_result_t getPropertiesExt(zes_power_ext_properties_t *pExtPoperties) = 0; virtual bool isPowerModuleSupported() = 0; - static OsPower *create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); + static OsPower *create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain); + static std::vector getNumberOfPowerDomainsSupported(OsSysman *pOsSysman); + virtual ~OsPower() = default; }; diff --git a/level_zero/sysman/source/api/power/sysman_power.cpp b/level_zero/sysman/source/api/power/sysman_power.cpp index 126f24f870..186683b4b4 100644 --- a/level_zero/sysman/source/api/power/sysman_power.cpp +++ b/level_zero/sysman/source/api/power/sysman_power.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2023-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -9,6 +9,7 @@ #include "shared/source/helpers/basic_math.h" +#include "level_zero/sysman/source/api/power/sysman_os_power.h" #include "level_zero/sysman/source/api/power/sysman_power_imp.h" #include "level_zero/sysman/source/device/os_sysman.h" @@ -26,8 +27,8 @@ PowerHandleContext::~PowerHandleContext() { releasePowerHandles(); } -void PowerHandleContext::createHandle(ze_bool_t isSubDevice, uint32_t subDeviceId) { - Power *pPower = new PowerImp(pOsSysman, isSubDevice, subDeviceId); +void PowerHandleContext::createHandle(ze_bool_t isSubDevice, uint32_t subDeviceId, zes_power_domain_t powerDomain) { + Power *pPower = new PowerImp(pOsSysman, isSubDevice, subDeviceId, powerDomain); if (pPower->initSuccess == true) { handleList.push_back(pPower); } else { @@ -35,11 +36,17 @@ void PowerHandleContext::createHandle(ze_bool_t isSubDevice, uint32_t subDeviceI } } ze_result_t PowerHandleContext::init(uint32_t subDeviceCount) { - // Create Handle for card level power - createHandle(false, 0); + + auto totalDomains = OsPower::getNumberOfPowerDomainsSupported(pOsSysman); + + for (auto &powerDomain : totalDomains) { + createHandle(false, 0, powerDomain); + } for (uint32_t subDeviceId = 0; subDeviceId < subDeviceCount; subDeviceId++) { - createHandle(true, subDeviceId); + for (auto &powerDomain : totalDomains) { + createHandle(true, subDeviceId, powerDomain); + } } return ZE_RESULT_SUCCESS; diff --git a/level_zero/sysman/source/api/power/sysman_power.h b/level_zero/sysman/source/api/power/sysman_power.h index 7bf533e626..4e1529cc6d 100644 --- a/level_zero/sysman/source/api/power/sysman_power.h +++ b/level_zero/sysman/source/api/power/sysman_power.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2023-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -52,7 +52,7 @@ struct PowerHandleContext { } private: - void createHandle(ze_bool_t isSubDevice, uint32_t subDeviceId); + void createHandle(ze_bool_t isSubDevice, uint32_t subDeviceId, zes_power_domain_t powerDomain); std::once_flag initPowerOnce; void initPower(); bool powerInitDone = false; diff --git a/level_zero/sysman/source/api/power/sysman_power_imp.cpp b/level_zero/sysman/source/api/power/sysman_power_imp.cpp index 95b8556809..93b242e418 100644 --- a/level_zero/sysman/source/api/power/sysman_power_imp.cpp +++ b/level_zero/sysman/source/api/power/sysman_power_imp.cpp @@ -64,9 +64,9 @@ ze_result_t PowerImp::powerSetEnergyThreshold(double threshold) { return pOsPower->setEnergyThreshold(threshold); } -PowerImp::PowerImp(OsSysman *pOsSysman, ze_bool_t isSubDevice, uint32_t subDeviceId) { +PowerImp::PowerImp(OsSysman *pOsSysman, ze_bool_t isSubDevice, uint32_t subDeviceId, zes_power_domain_t powerDomain) { - pOsPower = OsPower::create(pOsSysman, isSubDevice, subDeviceId); + pOsPower = OsPower::create(pOsSysman, isSubDevice, subDeviceId, powerDomain); UNRECOVERABLE_IF(nullptr == pOsPower); this->isCardPower = isSubDevice ? false : true; init(); diff --git a/level_zero/sysman/source/api/power/sysman_power_imp.h b/level_zero/sysman/source/api/power/sysman_power_imp.h index 560283542e..e4ec996245 100644 --- a/level_zero/sysman/source/api/power/sysman_power_imp.h +++ b/level_zero/sysman/source/api/power/sysman_power_imp.h @@ -26,7 +26,7 @@ class PowerImp : public Power, NEO::NonCopyableOrMovableClass { ze_result_t powerSetLimitsExt(uint32_t *pCount, zes_power_limit_ext_desc_t *pSustained) override; PowerImp() = default; - PowerImp(OsSysman *pOsSysman, ze_bool_t isSubDevice, uint32_t subDeviceId); + PowerImp(OsSysman *pOsSysman, ze_bool_t isSubDevice, uint32_t subDeviceId, zes_power_domain_t powerDomain); ~PowerImp() override; OsPower *pOsPower = nullptr; diff --git a/level_zero/sysman/source/api/power/windows/sysman_os_power_imp.cpp b/level_zero/sysman/source/api/power/windows/sysman_os_power_imp.cpp index c0634e0891..74f088e0a1 100644 --- a/level_zero/sysman/source/api/power/windows/sysman_os_power_imp.cpp +++ b/level_zero/sysman/source/api/power/windows/sysman_os_power_imp.cpp @@ -14,6 +14,11 @@ namespace L0 { namespace Sysman { +static const std::map powerGroupToDomainTypeMap = { + {ZES_POWER_DOMAIN_CARD, KmdSysman::PowerDomainsType::powerDomainCard}, + {ZES_POWER_DOMAIN_PACKAGE, KmdSysman::PowerDomainsType::powerDomainPackage}, +}; + ze_result_t WddmPowerImp::getProperties(zes_power_properties_t *pProperties) { pProperties->onSubdevice = false; pProperties->subdeviceId = 0; @@ -24,6 +29,7 @@ ze_result_t WddmPowerImp::getProperties(zes_power_properties_t *pProperties) { request.commandId = KmdSysman::Command::Get; request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); request.requestId = KmdSysman::Requests::Power::EnergyThresholdSupported; vRequests.push_back(request); @@ -66,7 +72,32 @@ ze_result_t WddmPowerImp::getProperties(zes_power_properties_t *pProperties) { } ze_result_t WddmPowerImp::getPropertiesExt(zes_power_ext_properties_t *pExtPoperties) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + pExtPoperties->domain = powerDomain; + if (pExtPoperties->defaultLimit) { + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); + request.requestId = KmdSysman::Requests::Power::TdpDefault; + + ze_result_t status = pKmdSysManager->requestSingle(request, response); + pExtPoperties->defaultLimit->limit = -1; + + if (status == ZE_RESULT_SUCCESS) { + memcpy_s(&pExtPoperties->defaultLimit->limit, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + } + + pExtPoperties->defaultLimit->limitUnit = ZES_LIMIT_UNIT_POWER; + pExtPoperties->defaultLimit->enabledStateLocked = true; + pExtPoperties->defaultLimit->intervalValueLocked = true; + pExtPoperties->defaultLimit->limitValueLocked = true; + pExtPoperties->defaultLimit->source = ZES_POWER_SOURCE_ANY; + pExtPoperties->defaultLimit->level = ZES_POWER_LEVEL_UNKNOWN; + } + + return ZE_RESULT_SUCCESS; } ze_result_t WddmPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy) { @@ -76,6 +107,7 @@ ze_result_t WddmPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy) request.commandId = KmdSysman::Command::Get; request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); request.requestId = KmdSysman::Requests::Power::CurrentEnergyCounter64Bit; ze_result_t status = pKmdSysManager->requestSingle(request, response); @@ -96,6 +128,7 @@ ze_result_t WddmPowerImp::getLimits(zes_power_sustained_limit_t *pSustained, zes request.commandId = KmdSysman::Command::Get; request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); if (pSustained) { memset(pSustained, 0, sizeof(zes_power_sustained_limit_t)); @@ -189,6 +222,7 @@ ze_result_t WddmPowerImp::setLimits(const zes_power_sustained_limit_t *pSustaine request.commandId = KmdSysman::Command::Set; request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); request.dataSize = sizeof(uint32_t); if (pSustained) { @@ -255,6 +289,7 @@ ze_result_t WddmPowerImp::getEnergyThreshold(zes_energy_threshold_t *pThreshold) request.commandId = KmdSysman::Command::Get; request.componentId = KmdSysman::Component::PowerComponent; request.requestId = KmdSysman::Requests::Power::CurrentEnergyThreshold; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); ze_result_t status = pKmdSysManager->requestSingle(request, response); @@ -278,6 +313,7 @@ ze_result_t WddmPowerImp::setEnergyThreshold(double threshold) { request.commandId = KmdSysman::Command::Set; request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); request.requestId = KmdSysman::Requests::Power::CurrentEnergyThreshold; request.dataSize = sizeof(uint32_t); @@ -295,6 +331,7 @@ bool WddmPowerImp::isPowerModuleSupported() { request.commandId = KmdSysman::Command::Get; request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); request.requestId = KmdSysman::Requests::Power::PowerLimit1Enabled; vRequests.push_back(request); @@ -349,6 +386,7 @@ ze_result_t WddmPowerImp::getLimitsExt(uint32_t *pCount, zes_power_limit_ext_des request.commandId = KmdSysman::Command::Get; request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); request.requestId = KmdSysman::Requests::Power::PowerLimit1Enabled; vRequests.push_back(request); @@ -455,6 +493,7 @@ ze_result_t WddmPowerImp::setLimitsExt(uint32_t *pCount, zes_power_limit_ext_des request.commandId = KmdSysman::Command::Set; request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(this->powerDomain)); request.dataSize = sizeof(uint32_t); for (uint32_t i = 0; i < *pCount; i++) { @@ -493,13 +532,53 @@ ze_result_t WddmPowerImp::setLimitsExt(uint32_t *pCount, zes_power_limit_ext_des return status; } -WddmPowerImp::WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { +WddmPowerImp::WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain) : powerDomain(powerDomain) { WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); } -OsPower *OsPower::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { - WddmPowerImp *pWddmPowerImp = new WddmPowerImp(pOsSysman, onSubdevice, subdeviceId); +std::vector OsPower::getNumberOfPowerDomainsSupported(OsSysman *pOsSysman) { + WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); + KmdSysManager *pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); + + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::NumPowerDomains; + + ze_result_t status = pKmdSysManager->requestSingle(request, response); + + std::vector powerDomains; + if (status != ZE_RESULT_SUCCESS) { + NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, + "No power domains are supported, power handles will not be created.\n"); + return powerDomains; + } + + uint32_t supportedPowerDomains = 0; + memcpy_s(&supportedPowerDomains, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + + switch (supportedPowerDomains) { + case 1: + powerDomains.push_back(ZES_POWER_DOMAIN_PACKAGE); + break; + case 2: + powerDomains.push_back(ZES_POWER_DOMAIN_PACKAGE); + powerDomains.push_back(ZES_POWER_DOMAIN_CARD); + break; + default: + NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, + "Unexpected value returned by KMD, power handles will not be created.\n"); + break; + } + + return powerDomains; +} + +OsPower *OsPower::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain) { + WddmPowerImp *pWddmPowerImp = new WddmPowerImp(pOsSysman, onSubdevice, subdeviceId, powerDomain); return static_cast(pWddmPowerImp); } diff --git a/level_zero/sysman/source/api/power/windows/sysman_os_power_imp.h b/level_zero/sysman/source/api/power/windows/sysman_os_power_imp.h index bc8e567445..e34807de2c 100644 --- a/level_zero/sysman/source/api/power/windows/sysman_os_power_imp.h +++ b/level_zero/sysman/source/api/power/windows/sysman_os_power_imp.h @@ -26,13 +26,14 @@ class WddmPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { ze_result_t getPropertiesExt(zes_power_ext_properties_t *pExtPoperties) override; bool isPowerModuleSupported() override; - WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); + WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain); WddmPowerImp() = default; ~WddmPowerImp() override = default; protected: KmdSysManager *pKmdSysManager = nullptr; uint32_t powerLimitCount = 0; + zes_power_domain_t powerDomain = ZES_POWER_DOMAIN_CARD; }; } // namespace Sysman diff --git a/level_zero/sysman/source/shared/windows/sysman_kmd_sys.h b/level_zero/sysman/source/shared/windows/sysman_kmd_sys.h index 8581a900a3..3c2ece2ff2 100644 --- a/level_zero/sysman/source/shared/windows/sysman_kmd_sys.h +++ b/level_zero/sysman/source/shared/windows/sysman_kmd_sys.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -361,6 +361,13 @@ enum TemperatureDomainsType { TempetatureMaxDomainTypes, }; +enum class PowerDomainsType { + powerDomainPackage = 0, + powerDomainCard, + + powerMaxDomainTypes, +}; + enum ActivityDomainsType { ActitvityDomainGT = 0, ActivityDomainRenderCompute, diff --git a/level_zero/sysman/test/unit_tests/sources/power/linux/mock_sysfs_power.h b/level_zero/sysman/test/unit_tests/sources/power/linux/mock_sysfs_power.h index a37083a1e3..900bd31f70 100644 --- a/level_zero/sysman/test/unit_tests/sources/power/linux/mock_sysfs_power.h +++ b/level_zero/sysman/test/unit_tests/sources/power/linux/mock_sysfs_power.h @@ -301,7 +301,7 @@ struct MockPowerFsAccess : public L0::Sysman::FsAccessInterface { class PublicLinuxPowerImp : public L0::Sysman::LinuxPowerImp { public: - PublicLinuxPowerImp(L0::Sysman::OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) : L0::Sysman::LinuxPowerImp(pOsSysman, onSubdevice, subdeviceId) {} + PublicLinuxPowerImp(L0::Sysman::OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain) : L0::Sysman::LinuxPowerImp(pOsSysman, onSubdevice, subdeviceId, powerDomain) {} using L0::Sysman::LinuxPowerImp::pPmt; using L0::Sysman::LinuxPowerImp::pSysfsAccess; }; diff --git a/level_zero/sysman/test/unit_tests/sources/power/linux/test_zes_power.cpp b/level_zero/sysman/test/unit_tests/sources/power/linux/test_zes_power.cpp index a28aec3226..162f65b8b7 100644 --- a/level_zero/sysman/test/unit_tests/sources/power/linux/test_zes_power.cpp +++ b/level_zero/sysman/test/unit_tests/sources/power/linux/test_zes_power.cpp @@ -207,7 +207,7 @@ TEST_F(SysmanDevicePowerFixtureI915, GivenValidPowerHandleAndPowerSetLimitSuppor } TEST_F(SysmanDevicePowerFixtureI915, GivenValidPowerHandleWhenGettingPowerPropertiesAndSysfsReadFailsThenFailureIsReturned) { - std::unique_ptr pLinuxPowerImp(new PublicLinuxPowerImp(pOsSysman, false, 0)); + std::unique_ptr pLinuxPowerImp(new PublicLinuxPowerImp(pOsSysman, false, 0, ZES_POWER_DOMAIN_CARD)); pLinuxPowerImp->pSysfsAccess = pSysfsAccess; pLinuxPowerImp->pPmt = static_cast(pLinuxSysmanImp->getPlatformMonitoringTechAccess(0)); pLinuxPowerImp->isPowerModuleSupported(); @@ -708,7 +708,7 @@ TEST_F(SysmanDevicePowerFixtureI915, GivenScanDirectoriesFailAndPmtIsNotNullPoin pSysmanDeviceImp->pPowerHandleContext->init(subDeviceCount); ze_bool_t onSubdevice = (subDeviceCount == 0) ? false : true; uint32_t subdeviceId = 0; - PublicLinuxPowerImp *pPowerImp = new PublicLinuxPowerImp(pOsSysman, onSubdevice, subdeviceId); + PublicLinuxPowerImp *pPowerImp = new PublicLinuxPowerImp(pOsSysman, onSubdevice, subdeviceId, ZES_POWER_DOMAIN_CARD); EXPECT_TRUE(pPowerImp->isPowerModuleSupported()); delete pPowerImp; } diff --git a/level_zero/sysman/test/unit_tests/sources/power/linux/test_zes_power_helper.cpp b/level_zero/sysman/test/unit_tests/sources/power/linux/test_zes_power_helper.cpp index 8cd17eafed..3c668c92b2 100644 --- a/level_zero/sysman/test/unit_tests/sources/power/linux/test_zes_power_helper.cpp +++ b/level_zero/sysman/test/unit_tests/sources/power/linux/test_zes_power_helper.cpp @@ -32,7 +32,7 @@ TEST_F(SysmanDevicePowerMultiDeviceFixtureHelper, GivenValidDeviceHandlesAndHwmo uint32_t subdeviceId = 0; do { ze_bool_t onSubdevice = (subDeviceCount == 0) ? false : true; - PublicLinuxPowerImp *pPowerImp = new PublicLinuxPowerImp(pOsSysman, onSubdevice, subdeviceId); + PublicLinuxPowerImp *pPowerImp = new PublicLinuxPowerImp(pOsSysman, onSubdevice, subdeviceId, ZES_POWER_DOMAIN_CARD); EXPECT_TRUE(pPowerImp->isPowerModuleSupported()); delete pPowerImp; diff --git a/level_zero/sysman/test/unit_tests/sources/power/windows/mock_power.h b/level_zero/sysman/test/unit_tests/sources/power/windows/mock_power.h index 6a8c60e1a7..ddcbae334a 100644 --- a/level_zero/sysman/test/unit_tests/sources/power/windows/mock_power.h +++ b/level_zero/sysman/test/unit_tests/sources/power/windows/mock_power.h @@ -16,6 +16,7 @@ constexpr uint32_t mockLimitCount = 3u; struct PowerKmdSysManager : public MockKmdSysManager { + uint32_t mockPowerDomainCount = 2; uint32_t mockPowerLimit1Enabled = 1; uint32_t mockPowerLimit2Enabled = 1; int32_t mockPowerLimit1 = 25000; @@ -32,8 +33,6 @@ struct PowerKmdSysManager : public MockKmdSysManager { uint32_t mockEnergyUnit = 14; uint64_t mockEnergyCounter64Bit = 32323232323232; uint32_t mockFrequencyTimeStamp = 38400000; - bool mockPowerLimit2EnabledFailure = false; - bool mockPowerLimit1EnabledFailure = false; uint32_t mockPowerFailure[KmdSysman::Requests::Power::MaxPowerRequests] = {0}; void getActivityProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) override { @@ -63,6 +62,12 @@ struct PowerKmdSysManager : public MockKmdSysManager { pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); switch (pRequest->inRequestId) { + case KmdSysman::Requests::Power::NumPowerDomains: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockPowerDomainCount; + pResponse->outReturnCode = getReturnCode(pRequest->inRequestId); + pResponse->outDataSize = sizeof(uint32_t); + } break; case KmdSysman::Requests::Power::EnergyThresholdSupported: { uint32_t *pValue = reinterpret_cast(pBuffer); *pValue = static_cast(this->allowSetCalls); @@ -89,21 +94,13 @@ struct PowerKmdSysManager : public MockKmdSysManager { } break; case KmdSysman::Requests::Power::PowerLimit1Enabled: { uint32_t *pValue = reinterpret_cast(pBuffer); - if (mockPowerLimit1EnabledFailure) { - *pValue = 0; - } else { - *pValue = mockPowerLimit1Enabled; - } + *pValue = mockPowerLimit1Enabled; pResponse->outReturnCode = getReturnCode(pRequest->inRequestId); pResponse->outDataSize = sizeof(uint32_t); } break; case KmdSysman::Requests::Power::PowerLimit2Enabled: { uint32_t *pValue = reinterpret_cast(pBuffer); - if (mockPowerLimit2EnabledFailure) { - *pValue = false; - } else { - *pValue = mockPowerLimit2Enabled; - } + *pValue = mockPowerLimit2Enabled; pResponse->outReturnCode = getReturnCode(pRequest->inRequestId); pResponse->outDataSize = sizeof(uint32_t); } break; diff --git a/level_zero/sysman/test/unit_tests/sources/power/windows/test_zes_sysman_power.cpp b/level_zero/sysman/test/unit_tests/sources/power/windows/test_zes_sysman_power.cpp index 7ebfd16d4d..025b5e78c5 100644 --- a/level_zero/sysman/test/unit_tests/sources/power/windows/test_zes_sysman_power.cpp +++ b/level_zero/sysman/test/unit_tests/sources/power/windows/test_zes_sysman_power.cpp @@ -12,7 +12,7 @@ namespace L0 { namespace Sysman { namespace ult { -constexpr uint32_t powerHandleComponentCount = 1u; +constexpr uint32_t powerHandleComponentCount = 2u; class SysmanDevicePowerFixture : public SysmanDeviceFixture { protected: @@ -57,6 +57,33 @@ TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDoma EXPECT_EQ(count, powerHandleComponentCount); } +TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainWithOnlyOneDomainSupportedThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { + init(true); + + uint32_t count = 0; + pKmdSysManager->mockPowerDomainCount = 1; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, pKmdSysManager->mockPowerDomainCount); +} + +TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainWithKmdFailureThenZeroCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { + init(true); + + uint32_t count = 0; + pKmdSysManager->mockPowerFailure[KmdSysman::Requests::Power::NumPowerDomains] = 1; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, 0u); +} + +TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainWithUnexpectedValueFromKmdForDomainsSupportedThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { + init(true); + + uint32_t count = 0; + pKmdSysManager->mockPowerFailure[KmdSysman::Requests::Power::NumPowerDomains] = 3; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, 0u); +} + TEST_F(SysmanDevicePowerFixture, GivenPowerDomainsAreEnumeratedWhenCallingIsPowerInitCompletedThenVerifyPowerInitializationIsCompleted) { init(true); @@ -93,7 +120,7 @@ TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDoma } } -TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesThenErrorIsReturned) { +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesAndExtPropertiesThenCallSucceeds) { // Setting allow set calls or not init(true); @@ -111,7 +138,68 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerProperties ze_result_t result = zesPowerGetProperties(handle, &properties); - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_FALSE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0u); + EXPECT_TRUE(properties.canControl); + EXPECT_TRUE(properties.isEnergyThresholdSupported); + EXPECT_EQ(static_cast(properties.maxLimit), pKmdSysManager->mockMaxPowerLimit); + EXPECT_EQ(static_cast(properties.minLimit), pKmdSysManager->mockMinPowerLimit); + EXPECT_EQ(static_cast(properties.defaultLimit), pKmdSysManager->mockTpdDefault); + EXPECT_TRUE(defaultLimit.limitValueLocked); + EXPECT_TRUE(defaultLimit.enabledStateLocked); + EXPECT_EQ(ZES_POWER_SOURCE_ANY, defaultLimit.source); + EXPECT_EQ(ZES_LIMIT_UNIT_POWER, defaultLimit.limitUnit); + EXPECT_EQ(defaultLimit.limit, static_cast(pKmdSysManager->mockTpdDefault)); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesAndExtPropertiesWithUnsetDefaultLimitThenCallSucceeds) { + // Setting allow set calls or not + init(true); + + auto handles = getPowerHandles(powerHandleComponentCount); + + for (auto handle : handles) { + + zes_power_properties_t properties = {}; + zes_power_ext_properties_t extProperties = {}; + + extProperties.stype = ZES_STRUCTURE_TYPE_POWER_EXT_PROPERTIES; + properties.pNext = &extProperties; + + ze_result_t result = zesPowerGetProperties(handle, &properties); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_FALSE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0u); + EXPECT_TRUE(properties.canControl); + EXPECT_TRUE(properties.isEnergyThresholdSupported); + EXPECT_EQ(static_cast(properties.maxLimit), pKmdSysManager->mockMaxPowerLimit); + EXPECT_EQ(static_cast(properties.minLimit), pKmdSysManager->mockMinPowerLimit); + EXPECT_EQ(static_cast(properties.defaultLimit), pKmdSysManager->mockTpdDefault); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesAndDefaultPowerIsNotAvailableThenCallSucceedsAndDefaultLimitIsInvalid) { + // Setting allow set calls or not + init(true); + + auto handles = getPowerHandles(powerHandleComponentCount); + + for (auto handle : handles) { + zes_power_properties_t properties = {}; + zes_power_ext_properties_t extProperties = {}; + zes_power_limit_ext_desc_t defaultLimit = {}; + + extProperties.defaultLimit = &defaultLimit; + extProperties.stype = ZES_STRUCTURE_TYPE_POWER_EXT_PROPERTIES; + properties.pNext = &extProperties; + + pKmdSysManager->mockPowerFailure[KmdSysman::Requests::Power::TdpDefault] = 1; + ze_result_t result = zesPowerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(defaultLimit.limit, -1); } } @@ -375,15 +463,15 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenCallingGetAnsSetPowerL pKmdSysManager->mockRequestMultiple = false; pKmdSysManager->requestMultipleSizeDiff = false; - pKmdSysManager->mockPowerLimit2EnabledFailure = true; + pKmdSysManager->mockPowerLimit2Enabled = 0; count = mockLimitCount; EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetLimitsExt(handle, &count, allLimits.data())); - pKmdSysManager->mockPowerLimit2EnabledFailure = false; + pKmdSysManager->mockPowerLimit2Enabled = 1; - pKmdSysManager->mockPowerLimit1EnabledFailure = true; + pKmdSysManager->mockPowerLimit1Enabled = 0; count = mockLimitCount; EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetLimitsExt(handle, &count, allLimits.data())); - pKmdSysManager->mockPowerLimit1EnabledFailure = false; + pKmdSysManager->mockPowerLimit1Enabled = 1; allLimits[0].level = ZES_POWER_LEVEL_UNKNOWN; count = mockLimitCount; diff --git a/level_zero/tools/test/black_box_tests/zello_sysman.cpp b/level_zero/tools/test/black_box_tests/zello_sysman.cpp index 62a36cd001..1419efc4f5 100644 --- a/level_zero/tools/test/black_box_tests/zello_sysman.cpp +++ b/level_zero/tools/test/black_box_tests/zello_sysman.cpp @@ -281,6 +281,20 @@ int geteuid() { } } #endif // defined(_WIN32) || defined(_WIN64) +static std::string getPowerDomainType(zes_power_domain_t type) { + static const std::map powerDomainEnumToStringMap{ + {ZES_POWER_DOMAIN_CARD, "ZES_POWER_DOMAIN_CARD"}, + {ZES_POWER_DOMAIN_PACKAGE, "ZES_POWER_DOMAIN_PACKAGE"}, + {ZES_POWER_DOMAIN_STACK, "ZES_POWER_DOMAIN_STACK"}, + {ZES_POWER_DOMAIN_MEMORY, "ZES_POWER_DOMAIN_MEMORY"}, + {ZES_POWER_DOMAIN_GPU, "ZES_POWER_DOMAIN_GPU"}}; + if (powerDomainEnumToStringMap.find(type) != powerDomainEnumToStringMap.end()) { + return powerDomainEnumToStringMap.at(type); + } else { + return "invalid"; + } +} + void testSysmanPower(ze_device_handle_t &device, std::vector &buf, uint32_t &curDeviceIndex) { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::cout << std::endl @@ -297,15 +311,23 @@ void testSysmanPower(ze_device_handle_t &device, std::vector &buf, for (const auto &handle : handles) { zes_power_properties_t properties = {}; + zes_power_ext_properties_t extProperties = {}; + zes_power_limit_ext_desc_t defaultLimit = {}; + + extProperties.defaultLimit = &defaultLimit; + extProperties.stype = ZES_STRUCTURE_TYPE_POWER_EXT_PROPERTIES; + properties.pNext = &extProperties; VALIDATECALL(zesPowerGetProperties(handle, &properties)); if (verbose) { std::cout << "properties.onSubdevice = " << static_cast(properties.onSubdevice) << std::endl; std::cout << "properties.subdeviceId = " << properties.subdeviceId << std::endl; std::cout << "properties.canControl = " << static_cast(properties.canControl) << std::endl; - std::cout << "properties.isEnergyThresholdSupported= " << static_cast(properties.isEnergyThresholdSupported) << std::endl; - std::cout << "properties.defaultLimit= " << properties.defaultLimit << std::endl; - std::cout << "properties.maxLimit =" << properties.maxLimit << std::endl; - std::cout << "properties.minLimit =" << properties.minLimit << std::endl; + std::cout << "properties.isEnergyThresholdSupported = " << static_cast(properties.isEnergyThresholdSupported) << std::endl; + std::cout << "properties.defaultLimit = " << properties.defaultLimit << std::endl; + std::cout << "properties.maxLimit = " << properties.maxLimit << std::endl; + std::cout << "properties.minLimit = " << properties.minLimit << std::endl; + std::cout << "extProperties.domain = " << getPowerDomainType(extProperties.domain) << std::endl; + std::cout << "defaultLimit.limit = " << defaultLimit.limit << std::endl; } int count = 5; // Measure average power 5 times for (; count > 0; count--) {