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 060abd0551..9c5b43b174 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 @@ -7,6 +7,7 @@ #include "level_zero/sysman/source/api/power/windows/sysman_os_power_imp.h" +#include "level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper.h" #include "level_zero/sysman/source/shared/windows/sysman_kmd_sys_manager.h" #include "level_zero/sysman/source/shared/windows/zes_os_sysman_imp.h" #include "level_zero/sysman/source/sysman_const.h" @@ -14,114 +15,25 @@ 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; - - std::vector vRequests = {}; - std::vector vResponses = {}; - KmdSysman::RequestProperty request = {}; - - 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); - - request.requestId = KmdSysman::Requests::Power::TdpDefault; - vRequests.push_back(request); - - request.requestId = KmdSysman::Requests::Power::MinPowerLimitDefault; - vRequests.push_back(request); - - request.requestId = KmdSysman::Requests::Power::MaxPowerLimitDefault; - vRequests.push_back(request); - - ze_result_t status = pKmdSysManager->requestMultiple(vRequests, vResponses); - - if ((status != ZE_RESULT_SUCCESS) || (vResponses.size() != vRequests.size())) { - return status; - } - - if (vResponses[0].returnCode == KmdSysman::Success) { - memcpy_s(&pProperties->canControl, sizeof(ze_bool_t), vResponses[0].dataBuffer, sizeof(ze_bool_t)); - memcpy_s(&pProperties->isEnergyThresholdSupported, sizeof(ze_bool_t), vResponses[0].dataBuffer, sizeof(ze_bool_t)); - } - - pProperties->defaultLimit = -1; - if (vResponses[1].returnCode == KmdSysman::Success) { - memcpy_s(&pProperties->defaultLimit, sizeof(uint32_t), vResponses[1].dataBuffer, sizeof(uint32_t)); - } - - pProperties->minLimit = -1; - if (vResponses[2].returnCode == KmdSysman::Success) { - memcpy_s(&pProperties->minLimit, sizeof(uint32_t), vResponses[2].dataBuffer, sizeof(uint32_t)); - } - - pProperties->maxLimit = -1; - if (vResponses[3].returnCode == KmdSysman::Success) { - memcpy_s(&pProperties->maxLimit, sizeof(uint32_t), vResponses[3].dataBuffer, sizeof(uint32_t)); - } - - return ZE_RESULT_SUCCESS; + auto pSysmanProductHelper = pWddmSysmanImp->getSysmanProductHelper(); + return pSysmanProductHelper->getPowerProperties(pProperties, this->powerDomain, pWddmSysmanImp); } ze_result_t WddmPowerImp::getPropertiesExt(zes_power_ext_properties_t *pExtPoperties) { - 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; + auto pSysmanProductHelper = pWddmSysmanImp->getSysmanProductHelper(); + return pSysmanProductHelper->getPowerPropertiesExt(pExtPoperties, this->powerDomain, pWddmSysmanImp); } ze_result_t WddmPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy) { - uint64_t energyCounter64Bit = 0; - 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::CurrentEnergyCounter64Bit; - - ze_result_t status = pKmdSysManager->requestSingle(request, response); - - if (status == ZE_RESULT_SUCCESS) { - memcpy_s(&energyCounter64Bit, sizeof(uint64_t), response.dataBuffer, sizeof(uint64_t)); - pEnergy->energy = energyCounter64Bit; - pEnergy->timestamp = SysmanDevice::getSysmanTimestamp(); - } - - return status; + auto pSysmanProductHelper = pWddmSysmanImp->getSysmanProductHelper(); + return pSysmanProductHelper->getPowerEnergyCounter(pEnergy, this->powerDomain, pWddmSysmanImp); } ze_result_t WddmPowerImp::getLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) { + if (supportsEnergyCounterOnly) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } ze_result_t status = ZE_RESULT_SUCCESS; KmdSysman::RequestProperty request; KmdSysman::ResponseProperty response; @@ -216,6 +128,9 @@ ze_result_t WddmPowerImp::getLimits(zes_power_sustained_limit_t *pSustained, zes } ze_result_t WddmPowerImp::setLimits(const zes_power_sustained_limit_t *pSustained, const zes_power_burst_limit_t *pBurst, const zes_power_peak_limit_t *pPeak) { + if (supportsEnergyCounterOnly) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } ze_result_t status = ZE_RESULT_SUCCESS; KmdSysman::RequestProperty request; KmdSysman::ResponseProperty response; @@ -281,6 +196,9 @@ ze_result_t WddmPowerImp::setLimits(const zes_power_sustained_limit_t *pSustaine } ze_result_t WddmPowerImp::getEnergyThreshold(zes_energy_threshold_t *pThreshold) { + if (supportsEnergyCounterOnly) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } KmdSysman::RequestProperty request; KmdSysman::ResponseProperty response; @@ -308,6 +226,9 @@ ze_result_t WddmPowerImp::getEnergyThreshold(zes_energy_threshold_t *pThreshold) } ze_result_t WddmPowerImp::setEnergyThreshold(double threshold) { + if (supportsEnergyCounterOnly) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } KmdSysman::RequestProperty request; KmdSysman::ResponseProperty response; @@ -324,6 +245,9 @@ ze_result_t WddmPowerImp::setEnergyThreshold(double threshold) { } bool WddmPowerImp::isPowerModuleSupported() { + if (supportsEnergyCounterOnly) { + return true; + } powerLimitCount = 0; std::vector vRequests(3); std::vector vResponses = {}; @@ -375,6 +299,9 @@ bool WddmPowerImp::isPowerModuleSupported() { } ze_result_t WddmPowerImp::getLimitsExt(uint32_t *pCount, zes_power_limit_ext_desc_t *pSustained) { + if (supportsEnergyCounterOnly) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } ze_result_t result = ZE_RESULT_SUCCESS; uint8_t count = 0; @@ -522,6 +449,9 @@ ze_result_t WddmPowerImp::getLimitsExt(uint32_t *pCount, zes_power_limit_ext_des } ze_result_t WddmPowerImp::setLimitsExt(uint32_t *pCount, zes_power_limit_ext_desc_t *pSustained) { + if (supportsEnergyCounterOnly) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } ze_result_t status = ZE_RESULT_SUCCESS; KmdSysman::RequestProperty request; KmdSysman::ResponseProperty response; @@ -576,49 +506,27 @@ ze_result_t WddmPowerImp::setLimitsExt(uint32_t *pCount, zes_power_limit_ext_des return status; } +void WddmPowerImp::isPowerHandleEnergyCounterOnly() { + switch (this->powerDomain) { + case ZES_POWER_DOMAIN_MEMORY: + case ZES_POWER_DOMAIN_GPU: + supportsEnergyCounterOnly = true; + break; + default: + break; + } +} + WddmPowerImp::WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain) : powerDomain(powerDomain) { - WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); + pWddmSysmanImp = static_cast(pOsSysman); pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); + isPowerHandleEnergyCounterOnly(); } 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; + auto pSysmanProductHelper = pWddmSysmanImp->getSysmanProductHelper(); + return pSysmanProductHelper->getNumberOfPowerDomainsSupported(pWddmSysmanImp); } OsPower *OsPower::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain) { 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 e34807de2c..a9608e15f4 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 @@ -13,6 +13,7 @@ namespace L0 { namespace Sysman { class KmdSysManager; +class WddmSysmanImp; class WddmPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { public: ze_result_t getProperties(zes_power_properties_t *pProperties) override; @@ -26,14 +27,17 @@ class WddmPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { ze_result_t getPropertiesExt(zes_power_ext_properties_t *pExtPoperties) override; bool isPowerModuleSupported() override; + void isPowerHandleEnergyCounterOnly(); WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_power_domain_t powerDomain); WddmPowerImp() = default; ~WddmPowerImp() override = default; protected: KmdSysManager *pKmdSysManager = nullptr; + WddmSysmanImp *pWddmSysmanImp = nullptr; uint32_t powerLimitCount = 0; zes_power_domain_t powerDomain = ZES_POWER_DOMAIN_CARD; + bool supportsEnergyCounterOnly = false; }; } // namespace Sysman diff --git a/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper.h b/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper.h index e1bfd7c534..e48d600d09 100644 --- a/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper.h +++ b/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper.h @@ -27,6 +27,10 @@ class SysmanProductHelper; using SysmanProductHelperCreateFunctionType = std::unique_ptr (*)(); extern SysmanProductHelperCreateFunctionType sysmanProductHelperFactory[IGFX_MAX_PRODUCT]; +static const std::map powerGroupToDomainTypeMap = { + {ZES_POWER_DOMAIN_CARD, KmdSysman::PowerDomainsType::powerDomainCard}, + {ZES_POWER_DOMAIN_PACKAGE, KmdSysman::PowerDomainsType::powerDomainPackage}, +}; class SysmanProductHelper { public: @@ -51,6 +55,12 @@ class SysmanProductHelper { // Memory virtual ze_result_t getMemoryBandWidth(zes_mem_bandwidth_t *pBandwidth, WddmSysmanImp *pWddmSysmanImp) = 0; + // Power + virtual std::vector getNumberOfPowerDomainsSupported(WddmSysmanImp *pWddmSysmanImp) = 0; + virtual ze_result_t getPowerProperties(zes_power_properties_t *pProperties, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) = 0; + virtual ze_result_t getPowerPropertiesExt(zes_power_ext_properties_t *pExtPoperties, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) = 0; + virtual ze_result_t getPowerEnergyCounter(zes_power_energy_counter_t *pEnergy, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) = 0; + // Pmt virtual std::map> *getGuidToKeyOffsetMap() = 0; diff --git a/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper_hw.h b/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper_hw.h index 93a8804dfd..10b0282984 100644 --- a/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper_hw.h +++ b/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper_hw.h @@ -35,6 +35,12 @@ class SysmanProductHelperHw : public SysmanProductHelper { // Memory ze_result_t getMemoryBandWidth(zes_mem_bandwidth_t *pBandwidth, WddmSysmanImp *pWddmSysmanImp) override; + // Power + std::vector getNumberOfPowerDomainsSupported(WddmSysmanImp *pWddmSysmanImp) override; + ze_result_t getPowerProperties(zes_power_properties_t *pProperties, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) override; + ze_result_t getPowerPropertiesExt(zes_power_ext_properties_t *pExtPoperties, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) override; + ze_result_t getPowerEnergyCounter(zes_power_energy_counter_t *pEnergy, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) override; + // Pmt std::map> *getGuidToKeyOffsetMap() override; diff --git a/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper_hw.inl b/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper_hw.inl index 715e9abde4..3de03d0a06 100644 --- a/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper_hw.inl +++ b/level_zero/sysman/source/shared/windows/product_helper/sysman_product_helper_hw.inl @@ -150,6 +150,152 @@ ze_result_t SysmanProductHelperHw::getMemoryBandWidth(zes_mem_bandwi return ZE_RESULT_SUCCESS; } +template +std::vector SysmanProductHelperHw::getNumberOfPowerDomainsSupported(WddmSysmanImp *pWddmSysmanImp) { + 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; +} + +template +ze_result_t SysmanProductHelperHw::getPowerProperties(zes_power_properties_t *pProperties, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) { + KmdSysManager *pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); + pProperties->onSubdevice = false; + pProperties->subdeviceId = 0; + + std::vector vRequests = {}; + std::vector vResponses = {}; + KmdSysman::RequestProperty request = {}; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(powerDomain)); + request.requestId = KmdSysman::Requests::Power::EnergyThresholdSupported; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Power::TdpDefault; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Power::MinPowerLimitDefault; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Power::MaxPowerLimitDefault; + vRequests.push_back(request); + + ze_result_t status = pKmdSysManager->requestMultiple(vRequests, vResponses); + + if ((status != ZE_RESULT_SUCCESS) || (vResponses.size() != vRequests.size())) { + return status; + } + + if (vResponses[0].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->canControl, sizeof(ze_bool_t), vResponses[0].dataBuffer, sizeof(ze_bool_t)); + memcpy_s(&pProperties->isEnergyThresholdSupported, sizeof(ze_bool_t), vResponses[0].dataBuffer, sizeof(ze_bool_t)); + } + + pProperties->defaultLimit = -1; + if (vResponses[1].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->defaultLimit, sizeof(uint32_t), vResponses[1].dataBuffer, sizeof(uint32_t)); + } + + pProperties->minLimit = -1; + if (vResponses[2].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->minLimit, sizeof(uint32_t), vResponses[2].dataBuffer, sizeof(uint32_t)); + } + + pProperties->maxLimit = -1; + if (vResponses[3].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->maxLimit, sizeof(uint32_t), vResponses[3].dataBuffer, sizeof(uint32_t)); + } + + return ZE_RESULT_SUCCESS; +} + +template +ze_result_t SysmanProductHelperHw::getPowerPropertiesExt(zes_power_ext_properties_t *pExtPoperties, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) { + KmdSysManager *pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); + 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(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; +} + +template +ze_result_t SysmanProductHelperHw::getPowerEnergyCounter(zes_power_energy_counter_t *pEnergy, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) { + KmdSysManager *pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); + uint64_t energyCounter64Bit = 0; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(powerDomain)); + request.requestId = KmdSysman::Requests::Power::CurrentEnergyCounter64Bit; + + ze_result_t status = pKmdSysManager->requestSingle(request, response); + + if (status == ZE_RESULT_SUCCESS) { + memcpy_s(&energyCounter64Bit, sizeof(uint64_t), response.dataBuffer, sizeof(uint64_t)); + pEnergy->energy = energyCounter64Bit; + pEnergy->timestamp = SysmanDevice::getSysmanTimestamp(); + } + + return status; +} + template std::map> *SysmanProductHelperHw::getGuidToKeyOffsetMap() { return nullptr; diff --git a/level_zero/sysman/source/shared/windows/product_helper/xe2_hpg_core/bmg/sysman_product_helper_bmg.cpp b/level_zero/sysman/source/shared/windows/product_helper/xe2_hpg_core/bmg/sysman_product_helper_bmg.cpp index 86659a4bbb..9ba4c0610f 100644 --- a/level_zero/sysman/source/shared/windows/product_helper/xe2_hpg_core/bmg/sysman_product_helper_bmg.cpp +++ b/level_zero/sysman/source/shared/windows/product_helper/xe2_hpg_core/bmg/sysman_product_helper_bmg.cpp @@ -20,11 +20,20 @@ namespace Sysman { constexpr static auto gfxProduct = IGFX_BMG; +// XTAL clock frequency is denoted as an integer between [0-3] with a predefined value for each number. This vector defines the predefined value for each integer represented by the index of the vector. +static const std::vector indexToXtalClockFrequecyMap = {24, 19.2, 38.4, 25}; + static std::map> guidToKeyOffsetMap = { {0x1e2f8200, // BMG PUNIT rev 1 - {{"VRAM_BANDWIDTH", 14}}}, + {{"XTAL_CLK_FREQUENCY", 1}, + {"VRAM_BANDWIDTH", 14}, + {"XTAL_COUNT", 128}, + {"VCCGT_ENERGY_ACCUMULATOR", 407}, + {"VCCDDR_ENERGY_ACCUMULATOR", 410}}}, {0x5e2f8210, // BMG OOBMSM rev 15 - {{"SOC_THERMAL_SENSORS_TEMPERATURE_0_2_0_GTTMMADR[1]", 41}, + {{"PACKAGE_ENERGY_STATUS_SKU", 34}, + {"PLATFORM_ENERGY_STATUS", 35}, + {"SOC_THERMAL_SENSORS_TEMPERATURE_0_2_0_GTTMMADR[1]", 41}, {"VRAM_TEMPERATURE_0_2_0_GTTMMADR", 42}, {"rx_byte_count_lsb", 70}, {"rx_byte_count_msb", 69}, @@ -838,6 +847,228 @@ ze_result_t SysmanProductHelperHw::getMemoryBandWidth(zes_mem_bandwi return status; } +template <> +std::vector SysmanProductHelperHw::getNumberOfPowerDomainsSupported(WddmSysmanImp *pWddmSysmanImp) { + 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; + } + + PlatformMonitoringTech *pPmt = pWddmSysmanImp->getSysmanPmt(); + if (pPmt != nullptr) { + powerDomains.push_back(ZES_POWER_DOMAIN_MEMORY); + powerDomains.push_back(ZES_POWER_DOMAIN_GPU); + } + return powerDomains; +} + +template <> +ze_result_t SysmanProductHelperHw::getPowerProperties(zes_power_properties_t *pProperties, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) { + if (powerDomain == ZES_POWER_DOMAIN_CARD || powerDomain == ZES_POWER_DOMAIN_PACKAGE) { + KmdSysManager *pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); + pProperties->onSubdevice = false; + pProperties->subdeviceId = 0; + + std::vector vRequests = {}; + std::vector vResponses = {}; + KmdSysman::RequestProperty request = {}; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.paramInfo = static_cast(powerGroupToDomainTypeMap.at(powerDomain)); + request.requestId = KmdSysman::Requests::Power::EnergyThresholdSupported; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Power::TdpDefault; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Power::MinPowerLimitDefault; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Power::MaxPowerLimitDefault; + vRequests.push_back(request); + + ze_result_t status = pKmdSysManager->requestMultiple(vRequests, vResponses); + + if ((status != ZE_RESULT_SUCCESS) || (vResponses.size() != vRequests.size())) { + return status; + } + + if (vResponses[0].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->canControl, sizeof(ze_bool_t), vResponses[0].dataBuffer, sizeof(ze_bool_t)); + memcpy_s(&pProperties->isEnergyThresholdSupported, sizeof(ze_bool_t), vResponses[0].dataBuffer, sizeof(ze_bool_t)); + } + + pProperties->defaultLimit = -1; + if (vResponses[1].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->defaultLimit, sizeof(uint32_t), vResponses[1].dataBuffer, sizeof(uint32_t)); + } + + pProperties->minLimit = -1; + if (vResponses[2].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->minLimit, sizeof(uint32_t), vResponses[2].dataBuffer, sizeof(uint32_t)); + } + + pProperties->maxLimit = -1; + if (vResponses[3].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->maxLimit, sizeof(uint32_t), vResponses[3].dataBuffer, sizeof(uint32_t)); + } + return ZE_RESULT_SUCCESS; + } else if (powerDomain == ZES_POWER_DOMAIN_MEMORY || powerDomain == ZES_POWER_DOMAIN_GPU) { + PlatformMonitoringTech *pPmt = pWddmSysmanImp->getSysmanPmt(); + if (pPmt == nullptr) { + return ZE_RESULT_ERROR_UNKNOWN; + } + pProperties->onSubdevice = false; + pProperties->subdeviceId = 0; + pProperties->canControl = false; + pProperties->isEnergyThresholdSupported = false; + pProperties->defaultLimit = -1; + pProperties->minLimit = -1; + pProperties->maxLimit = -1; + return ZE_RESULT_SUCCESS; + } else { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } +} + +template <> +ze_result_t SysmanProductHelperHw::getPowerPropertiesExt(zes_power_ext_properties_t *pExtPoperties, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) { + if (powerDomain == ZES_POWER_DOMAIN_CARD || powerDomain == ZES_POWER_DOMAIN_PACKAGE) { + KmdSysManager *pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); + 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(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; + } else if (powerDomain == ZES_POWER_DOMAIN_MEMORY || powerDomain == ZES_POWER_DOMAIN_GPU) { + pExtPoperties->domain = powerDomain; + if (pExtPoperties->defaultLimit) { + pExtPoperties->defaultLimit->limit = -1; + 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; + } else { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } +} + +template <> +ze_result_t SysmanProductHelperHw::getPowerEnergyCounter(zes_power_energy_counter_t *pEnergy, zes_power_domain_t powerDomain, WddmSysmanImp *pWddmSysmanImp) { + ze_result_t status = ZE_RESULT_SUCCESS; + uint32_t energyCounter = 0; + std::string key; + + PlatformMonitoringTech *pPmt = pWddmSysmanImp->getSysmanPmt(); + if (pPmt == nullptr) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + switch (powerDomain) { + case ZES_POWER_DOMAIN_PACKAGE: + key = "PACKAGE_ENERGY_STATUS_SKU"; + break; + case ZES_POWER_DOMAIN_CARD: + key = "PLATFORM_ENERGY_STATUS"; + break; + case ZES_POWER_DOMAIN_MEMORY: + key = "VCCDDR_ENERGY_ACCUMULATOR"; + break; + case ZES_POWER_DOMAIN_GPU: + key = "VCCGT_ENERGY_ACCUMULATOR"; + break; + default: + DEBUG_BREAK_IF(true); + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + break; + } + + status = pPmt->readValue(key, energyCounter); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + // Energy counter is in U(18.14) format. Need to convert it into uint64_t + uint32_t integerPart = static_cast(energyCounter >> 14); + + uint32_t decimalBits = static_cast((energyCounter & 0x3FFF)); + double decimalPart = static_cast(decimalBits) / (1 << 14); + + double result = static_cast(integerPart + decimalPart); + pEnergy->energy = static_cast((result * convertJouleToMicroJoule)); + + // timestamp calcuation + uint64_t timestamp64 = 0; + uint32_t frequency = 0; + + status = pPmt->readValue("XTAL_COUNT", timestamp64); + if (status != ZE_RESULT_SUCCESS) { + return status; + } + status = pPmt->readValue("XTAL_CLK_FREQUENCY", frequency); + if (status != ZE_RESULT_SUCCESS) { + return status; + } + double timestamp = timestamp64 / indexToXtalClockFrequecyMap[frequency & 0x2]; + pEnergy->timestamp = static_cast(timestamp); + return status; +} + template <> std::map> *SysmanProductHelperHw::getGuidToKeyOffsetMap() { return &guidToKeyOffsetMap; 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 62f0c75bf0..9e07fe5db5 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 @@ -7,6 +7,7 @@ #pragma once +#include "level_zero/sysman/source/shared/windows/pmt/sysman_pmt.h" #include "level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h" namespace L0 { @@ -225,6 +226,12 @@ struct PowerKmdSysManager : public MockKmdSysManager { } }; +class PublicPlatformMonitoringTech : public L0::Sysman::PlatformMonitoringTech { + public: + PublicPlatformMonitoringTech(std::vector deviceInterfaceList, SysmanProductHelper *pSysmanProductHelper) : PlatformMonitoringTech(deviceInterfaceList, pSysmanProductHelper) {} + using PlatformMonitoringTech::keyOffsetMap; +}; + } // namespace ult } // namespace Sysman } // namespace L0 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 ac7cfc7352..a936069d40 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 @@ -5,6 +5,8 @@ * */ +#include "shared/test/common/test_macros/hw_test.h" + #include "level_zero/sysman/test/unit_tests/sources/power/windows/mock_power.h" #include "level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h" @@ -79,7 +81,15 @@ TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDoma init(true); uint32_t count = 0; - pKmdSysManager->mockPowerFailure[KmdSysman::Requests::Power::NumPowerDomains] = 3; + pKmdSysManager->mockPowerFailure[KmdSysman::Requests::Power::NumPowerDomains] = 1; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, 0u); +} + +TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainWithUnexpectedResponseFromKmdThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { + init(true); + uint32_t count = 0; + pKmdSysManager->mockPowerDomainCount = 3; EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); EXPECT_EQ(count, 0u); } @@ -225,7 +235,37 @@ TEST_F(SysmanDevicePowerFixture, DISABLED_GivenValidPowerHandleWhenGettingPowerP } } -TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved) { +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerPropertiesAndExtPropertiesAndRequestMultipleFailesThenCallFails) { + // 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; + + // Mock failure of individual requests in the request multiple call + std::vector requestId = {KmdSysman::Requests::Power::EnergyThresholdSupported, KmdSysman::Requests::Power::TdpDefault, KmdSysman::Requests::Power::MinPowerLimitDefault, KmdSysman::Requests::Power::MaxPowerLimitDefault}; + for (auto it = requestId.begin(); it != requestId.end(); it++) { + pKmdSysManager->mockPowerFailure[*it] = 1; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetProperties(handle, &properties)); + pKmdSysManager->mockPowerFailure[*it] = 0; + } + + pKmdSysManager->mockRequestMultiple = true; + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, zesPowerGetProperties(handle, &properties)); + pKmdSysManager->requestMultipleSizeDiff = true; + pKmdSysManager->mockRequestMultipleResult = ZE_RESULT_SUCCESS; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesPowerGetProperties(handle, &properties)); + pKmdSysManager->mockRequestMultiple = false; + pKmdSysManager->requestMultipleSizeDiff = false; + pKmdSysManager->mockRequestMultipleResult = ZE_RESULT_ERROR_NOT_AVAILABLE; + } +} + +HWTEST2_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved, IsAtMostDg2) { // Setting allow set calls or not init(true); @@ -242,6 +282,19 @@ TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCoun } } +HWTEST2_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterAndKmdCallFailsThenCallFails, IsAtMostDg2) { + // Setting allow set calls or not + init(true); + + auto handles = getPowerHandles(powerHandleComponentCount); + for (auto handle : handles) { + pKmdSysManager->mockPowerFailure[KmdSysman::Requests::Power::CurrentEnergyCounter64Bit] = 1; + zes_power_energy_counter_t energyCounter; + ze_result_t result = zesPowerGetEnergyCounter(handle, &energyCounter); + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result); + } +} + TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerLimitsAllowSetToFalseThenCallSucceedsWithValidPowerReadingsRetrieved) { // Setting allow set calls or not init(false); diff --git a/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/CMakeLists.txt index 5a0f597ade..b56c738d8d 100644 --- a/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/CMakeLists.txt +++ b/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/CMakeLists.txt @@ -10,6 +10,7 @@ if(WIN32) ${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_temperature_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_memory_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sysman_product_helper_power_tests.cpp ) endif() add_subdirectories() \ No newline at end of file diff --git a/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/sysman_product_helper_power_tests.cpp b/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/sysman_product_helper_power_tests.cpp new file mode 100644 index 0000000000..6078f45100 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/sysman_product_helper_power_tests.cpp @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2024 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/common/helpers/variable_backup.h" +#include "shared/test/common/os_interface/windows/mock_sys_calls.h" +#include "shared/test/common/test_macros/hw_test.h" + +#include "level_zero/sysman/source/api/power/windows/sysman_os_power_imp.h" +#include "level_zero/sysman/source/sysman_const.h" +#include "level_zero/sysman/test/unit_tests/sources/power/windows/mock_power.h" +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h" + +namespace L0 { +namespace Sysman { +namespace ult { + +const std::wstring pmtInterfaceName = L"TEST\0"; +std::vector pmtInterfacePower(pmtInterfaceName.begin(), pmtInterfaceName.end()); + +const std::map> dummyKeyOffsetMap = { + {{"XTAL_CLK_FREQUENCY", {1, 0}}, + {"XTAL_COUNT", {128, 0}}, + {"VCCGT_ENERGY_ACCUMULATOR", {407, 0}}, + {"VCCDDR_ENERGY_ACCUMULATOR", {410, 0}}, + {"PACKAGE_ENERGY_STATUS_SKU", {34, 1}}, + {"PLATFORM_ENERGY_STATUS", {35, 1}}}}; + +static const std::vector indexToXtalClockFrequecyMap = {24, 19.2, 38.4, 25}; +constexpr uint32_t powerHandleDomainCount = 4u; + +class SysmanProductHelperPowerTest : public SysmanDeviceFixture { + + protected: + std::unique_ptr pKmdSysManager; + L0::Sysman::KmdSysManager *pOriginalKmdSysManager = nullptr; + + void SetUp() override { + SysmanDeviceFixture::SetUp(); + } + + void init(bool allowSetCalls) { + pKmdSysManager.reset(new PowerKmdSysManager); + pKmdSysManager->allowSetCalls = allowSetCalls; + pOriginalKmdSysManager = pWddmSysmanImp->pKmdSysManager; + pWddmSysmanImp->pKmdSysManager = pKmdSysManager.get(); + + for (auto handle : pSysmanDeviceImp->pPowerHandleContext->handleList) { + delete handle; + } + + auto pPmt = new PublicPlatformMonitoringTech(pmtInterfacePower, pWddmSysmanImp->getSysmanProductHelper()); + pPmt->keyOffsetMap = dummyKeyOffsetMap; + pWddmSysmanImp->pPmt.reset(pPmt); + pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); + } + void TearDown() override { + pWddmSysmanImp->pKmdSysManager = pOriginalKmdSysManager; + SysmanDeviceFixture::TearDown(); + } + + std::vector getPowerHandles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +HWTEST2_F(SysmanProductHelperPowerTest, GivenComponentCountZeroWhenEnumeratingPowerDomainsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds, IsBMG) { + init(true); + uint32_t count = 0; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, powerHandleDomainCount); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenInvalidComponentCountWhenEnumeratingPowerDomainsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds, IsBMG) { + init(true); + uint32_t count = 0; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, powerHandleDomainCount); + + count = count + 1; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, powerHandleDomainCount); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved, IsBMG) { + static constexpr uint32_t mockPmtEnergyCounterVariableBackupValue = 100; + static constexpr uint32_t mockPmtTimestampVariableBackupValue = 10000000; + static constexpr uint32_t mockPmtFrequencyIndexVariableBackupValue = 2; + + VariableBackup psysCallsCreateFile(&NEO::SysCalls::sysCallsCreateFile, [](LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) -> HANDLE { + return reinterpret_cast(static_cast(0x7)); + }); + VariableBackup psysCallsDeviceIoControl(&NEO::SysCalls::sysCallsDeviceIoControl, [](HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) -> BOOL { + PmtSysman::PmtTelemetryRead *readRequest = static_cast(lpInBuffer); + switch (readRequest->offset) { + case 1: + *lpBytesReturned = 4; + *static_cast(lpOutBuffer) = mockPmtFrequencyIndexVariableBackupValue; + return true; + case 128: + *lpBytesReturned = 8; + *static_cast(lpOutBuffer) = mockPmtTimestampVariableBackupValue; + return true; + default: + *lpBytesReturned = 4; + *static_cast(lpOutBuffer) = mockPmtEnergyCounterVariableBackupValue; + return true; + } + }); + // Setting allow set calls or not + init(true); + + // Calculate the expected energy counter value from the mockPmtEnergyCounterVariableBackupValue + uint32_t integerPart = static_cast(mockPmtEnergyCounterVariableBackupValue >> 14); + uint32_t decimalBits = static_cast((mockPmtEnergyCounterVariableBackupValue & 0x3FFF)); + double decimalPart = static_cast(decimalBits) / (1 << 14); + double result = static_cast(integerPart + decimalPart); + uint64_t expectedEnergyCounterValue = static_cast((result * convertJouleToMicroJoule)); + + auto handles = getPowerHandles(powerHandleDomainCount); + for (auto handle : handles) { + zes_power_energy_counter_t energyCounter; + + ze_result_t result = zesPowerGetEnergyCounter(handle, &energyCounter); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(energyCounter.energy, expectedEnergyCounterValue); + EXPECT_EQ(energyCounter.timestamp, static_cast(mockPmtTimestampVariableBackupValue / indexToXtalClockFrequecyMap[mockPmtFrequencyIndexVariableBackupValue])); + } +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenInValidPowerDomainWhenGettingPowerEnergyCounterThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_UNKNOWN); + zes_power_energy_counter_t energyCounter = {}; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->getEnergyCounter(&energyCounter)); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPmtHandleWhenCallingZesPowerGetEnergyCounterAndIoctlFailsThenCallsFails, IsBMG) { + static uint32_t count = 3; + VariableBackup psysCallsCreateFile(&NEO::SysCalls::sysCallsCreateFile, [](LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) -> HANDLE { + return reinterpret_cast(static_cast(0x7)); + }); + VariableBackup psysCallsDeviceIoControl(&NEO::SysCalls::sysCallsDeviceIoControl, [](HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) -> BOOL { + PmtSysman::PmtTelemetryRead *readRequest = static_cast(lpInBuffer); + switch (readRequest->offset) { + case 1: + *lpBytesReturned = 4; + return (count == 3) ? false : true; + case 128: + *lpBytesReturned = 8; + return (count == 2) ? false : true; + default: + *lpBytesReturned = 4; + return (count == 1) ? false : true; + } + }); + + init(true); + auto handles = getPowerHandles(powerHandleDomainCount); + while (count) { + zes_power_energy_counter_t energyCounter; + ze_result_t result = zesPowerGetEnergyCounter(handles[0], &energyCounter); + EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, result); + count--; + } +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenNullPmtHandleWhenCallingZesPowerGetEnergyCounterThenCallFails, IsBMG) { + init(true); + auto handles = getPowerHandles(powerHandleDomainCount); + pWddmSysmanImp->pPmt.reset(nullptr); + zes_power_energy_counter_t energyCounter; + ze_result_t result = zesPowerGetEnergyCounter(handles[0], &energyCounter); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleWhenGettingPowerPropertiesAndExtPropertiesThenCallSucceeds, IsBMG) { + // Setting allow set calls or not + init(true); + auto handles = getPowerHandles(powerHandleDomainCount); + 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; + + ze_result_t result = zesPowerGetProperties(handle, &properties); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_FALSE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0u); + EXPECT_TRUE(defaultLimit.limitValueLocked); + EXPECT_TRUE(defaultLimit.enabledStateLocked); + EXPECT_EQ(ZES_POWER_SOURCE_ANY, defaultLimit.source); + EXPECT_EQ(ZES_LIMIT_UNIT_POWER, defaultLimit.limitUnit); + + if (extProperties.domain == ZES_POWER_DOMAIN_CARD || extProperties.domain == ZES_POWER_DOMAIN_PACKAGE) { + 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_EQ(defaultLimit.limit, static_cast(pKmdSysManager->mockTpdDefault)); + } else if (extProperties.domain == ZES_POWER_DOMAIN_GPU || extProperties.domain == ZES_POWER_DOMAIN_MEMORY) { + EXPECT_FALSE(properties.canControl); + EXPECT_FALSE(properties.isEnergyThresholdSupported); + EXPECT_EQ(properties.maxLimit, -1); + EXPECT_EQ(properties.minLimit, -1); + EXPECT_EQ(properties.defaultLimit, -1); + EXPECT_EQ(defaultLimit.limit, -1); + } + } +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenValidPowerHandleWhenGettingPowerPropertiesAndExtPropertiesWithUnsetDefaultLimitThenCallSucceeds, IsBMG) { + // Setting allow set calls or not + init(true); + + auto handles = getPowerHandles(powerHandleDomainCount); + + 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_EQ(properties.subdeviceId, 0u); + EXPECT_FALSE(properties.onSubdevice); + + if (extProperties.domain == ZES_POWER_DOMAIN_CARD || extProperties.domain == ZES_POWER_DOMAIN_PACKAGE) { + 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); + } else if (extProperties.domain == ZES_POWER_DOMAIN_GPU || extProperties.domain == ZES_POWER_DOMAIN_MEMORY) { + EXPECT_FALSE(properties.canControl); + EXPECT_FALSE(properties.isEnergyThresholdSupported); + EXPECT_EQ(properties.maxLimit, -1); + EXPECT_EQ(properties.minLimit, -1); + EXPECT_EQ(properties.defaultLimit, -1); + } + } +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenValidEnergyCounterOnlyPowerDomainWhenGettingPowerGetPropertiesAndPmtIsNullThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + pWddmSysmanImp->pPmt.reset(nullptr); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_MEMORY); + zes_power_properties_t powerProperties = {}; + ASSERT_EQ(ZE_RESULT_ERROR_UNKNOWN, pWddmPowerImp->getProperties(&powerProperties)); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenInValidPowerDomainWhenGettingPowerGetPropertiesThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_UNKNOWN); + zes_power_properties_t powerProperties = {}; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->getProperties(&powerProperties)); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenInValidPowerDomainWhenGettingPowerGetPropertiesExtThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_UNKNOWN); + zes_power_ext_properties_t powerProperties = {}; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->getPropertiesExt(&powerProperties)); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenEnergyCounterOnlyPowerDomainWhenGettingPowerLimtsThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_GPU); + zes_power_sustained_limit_t sustained; + zes_power_burst_limit_t burst; + zes_power_peak_limit_t peak; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->getLimits(&sustained, &burst, &peak)); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenEnergyCounterOnlyPowerDomainWhenCallingSetPowerLimtsThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_GPU); + zes_power_sustained_limit_t sustained; + zes_power_burst_limit_t burst; + zes_power_peak_limit_t peak; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->setLimits(&sustained, &burst, &peak)); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenEnergyCounterOnlyPowerDomainWhenCallingGetPowerExtLimtsThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_GPU); + uint32_t count = 0; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->getLimitsExt(&count, nullptr)); +} +HWTEST2_F(SysmanProductHelperPowerTest, GivenEnergyCounterOnlyPowerDomainWhenCallingSetPowerExtLimtsThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_GPU); + uint32_t count = 0; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->setLimitsExt(&count, nullptr)); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenEnergyCounterOnlyPowerDomainWhenCallingGetEnergyThresholdThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_GPU); + zes_energy_threshold_t energyThreshold; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->getEnergyThreshold(&energyThreshold)); +} + +HWTEST2_F(SysmanProductHelperPowerTest, GivenEnergyCounterOnlyPowerDomainWhenCallingSetEnergyThresholdThenUnsupportedIsReturned, IsBMG) { + // Setting allow set calls or not + init(true); + std::unique_ptr pWddmPowerImp = std::make_unique(pOsSysman, false, 0, ZES_POWER_DOMAIN_GPU); + double energyThreshold = 0; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmPowerImp->setEnergyThreshold(energyThreshold)); +} + +} // namespace ult +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/sysman_product_helper_temperature_tests.cpp b/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/sysman_product_helper_temperature_tests.cpp index 8e3241dbbe..290670ccc8 100644 --- a/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/sysman_product_helper_temperature_tests.cpp +++ b/level_zero/sysman/test/unit_tests/sources/shared/windows/product_helper/sysman_product_helper_temperature_tests.cpp @@ -54,7 +54,7 @@ class SysmanProductHelperTemperatureTest : public SysmanDeviceFixture { } }; -HWTEST2_F(SysmanProductHelperTemperatureTest, GivenComponentCountZeroWhenEnumeratingTemperatureSensorsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds, IsAtMostDg2) { +HWTEST2_F(SysmanProductHelperTemperatureTest, GivenComponentCountZeroWhenEnumeratingTemperatureSensorsThenValidCountIsReturnedAndVerifySysmanTemperatureGetCallSucceeds, IsAtMostDg2) { uint32_t count = 0; EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); EXPECT_EQ(count, temperatureHandleComponentCount); @@ -68,7 +68,7 @@ HWTEST2_F(SysmanProductHelperTemperatureTest, GivenTempDomainsAreEnumeratedWhenC EXPECT_EQ(true, pSysmanDeviceImp->pTempHandleContext->isTempInitDone()); } -HWTEST2_F(SysmanProductHelperTemperatureTest, GivenInvalidComponentCountWhenEnumeratingTemperatureSensorsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds, IsAtMostDg2) { +HWTEST2_F(SysmanProductHelperTemperatureTest, GivenInvalidComponentCountWhenEnumeratingTemperatureSensorsThenValidCountIsReturnedAndVerifySysmanTemperatureGetCallSucceeds, IsAtMostDg2) { uint32_t count = 0; EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); EXPECT_EQ(count, temperatureHandleComponentCount); @@ -78,7 +78,7 @@ HWTEST2_F(SysmanProductHelperTemperatureTest, GivenInvalidComponentCountWhenEnum EXPECT_EQ(count, temperatureHandleComponentCount); } -HWTEST2_F(SysmanProductHelperTemperatureTest, GivenComponentCountZeroWhenEnumeratingTemperatureSensorsThenValidPowerHandlesIsReturned, IsAtMostDg2) { +HWTEST2_F(SysmanProductHelperTemperatureTest, GivenComponentCountZeroWhenEnumeratingTemperatureSensorsThenValidTemperatureHandlesIsReturned, IsAtMostDg2) { uint32_t count = 0; EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); EXPECT_EQ(count, temperatureHandleComponentCount);