From d0fb5a6e512f52db54ab8071cf2e5afbeeb1b89e Mon Sep 17 00:00:00 2001 From: "Kulkarni, Ashwin Kumar" Date: Thu, 23 Mar 2023 07:33:11 +0000 Subject: [PATCH] Support Windows Sysman initialization Support for Initialization using zesInit Support Power module using new sysman initialization Related-To: LOCI-4134 Signed-off-by: Kulkarni, Ashwin Kumar --- .../source/power/windows/os_power_imp.cpp | 278 ++++++++- .../source/power/windows/os_power_imp.h | 3 + .../sysman/source/windows/CMakeLists.txt | 3 + .../source/windows/hw_device_id_windows.cpp | 2 +- level_zero/sysman/source/windows/kmd_sys.h | 580 ++++++++++++++++++ .../sysman/source/windows/kmd_sys_manager.cpp | 246 ++++++++ .../sysman/source/windows/kmd_sys_manager.h | 43 ++ .../sysman/source/windows/os_sysman_imp.cpp | 62 +- .../sysman/source/windows/os_sysman_imp.h | 24 + .../firmware_util/mock_fw_util_fixture.h | 1 + .../sources/power/windows/CMakeLists.txt | 14 + .../sources/power/windows/mock_power.h | 208 +++++++ .../power/windows/test_zes_sysman_power.cpp | 289 +++++++++ .../unit_tests/sources/windows/CMakeLists.txt | 18 + .../sources/windows/mock_kmd_sys_manager.h | 514 ++++++++++++++++ .../sources/windows/mock_sysman_driver.h | 33 + .../sources/windows/mock_sysman_fixture.h | 63 ++ .../sources/windows/mock_sysman_wddm.h | 21 + .../sources/windows/test_sysman_driver.cpp | 43 ++ .../sources/windows/test_sysman_manager.cpp | 242 ++++++++ 20 files changed, 2676 insertions(+), 11 deletions(-) create mode 100644 level_zero/sysman/source/windows/kmd_sys.h create mode 100644 level_zero/sysman/source/windows/kmd_sys_manager.cpp create mode 100644 level_zero/sysman/source/windows/kmd_sys_manager.h create mode 100644 level_zero/sysman/test/unit_tests/sources/power/windows/CMakeLists.txt create mode 100644 level_zero/sysman/test/unit_tests/sources/power/windows/mock_power.h create mode 100644 level_zero/sysman/test/unit_tests/sources/power/windows/test_zes_sysman_power.cpp create mode 100644 level_zero/sysman/test/unit_tests/sources/windows/CMakeLists.txt create mode 100644 level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h create mode 100644 level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_driver.h create mode 100644 level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h create mode 100644 level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_wddm.h create mode 100644 level_zero/sysman/test/unit_tests/sources/windows/test_sysman_driver.cpp create mode 100644 level_zero/sysman/test/unit_tests/sources/windows/test_sysman_manager.cpp diff --git a/level_zero/sysman/source/power/windows/os_power_imp.cpp b/level_zero/sysman/source/power/windows/os_power_imp.cpp index 4adb1f3c87..e94289691b 100644 --- a/level_zero/sysman/source/power/windows/os_power_imp.cpp +++ b/level_zero/sysman/source/power/windows/os_power_imp.cpp @@ -7,13 +7,61 @@ #include "level_zero/sysman/source/power/windows/os_power_imp.h" +#include "level_zero/sysman/source/windows/kmd_sys_manager.h" #include "level_zero/sysman/source/windows/os_sysman_imp.h" namespace L0 { namespace Sysman { ze_result_t WddmPowerImp::getProperties(zes_power_properties_t *pProperties) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + 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.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; } ze_result_t WddmPowerImp::getPropertiesExt(zes_power_ext_properties_t *pExtPoperties) { @@ -21,27 +69,238 @@ ze_result_t WddmPowerImp::getPropertiesExt(zes_power_ext_properties_t *pExtPoper } ze_result_t WddmPowerImp::getEnergyCounter(zes_power_energy_counter_t *pEnergy) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + uint64_t energyCounter64Bit = 0; + uint64_t valueTimeStamp = 0; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + 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; + memcpy_s(&valueTimeStamp, sizeof(uint64_t), (response.dataBuffer + sizeof(uint64_t)), sizeof(uint64_t)); + pEnergy->timestamp = valueTimeStamp; + } + + return status; } ze_result_t WddmPowerImp::getLimits(zes_power_sustained_limit_t *pSustained, zes_power_burst_limit_t *pBurst, zes_power_peak_limit_t *pPeak) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + ze_result_t status = ZE_RESULT_SUCCESS; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + + if (pSustained) { + memset(pSustained, 0, sizeof(zes_power_sustained_limit_t)); + + request.requestId = KmdSysman::Requests::Power::PowerLimit1Enabled; + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memcpy_s(&pSustained->enabled, sizeof(ze_bool_t), response.dataBuffer, sizeof(ze_bool_t)); + + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memcpy_s(&pSustained->power, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1Tau; + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memcpy_s(&pSustained->interval, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + } + + if (pBurst) { + memset(pBurst, 0, sizeof(zes_power_burst_limit_t)); + + request.requestId = KmdSysman::Requests::Power::PowerLimit2Enabled; + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memcpy_s(&pBurst->enabled, sizeof(ze_bool_t), response.dataBuffer, sizeof(ze_bool_t)); + + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit2; + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memcpy_s(&pBurst->power, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + } + + if (pPeak) { + memset(pPeak, 0, sizeof(zes_power_peak_limit_t)); + + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit4Ac; + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memcpy_s(&pPeak->powerAC, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit4Dc; + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memcpy_s(&pPeak->powerDC, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + } + + return status; } 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) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + ze_result_t status = ZE_RESULT_SUCCESS; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Set; + request.componentId = KmdSysman::Component::PowerComponent; + request.dataSize = sizeof(uint32_t); + + if (pSustained) { + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + + memcpy_s(request.dataBuffer, sizeof(uint32_t), &pSustained->power, sizeof(uint32_t)); + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1Tau; + + memcpy_s(request.dataBuffer, sizeof(uint32_t), &pSustained->interval, sizeof(uint32_t)); + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + } + + if (pBurst) { + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit2; + + memcpy_s(request.dataBuffer, sizeof(uint32_t), &pBurst->power, sizeof(uint32_t)); + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + } + + if (pPeak) { + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit4Ac; + + memcpy_s(request.dataBuffer, sizeof(uint32_t), &pPeak->powerAC, sizeof(uint32_t)); + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit4Dc; + + memcpy_s(request.dataBuffer, sizeof(uint32_t), &pPeak->powerDC, sizeof(uint32_t)); + + status = pKmdSysManager->requestSingle(request, response); + } + + return status; } ze_result_t WddmPowerImp::getEnergyThreshold(zes_energy_threshold_t *pThreshold) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + pThreshold->processId = 0; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentEnergyThreshold; + + ze_result_t status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + memset(pThreshold, 0, sizeof(zes_energy_threshold_t)); + + uint32_t value = 0; + memcpy_s(&value, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + pThreshold->threshold = static_cast(value); + pThreshold->enable = true; + + return status; } ze_result_t WddmPowerImp::setEnergyThreshold(double threshold) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Set; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentEnergyThreshold; + request.dataSize = sizeof(uint32_t); + + uint32_t value = static_cast(threshold); + memcpy_s(request.dataBuffer, sizeof(uint32_t), &value, sizeof(uint32_t)); + + return pKmdSysManager->requestSingle(request, response); } bool WddmPowerImp::isPowerModuleSupported() { - return false; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::PowerLimit1Enabled; + + ze_result_t status = pKmdSysManager->requestSingle(request, response); + + uint32_t enabled = 0; + memcpy_s(&enabled, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + return ((status == ZE_RESULT_SUCCESS) && (enabled)); } ze_result_t WddmPowerImp::getLimitsExt(uint32_t *pCount, zes_power_limit_ext_desc_t *pSustained) { @@ -53,10 +312,13 @@ ze_result_t WddmPowerImp::setLimitsExt(uint32_t *pCount, zes_power_limit_ext_des } WddmPowerImp::WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { + WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); + pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); } OsPower *OsPower::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) { - return nullptr; + WddmPowerImp *pWddmPowerImp = new WddmPowerImp(pOsSysman, onSubdevice, subdeviceId); + return static_cast(pWddmPowerImp); } } // namespace Sysman diff --git a/level_zero/sysman/source/power/windows/os_power_imp.h b/level_zero/sysman/source/power/windows/os_power_imp.h index f21f2f1295..a06b9d9faa 100644 --- a/level_zero/sysman/source/power/windows/os_power_imp.h +++ b/level_zero/sysman/source/power/windows/os_power_imp.h @@ -29,6 +29,9 @@ class WddmPowerImp : public OsPower, NEO::NonCopyableOrMovableClass { WddmPowerImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); WddmPowerImp() = default; ~WddmPowerImp() override = default; + + protected: + KmdSysManager *pKmdSysManager = nullptr; }; } // namespace Sysman diff --git a/level_zero/sysman/source/windows/CMakeLists.txt b/level_zero/sysman/source/windows/CMakeLists.txt index babc9a19ce..957cb47883 100644 --- a/level_zero/sysman/source/windows/CMakeLists.txt +++ b/level_zero/sysman/source/windows/CMakeLists.txt @@ -9,7 +9,10 @@ if(WIN32) PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/os_sysman_imp.h + ${CMAKE_CURRENT_SOURCE_DIR}/kmd_sys.h + ${CMAKE_CURRENT_SOURCE_DIR}/kmd_sys_manager.h ${CMAKE_CURRENT_SOURCE_DIR}/os_sysman_imp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/kmd_sys_manager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hw_device_id_windows.cpp ) endif() diff --git a/level_zero/sysman/source/windows/hw_device_id_windows.cpp b/level_zero/sysman/source/windows/hw_device_id_windows.cpp index 45cfd4144e..c0eec63742 100644 --- a/level_zero/sysman/source/windows/hw_device_id_windows.cpp +++ b/level_zero/sysman/source/windows/hw_device_id_windows.cpp @@ -13,7 +13,7 @@ namespace L0 { namespace Sysman { std::unique_ptr createSysmanHwDeviceId(std::unique_ptr &hwDeviceId) { - return std::unique_ptr{}; + return std::move(hwDeviceId); } } // namespace Sysman diff --git a/level_zero/sysman/source/windows/kmd_sys.h b/level_zero/sysman/source/windows/kmd_sys.h new file mode 100644 index 0000000000..8c1c9878f8 --- /dev/null +++ b/level_zero/sysman/source/windows/kmd_sys.h @@ -0,0 +1,580 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include +#include +namespace L0 { +namespace Sysman { +namespace KmdSysman { +constexpr uint32_t KmdMaxBufferSize = 2048; +constexpr uint32_t MaxPropertyBufferSize = 128; +constexpr uint32_t PcEscapeOperation = 35; +constexpr uint32_t KmdSysmanSuccess = 0; +constexpr uint32_t KmdSysmanFail = 1; +constexpr uint32_t KmdMajorVersion = 1; +constexpr uint32_t KmdMinorVersion = 0; +constexpr uint32_t KmdPatchNumber = 0; + +struct GfxSysmanMainHeaderIn { + uint32_t inVersion; + uint32_t inNumElements; + uint32_t inTotalsize; + uint8_t inBuffer[KmdMaxBufferSize]; +}; + +struct GfxSysmanMainHeaderOut { + uint32_t outStatus; + uint32_t outNumElements; + uint32_t outTotalSize; + uint8_t outBuffer[KmdMaxBufferSize]; +}; + +struct GfxSysmanReqHeaderIn { + uint32_t inRequestId; + uint32_t inCommand; + uint32_t inComponent; + uint32_t inCommandParam; + uint32_t inDataSize; +}; + +struct GfxSysmanReqHeaderOut { + uint32_t outRequestId; + uint32_t outComponent; + uint32_t outReturnCode; + uint32_t outDataSize; +}; + +enum Command { + Get = 0, + Set, + RegisterEvent, + UnregisterEvent, + + MaxCommands, +}; + +enum Events { + EnergyThresholdCrossed = 0, + EnterD0, + EnterD3, + EnterTDR, + ExitTDR, + FrequencyThrottled, + CriticalTemperature, + TemperatureThreshold1, + TemperatureThreshold2, + ResetDeviceRequired, + + MaxEvents, +}; + +enum Component { + InterfaceProperties = 0, + PowerComponent, + FrequencyComponent, + ActivityComponent, + FanComponent, + TemperatureComponent, + FpsComponent, + SchedulerComponent, + MemoryComponent, + PciComponent, + GlobalOperationsComponent, + StandbyComponent, + PerformanceComponent, + + MaxComponents, +}; + +namespace Requests { + +enum Interface { + InterfaceVersion = 0, + + MaxInterfaceRequests, +}; + +enum Power { + NumPowerDomains = 0, + + // support / enabled + EnergyThresholdSupported, + EnergyThresholdEnabled, + PowerLimit1Enabled, + PowerLimit2Enabled, + + // default fused values + PowerLimit1Default, + PowerLimit2Default, + PowerLimit1TauDefault, + PowerLimit4AcDefault, + PowerLimit4DcDefault, + EnergyThresholdDefault, + TdpDefault, + MinPowerLimitDefault, + MaxPowerLimitDefault, + EnergyCounterUnits, + + // current runtime values + CurrentPowerLimit1, + CurrentPowerLimit2, + CurrentPowerLimit1Tau, + CurrentPowerLimit4Ac, + CurrentPowerLimit4Dc, + CurrentEnergyThreshold, + DisableEnergyThreshold, + CurrentEnergyCounter, + CurrentEnergyCounter64Bit, + + MaxPowerRequests, +}; + +enum Activity { + NumActivityDomains = 0, + + // default fused values + ActivityCounterNumberOfBits, + ActivityCounterFrequency, + TimestampFrequency, + + // current runtime values + CurrentActivityCounter, + + MaxActivityRequests, +}; + +enum Performance { + NumPerformanceDomains = 0, + SupportedDomains, + Factor, + MaxPerformanceRequests +}; + +enum Temperature { + NumTemperatureDomains = 0, + + // support / enabled + TempCriticalEventSupported, + TempThreshold1EventSupported, + TempThreshold2EventSupported, + TempCriticalEventEnabled, + TempThreshold1EventEnabled, + TempThreshold2EventEnabled, + + // default fused values + MaxTempSupported, + + // current runtime values + CurrentTemperature, + + MaxTemperatureRequests, +}; + +enum Frequency { + NumFrequencyDomains = 0, + + // support / enabled + FrequencyOcSupported, + VoltageOverrideSupported, + VoltageOffsetSupported, + HighVoltageModeSupported, + ExtendedOcSupported, + FixedModeSupported, + HighVoltageEnabled, + CanControlFrequency, + FrequencyThrottledEventSupported, + + // default fused values + TjMaxDefault, + IccMaxDefault, + MaxOcFrequencyDefault, + MaxNonOcFrequencyDefault, + MaxOcVoltageDefault, + MaxNonOcVoltageDefault, + FrequencyRangeMinDefault, + FrequencyRangeMaxDefault, + + // current runtime values + CurrentFrequencyTarget, + CurrentVoltageTarget, + CurrentVoltageOffset, + CurrentVoltageMode, + CurrentFixedMode, + CurrentTjMax, + CurrentIccMax, + CurrentVoltage, + CurrentRequestedFrequency, + CurrentTdpFrequency, + CurrentEfficientFrequency, + CurrentResolvedFrequency, + CurrentThrottleReasons, + CurrentThrottleTime, + CurrentFrequencyRange, + + MaxFrequencyRequests, +}; + +enum Fans { + NumFanDomains = 0, + + // default fused values + MaxFanControlPointsSupported, + MaxFanSpeedSupported, + + // current runtime values + CurrentNumOfControlPoints, + CurrentFanPoint, + CurrentFanSpeed, + + MaxFanRequests, +}; + +enum Fps { + NumFpsDomains = 0, + IsDisplayAttached, + InstRenderTime, + TimeToFlip, + AvgFps, + AvgRenderTime, + AvgInstFps, + + MaxFpsRequests, +}; + +enum Scheduler { + NumSchedulerDomains = 0, + + MaxSchedulerRequests, +}; + +enum Memory { + NumMemoryDomains = 0, + + // default fused values + MemoryType, + MemoryLocation, + PhysicalSize, + StolenSize, + SystemSize, + DedicatedSize, + MemoryWidth, + NumChannels, + MaxBandwidth, + + // current runtime values + CurrentBandwidthRead, + CurrentBandwidthWrite, + CurrentFreeMemorySize, + CurrentTotalAllocableMem, + + MaxMemoryRequests +}; + +enum Pci { + NumPciDomains = 0, + + // support / enabled + BandwidthCountersSupported, + PacketCountersSupported, + ReplayCountersSupported, + + // default fused values + DeviceId, + VendorId, + Domain, + Bus, + Device, + Function, + Gen, + DevType, + MaxLinkWidth, + MaxLinkSpeed, + BusInterface, + BusWidth, + BarType, + BarIndex, + BarBase, + BarSize, + + // current runtime values + CurrentLinkWidth, + CurrentLinkSpeed, + CurrentLinkStatus, + CurrentLinkQualityFlags, + CurrentLinkStabilityFlags, + CurrentLinkReplayCounter, + CurrentLinkPacketCounter, + CurrentLinkRxCounter, + CurrentLinkTxCounter, + + // resizable bar + ResizableBarSupported, + ResizableBarEnabled, + + MaxPciRequests, +}; + +enum GlobalOperation { + NumGlobalOperationDomains = 0, + + TriggerDeviceLevelReset +}; + +} // namespace Requests + +enum FlipType { + MMIOFlip = 0, + MMIOAsyncFlip, + DMAFlip, + DMAAsyncFlip, + + MaxFlipTypes, +}; + +enum GeneralDomainsType { + GeneralDomainDGPU = 0, + GeneralDomainHBM, + + GeneralDomainMaxTypes, +}; + +enum TemperatureDomainsType { + TemperatureDomainPackage = 0, + TemperatureDomainDGPU, + TemperatureDomainHBM, + + TempetatureMaxDomainTypes, +}; + +enum ActivityDomainsType { + ActitvityDomainGT = 0, + ActivityDomainRenderCompute, + ActivityDomainMedia, + + ActivityDomainMaxTypes, +}; + +enum PciDomainsType { + PciCurrentDevice = 0, + PciParentDevice, + PciRootPort, + + PciDomainMaxTypes, +}; + +enum MemoryType { + DDR4 = 0, + DDR5, + LPDDR5, + LPDDR4, + DDR3, + LPDDR3, + GDDR4, + GDDR5, + GDDR5X, + GDDR6, + GDDR6X, + GDDR7, + UknownMemType, + + MaxMemoryTypes, +}; + +enum MemoryWidthType { + MemWidth8x = 0, + MemWidth16x, + MemWidth32x, + + UnknownMemWidth, + + MaxMemoryWidthTypes, +}; + +enum MemoryLocationsType { + SystemMemory = 0, + DeviceMemory, + + UnknownMemoryLocation, + + MaxMemoryLocationTypes, +}; + +enum PciGensType { + PciGen1_1 = 0, + PciGen2_0, + PciGen3_0, + PciGen4_0, + + UnknownPciGen, + + MaxPciGenTypes, +}; + +enum PciLinkSpeedType { + UnknownPciLinkSpeed = 0, + PciLinkSpeed2_5 = 1, + PciLinkSpeed5_0, + PciLinkSpeed8_0, + PciLinkSpeed16_0, + + MaxPciLinkSpeedTypes, +}; + +enum ReturnCodes { + Success = 0, + + PcuError, + IllegalCommand, + TimeOut, + IllegalData, + IllegalSubCommand, + OverclockingLocked, + DomainServiceNotSupported, + FrequencyExceedsMax, + VoltageExceedsMax, + OverclockingNotSupported, + InvalidVr, + InvalidIccMax, + VoltageOverrideDisabled, + ServiceNotAvailable, + InvalidRequestType, + InvalidComponent, + BufferNotLargeEnough, + GetNotSupported, + SetNotSupported, + MissingProperties, + InvalidEvent, + CreateEventError, + ErrorVersion, + ErrorSize, + ErrorNoElements, + ErrorBufferCorrupted, + VTNotSupported, + NotInitialized, + PropertyNotSet, + InvalidFlipType, +}; + +enum PciLinkWidthType { + PciLinkWidth1x = 0, + PciLinkWidth2x, + PciLinkWidth4x, + PciLinkWidth8x, + PciLinkWidth12x, + PciLinkWidth16x, + PciLinkWidth32x, + + UnknownPciLinkWidth, + + MaxPciLinkWidthTypes, +}; + +struct KmdSysmanVersion { + KmdSysmanVersion() : data(0) {} + union { + struct { + uint32_t reservedBits : 8; + uint32_t majorVersion : 8; + uint32_t minorVersion : 8; + uint32_t patchNumber : 8; + }; + uint32_t data; + }; +}; + +struct RequestProperty { + RequestProperty() : requestId(0), commandId(0), componentId(0), paramInfo(0), dataSize(0) {} + RequestProperty(const RequestProperty &other) { + requestId = other.requestId; + commandId = other.commandId; + componentId = other.componentId; + paramInfo = other.paramInfo; + dataSize = other.dataSize; + if (other.dataSize > 0 && other.dataSize < MaxPropertyBufferSize && other.dataBuffer) { + memcpy_s(dataBuffer, other.dataSize, other.dataBuffer, other.dataSize); + } + } + RequestProperty(uint32_t _requestId, + uint32_t _commandId, + uint32_t _componentId, + uint32_t _paramInfo, + uint32_t _dataSize, + uint8_t *_dataBuffer) { + requestId = _requestId; + commandId = _commandId; + componentId = _componentId; + paramInfo = _paramInfo; + dataSize = _dataSize; + if (dataSize > 0 && dataSize < MaxPropertyBufferSize && _dataBuffer) { + memcpy_s(dataBuffer, dataSize, _dataBuffer, dataSize); + } + } + RequestProperty &operator=(const RequestProperty &other) { + requestId = other.requestId; + commandId = other.commandId; + componentId = other.componentId; + paramInfo = other.paramInfo; + dataSize = other.dataSize; + if (other.dataSize > 0 && other.dataSize < MaxPropertyBufferSize && other.dataBuffer) { + memcpy_s(dataBuffer, other.dataSize, other.dataBuffer, other.dataSize); + } + return *this; + } + uint32_t requestId; + uint32_t commandId; + uint32_t componentId; + uint32_t paramInfo; + uint32_t dataSize; + uint8_t dataBuffer[MaxPropertyBufferSize] = {0}; +}; + +struct ResponseProperty { + ResponseProperty() : requestId(0), returnCode(0), componentId(0), dataSize(0) {} + ResponseProperty(const ResponseProperty &other) { + requestId = other.requestId; + returnCode = other.returnCode; + componentId = other.componentId; + dataSize = other.dataSize; + if (other.dataSize > 0 && other.dataSize < MaxPropertyBufferSize && other.dataBuffer) { + memcpy_s(dataBuffer, other.dataSize, other.dataBuffer, other.dataSize); + } + } + ResponseProperty(uint32_t _requestId, + uint32_t _returnCode, + uint32_t _componentId, + uint32_t _dataSize, + uint8_t *_dataBuffer) { + requestId = _requestId; + returnCode = _returnCode; + componentId = _componentId; + dataSize = _dataSize; + if (dataSize > 0 && dataSize < MaxPropertyBufferSize && _dataBuffer) { + memcpy_s(dataBuffer, dataSize, _dataBuffer, dataSize); + } + } + ResponseProperty &operator=(const ResponseProperty &other) { + this->requestId = other.requestId; + this->returnCode = other.returnCode; + this->componentId = other.componentId; + this->dataSize = other.dataSize; + if (other.dataSize > 0 && other.dataSize < MaxPropertyBufferSize && other.dataBuffer) { + memcpy_s(this->dataBuffer, other.dataSize, other.dataBuffer, other.dataSize); + } + return *this; + } + + uint32_t requestId; + uint32_t returnCode; + uint32_t componentId; + uint32_t dataSize; + uint8_t dataBuffer[MaxPropertyBufferSize] = {0}; +}; +} // namespace KmdSysman +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/windows/kmd_sys_manager.cpp b/level_zero/sysman/source/windows/kmd_sys_manager.cpp new file mode 100644 index 0000000000..5a47db8841 --- /dev/null +++ b/level_zero/sysman/source/windows/kmd_sys_manager.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/windows/kmd_sys_manager.h" + +#include "shared/source/os_interface/windows/wddm/wddm.h" + +#include "gfxEscape.h" + +namespace L0 { +namespace Sysman { +struct PcEscapeInfo { + GFX_ESCAPE_HEADER_T headerGfx; + uint32_t escapeOpInput; + uint32_t escapeErrorType; + + uint32_t dataInSize; + uint64_t pDataIn; + + uint32_t dataOutSize; + uint64_t pDataOut; +}; + +uint32_t sumOfBufferData(void *pBuffer, uint32_t bufferSize) { + uint32_t index; + uint32_t ulCheckSum; + uint32_t numOfUnsignedLongs = bufferSize / sizeof(uint32_t); + uint32_t *pElement = static_cast(pBuffer); + + ulCheckSum = 0; + for (index = 0; index < numOfUnsignedLongs; index++) { + ulCheckSum += *pElement; + pElement++; + } + + return ulCheckSum; +} + +KmdSysManager::KmdSysManager(NEO::Wddm *pWddm) { + pWddmAccess = pWddm; +} + +KmdSysManager *KmdSysManager::create(NEO::Wddm *pWddm) { + return new KmdSysManager(pWddm); +} +ze_result_t KmdSysManager::requestSingle(KmdSysman::RequestProperty &inputRequest, KmdSysman::ResponseProperty &outputResponse) { + KmdSysman::GfxSysmanMainHeaderIn inMainHeader; + KmdSysman::GfxSysmanMainHeaderOut outMainHeader; + + memset(&inMainHeader, 0, sizeof(KmdSysman::GfxSysmanMainHeaderIn)); + memset(&outMainHeader, 0, sizeof(KmdSysman::GfxSysmanMainHeaderOut)); + + std::vector vectorInput; + vectorInput.push_back(inputRequest); + + if (!parseBufferIn(&inMainHeader, vectorInput)) { + return ZE_RESULT_ERROR_INVALID_SIZE; + } + + KmdSysman::KmdSysmanVersion versionKmd; + versionKmd.data = 0; + versionKmd.majorVersion = KmdSysman::KmdMajorVersion; + versionKmd.minorVersion = KmdSysman::KmdMinorVersion; + versionKmd.patchNumber = KmdSysman::KmdPatchNumber; + + inMainHeader.inVersion = versionKmd.data; + uint64_t inPointerToLongInt = reinterpret_cast(&inMainHeader); + uint64_t outPointerToLongInt = reinterpret_cast(&outMainHeader); + auto status = escape(KmdSysman::PcEscapeOperation, inPointerToLongInt, sizeof(KmdSysman::GfxSysmanMainHeaderIn), + outPointerToLongInt, sizeof(KmdSysman::GfxSysmanMainHeaderOut)); + + if (status == STATUS_SUCCESS) { + std::vector vecOutput; + if (!parseBufferOut(&outMainHeader, vecOutput)) { + return ZE_RESULT_ERROR_INVALID_SIZE; + } + + if (vecOutput.size() > 0) { + outputResponse = vecOutput[0]; + } else { + return ZE_RESULT_ERROR_INVALID_SIZE; + } + + return (outputResponse.returnCode == KmdSysman::KmdSysmanSuccess) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_NOT_AVAILABLE; + } else if (status == STATUS_DEVICE_REMOVED) { + return ZE_RESULT_ERROR_DEVICE_LOST; + } + + return ZE_RESULT_ERROR_INVALID_ARGUMENT; +} + +ze_result_t KmdSysManager::requestMultiple(std::vector &inputRequest, std::vector &outputResponse) { + KmdSysman::GfxSysmanMainHeaderIn inMainHeader; + KmdSysman::GfxSysmanMainHeaderOut outMainHeader; + + if (inputRequest.size() == 0) { + return ZE_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + memset(&inMainHeader, 0, sizeof(KmdSysman::GfxSysmanMainHeaderIn)); + memset(&outMainHeader, 0, sizeof(KmdSysman::GfxSysmanMainHeaderOut)); + + if (!parseBufferIn(&inMainHeader, inputRequest)) { + return ZE_RESULT_ERROR_INVALID_SIZE; + } + + KmdSysman::KmdSysmanVersion versionKmd; + versionKmd.data = 0; + versionKmd.majorVersion = 1; + versionKmd.minorVersion = 0; + versionKmd.patchNumber = 0; + + inMainHeader.inVersion = versionKmd.data; + uint64_t inPointerToLongInt = reinterpret_cast(&inMainHeader); + uint64_t outPointerToLongInt = reinterpret_cast(&outMainHeader); + auto status = escape(KmdSysman::PcEscapeOperation, inPointerToLongInt, sizeof(KmdSysman::GfxSysmanMainHeaderIn), + outPointerToLongInt, sizeof(KmdSysman::GfxSysmanMainHeaderOut)); + + if (status == STATUS_SUCCESS) { + if (!parseBufferOut(&outMainHeader, outputResponse)) { + return ZE_RESULT_ERROR_INVALID_SIZE; + } + + if (outputResponse.size() == 0) { + return ZE_RESULT_ERROR_INVALID_SIZE; + } + return ZE_RESULT_SUCCESS; + } else if (status == STATUS_DEVICE_REMOVED) { + return ZE_RESULT_ERROR_DEVICE_LOST; + } + + return ZE_RESULT_ERROR_INVALID_ARGUMENT; +} + +NTSTATUS KmdSysManager::escape(uint32_t escapeOp, uint64_t pDataIn, uint32_t dataInSize, uint64_t pDataOut, uint32_t dataOutSize) { + NTSTATUS status = STATUS_UNSUCCESSFUL; + if (pWddmAccess) { + D3DKMT_ESCAPE escapeCommand = {0}; + PcEscapeInfo pcEscape = {0}; + escapeCommand.Flags.HardwareAccess = 0; + escapeCommand.Flags.Reserved = 0; + escapeCommand.hAdapter = (D3DKMT_HANDLE)0; + escapeCommand.hContext = (D3DKMT_HANDLE)0; + escapeCommand.hDevice = (D3DKMT_HANDLE)pWddmAccess->getDeviceHandle(); + escapeCommand.pPrivateDriverData = &pcEscape; + escapeCommand.PrivateDriverDataSize = sizeof(pcEscape); + escapeCommand.Type = D3DKMT_ESCAPE_DRIVERPRIVATE; + + pcEscape.headerGfx.EscapeCode = GFX_ESCAPE_PWRCONS_CONTROL; + pcEscape.escapeErrorType = 0; + pcEscape.escapeOpInput = escapeOp; + pcEscape.headerGfx.Size = sizeof(pcEscape) - sizeof(pcEscape.headerGfx); + + pcEscape.pDataIn = pDataIn; + pcEscape.pDataOut = pDataOut; + + pcEscape.dataInSize = dataInSize; + pcEscape.dataOutSize = dataOutSize; + void *pBuffer = &pcEscape; + pBuffer = reinterpret_cast(pBuffer) + sizeof(pcEscape.headerGfx); + pcEscape.headerGfx.CheckSum = sumOfBufferData(pBuffer, pcEscape.headerGfx.Size); + + status = pWddmAccess->escape(escapeCommand); + } + + return status; +} + +bool KmdSysManager::parseBufferIn(KmdSysman::GfxSysmanMainHeaderIn *pInMainHeader, std::vector &vectorInput) { + memset(pInMainHeader, 0, sizeof(KmdSysman::GfxSysmanMainHeaderIn)); + for (uint32_t i = 0; i < vectorInput.size(); i++) { + KmdSysman::GfxSysmanReqHeaderIn headerIn; + headerIn.inRequestId = vectorInput[i].requestId; + headerIn.inCommand = vectorInput[i].commandId; + headerIn.inComponent = vectorInput[i].componentId; + headerIn.inCommandParam = vectorInput[i].paramInfo; + headerIn.inDataSize = vectorInput[i].dataSize; + + if ((pInMainHeader->inTotalsize + sizeof(KmdSysman::GfxSysmanReqHeaderIn)) >= KmdSysman::KmdMaxBufferSize) { + memset(pInMainHeader, 0, sizeof(KmdSysman::GfxSysmanMainHeaderIn)); + return false; + } + + if ((pInMainHeader->inTotalsize + sizeof(KmdSysman::GfxSysmanReqHeaderIn) + headerIn.inDataSize) >= KmdSysman::KmdMaxBufferSize) { + memset(pInMainHeader, 0, sizeof(KmdSysman::GfxSysmanMainHeaderIn)); + return false; + } + + uint8_t *pBuff = reinterpret_cast(&pInMainHeader->inBuffer[pInMainHeader->inTotalsize]); + memcpy_s(pBuff, sizeof(KmdSysman::GfxSysmanReqHeaderIn), &headerIn, sizeof(KmdSysman::GfxSysmanReqHeaderIn)); + + pBuff += sizeof(KmdSysman::GfxSysmanReqHeaderIn); + pInMainHeader->inTotalsize += sizeof(KmdSysman::GfxSysmanReqHeaderIn); + + if (headerIn.inDataSize > 0) { + memcpy_s(pBuff, headerIn.inDataSize, vectorInput[i].dataBuffer, headerIn.inDataSize); + pInMainHeader->inTotalsize += headerIn.inDataSize; + } + + pInMainHeader->inNumElements++; + } + + return true; +} + +bool KmdSysManager::parseBufferOut(KmdSysman::GfxSysmanMainHeaderOut *pOutMainHeader, std::vector &vectorOutput) { + uint8_t *pBuff = reinterpret_cast(pOutMainHeader->outBuffer); + uint32_t totalSize = 0; + vectorOutput.clear(); + for (uint32_t i = 0; i < pOutMainHeader->outNumElements; i++) { + KmdSysman::ResponseProperty propertyResponse; + KmdSysman::GfxSysmanReqHeaderOut headerOut; + + memcpy_s(&headerOut, sizeof(KmdSysman::GfxSysmanReqHeaderOut), pBuff, sizeof(KmdSysman::GfxSysmanReqHeaderOut)); + + propertyResponse.requestId = headerOut.outRequestId; + propertyResponse.returnCode = headerOut.outReturnCode; + propertyResponse.componentId = headerOut.outComponent; + propertyResponse.dataSize = headerOut.outDataSize; + + pBuff += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + + if (headerOut.outDataSize > 0) { + memcpy_s(propertyResponse.dataBuffer, headerOut.outDataSize, pBuff, headerOut.outDataSize); + pBuff += headerOut.outDataSize; + } + + vectorOutput.push_back(propertyResponse); + + totalSize += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + totalSize += headerOut.outDataSize; + } + + if (totalSize != pOutMainHeader->outTotalSize) { + vectorOutput.clear(); + return false; + } + + return true; +} +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/windows/kmd_sys_manager.h b/level_zero/sysman/source/windows/kmd_sys_manager.h new file mode 100644 index 0000000000..0401880de3 --- /dev/null +++ b/level_zero/sysman/source/windows/kmd_sys_manager.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/source/gmm_helper/gmm_lib.h" + +#include "level_zero/sysman/source/windows/kmd_sys.h" +#include "level_zero/ze_api.h" + +#include + +namespace NEO { +class Wddm; +} + +namespace L0 { +namespace Sysman { +class KmdSysManager { + public: + static KmdSysManager *create(NEO::Wddm *pWddm); + KmdSysManager() = default; + virtual ~KmdSysManager() = default; + + virtual ze_result_t requestSingle(KmdSysman::RequestProperty &In, KmdSysman::ResponseProperty &Out); + virtual ze_result_t requestMultiple(std::vector &vIn, std::vector &vOut); + NEO::Wddm *GetWddmAccess() { return pWddmAccess; } + + private: + virtual NTSTATUS escape(uint32_t escapeOp, uint64_t pDataIn, uint32_t dataInSize, uint64_t pDataOut, uint32_t dataOutSize); + + bool parseBufferIn(KmdSysman::GfxSysmanMainHeaderIn *pIn, std::vector &vIn); + bool parseBufferOut(KmdSysman::GfxSysmanMainHeaderOut *pOut, std::vector &vOut); + + KmdSysManager(NEO::Wddm *pWddm); + NEO::Wddm *pWddmAccess = nullptr; +}; +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/windows/os_sysman_imp.cpp b/level_zero/sysman/source/windows/os_sysman_imp.cpp index cfbad675ad..49f6c25516 100644 --- a/level_zero/sysman/source/windows/os_sysman_imp.cpp +++ b/level_zero/sysman/source/windows/os_sysman_imp.cpp @@ -7,21 +7,79 @@ #include "level_zero/sysman/source/windows/os_sysman_imp.h" +#include "shared/source/helpers/gfx_core_helper.h" +#include "shared/source/os_interface/driver_info.h" +#include "shared/source/os_interface/windows/wddm/wddm.h" + +#include "level_zero/sysman/source/firmware_util/firmware_util.h" +#include "level_zero/sysman/source/windows/kmd_sys_manager.h" + namespace L0 { namespace Sysman { ze_result_t WddmSysmanImp::init() { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + NEO::OSInterface &OsInterface = *(pParentSysmanDeviceImp->getRootDeviceEnvironment()).osInterface; + auto driverModel = OsInterface.getDriverModel(); + + if (driverModel && (driverModel->getDriverModelType() == NEO::DriverModelType::WDDM)) { + pWddm = driverModel->as(); + } else { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + pKmdSysManager = KmdSysManager::create(pWddm); + UNRECOVERABLE_IF(nullptr == pKmdSysManager); + + subDeviceCount = NEO::GfxCoreHelper::getSubDevicesCount(&pParentSysmanDeviceImp->getHardwareInfo()); + if (subDeviceCount == 1) { + subDeviceCount = 0; + } + + return ZE_RESULT_SUCCESS; } uint32_t WddmSysmanImp::getSubDeviceCount() { - return 0; + return subDeviceCount; +} + +void WddmSysmanImp::createFwUtilInterface() { + const auto pciBusInfo = pParentSysmanDeviceImp->getRootDeviceEnvironment().osInterface->getDriverModel()->getPciBusInfo(); + const uint16_t domain = static_cast(pciBusInfo.pciDomain); + const uint8_t bus = static_cast(pciBusInfo.pciBus); + const uint8_t device = static_cast(pciBusInfo.pciDevice); + const uint8_t function = static_cast(pciBusInfo.pciFunction); + pFwUtilInterface = FirmwareUtil::create(domain, bus, device, function); +} + +FirmwareUtil *WddmSysmanImp::getFwUtilInterface() { + if (pFwUtilInterface == nullptr) { + createFwUtilInterface(); + } + return pFwUtilInterface; +} + +void WddmSysmanImp::releaseFwUtilInterface() { + if (nullptr != pFwUtilInterface) { + delete pFwUtilInterface; + pFwUtilInterface = nullptr; + } } WddmSysmanImp::WddmSysmanImp(SysmanDeviceImp *pParentSysmanDeviceImp) { + this->pParentSysmanDeviceImp = pParentSysmanDeviceImp; } WddmSysmanImp::~WddmSysmanImp() { + if (nullptr != pKmdSysManager) { + delete pKmdSysManager; + pKmdSysManager = nullptr; + } + releaseFwUtilInterface(); +} + +KmdSysManager &WddmSysmanImp::getKmdSysManager() { + UNRECOVERABLE_IF(nullptr == pKmdSysManager); + return *pKmdSysManager; } OsSysman *OsSysman::create(SysmanDeviceImp *pParentSysmanDeviceImp) { diff --git a/level_zero/sysman/source/windows/os_sysman_imp.h b/level_zero/sysman/source/windows/os_sysman_imp.h index 3273fb5420..fd58e9de11 100644 --- a/level_zero/sysman/source/windows/os_sysman_imp.h +++ b/level_zero/sysman/source/windows/os_sysman_imp.h @@ -8,8 +8,15 @@ #pragma once #include "shared/source/helpers/non_copyable_or_moveable.h" +#include "level_zero/sysman/source/firmware_util/firmware_util.h" #include "level_zero/sysman/source/os_sysman.h" +#include "level_zero/sysman/source/sysman_device.h" +#include "level_zero/sysman/source/sysman_device_imp.h" +#include "level_zero/sysman/source/windows/kmd_sys_manager.h" +namespace NEO { +class Wddm; +} namespace L0 { namespace Sysman { @@ -19,7 +26,24 @@ class WddmSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass { ~WddmSysmanImp() override; ze_result_t init() override; + + KmdSysManager &getKmdSysManager(); + FirmwareUtil *getFwUtilInterface(); + NEO::Wddm &getWddm(); + void releaseFwUtilInterface(); + uint32_t getSubDeviceCount() override; + + protected: + FirmwareUtil *pFwUtilInterface = nullptr; + KmdSysManager *pKmdSysManager = nullptr; + SysmanDevice *pDevice = nullptr; + + private: + SysmanDeviceImp *pParentSysmanDeviceImp = nullptr; + NEO::Wddm *pWddm = nullptr; + uint32_t subDeviceCount = 0; + void createFwUtilInterface(); }; } // namespace Sysman diff --git a/level_zero/sysman/test/unit_tests/sources/firmware_util/mock_fw_util_fixture.h b/level_zero/sysman/test/unit_tests/sources/firmware_util/mock_fw_util_fixture.h index 3f51d43635..c73c30085a 100644 --- a/level_zero/sysman/test/unit_tests/sources/firmware_util/mock_fw_util_fixture.h +++ b/level_zero/sysman/test/unit_tests/sources/firmware_util/mock_fw_util_fixture.h @@ -7,6 +7,7 @@ #pragma once +#include "shared/source/os_interface/os_library.h" #include "shared/test/common/test_macros/mock_method_macros.h" #include "level_zero/sysman/source/firmware_util/firmware_util.h" diff --git a/level_zero/sysman/test/unit_tests/sources/power/windows/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/power/windows/CMakeLists.txt new file mode 100644 index 0000000000..8cbf3e4f89 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/power/windows/CMakeLists.txt @@ -0,0 +1,14 @@ +# +# Copyright (C) 2020-2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(WIN32) + target_sources(${TARGET_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_sysman_power.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_power.h + ) +endif() 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 new file mode 100644 index 0000000000..e48ead34d5 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/power/windows/mock_power.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h" + +namespace L0 { +namespace ult { + +struct PowerKmdSysManager : public MockKmdSysManager { + + uint32_t mockPowerLimit1Enabled = 1; + uint32_t mockPowerLimit2Enabled = 1; + int32_t mockPowerLimit1 = 25000; + int32_t mockPowerLimit2 = 41000; + int32_t mockTauPowerLimit1 = 20800; + uint32_t mockTpdDefault = 34000; + uint32_t mockMinPowerLimit = 1000; + uint32_t mockMaxPowerLimit = 80000; + int32_t mockAcPowerPeak = 0; + int32_t mockDcPowerPeak = 0; + uint32_t mockEnergyThreshold = 0; + uint32_t mockEnergyCounter = 3231121; + uint32_t mockTimeStamp = 1123412412; + uint32_t mockEnergyUnit = 14; + uint64_t mockEnergyCounter64Bit = 32323232323232; + uint32_t mockFrequencyTimeStamp = 38400000; + + void getActivityProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + uint8_t *pBuffer = reinterpret_cast(pResponse); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + + switch (pRequest->inRequestId) { + case KmdSysman::Requests::Activity::TimestampFrequency: { + uint32_t *pValueFrequency = reinterpret_cast(pBuffer); + *pValueFrequency = mockFrequencyTimeStamp; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + default: { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } break; + } + } + + void getPowerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) override { + uint8_t *pBuffer = reinterpret_cast(pResponse); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + + switch (pRequest->inRequestId) { + case KmdSysman::Requests::Power::EnergyThresholdSupported: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = static_cast(this->allowSetCalls); + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::TdpDefault: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockTpdDefault; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::MinPowerLimitDefault: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockMinPowerLimit; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::MaxPowerLimitDefault: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockMaxPowerLimit; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::PowerLimit1Enabled: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockPowerLimit1Enabled; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::PowerLimit2Enabled: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockPowerLimit2Enabled; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit1: { + int32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockPowerLimit1; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(int32_t); + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit1Tau: { + int32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockTauPowerLimit1; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(int32_t); + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit2: { + int32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockPowerLimit2; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(int32_t); + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit4Ac: { + int32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockAcPowerPeak; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(int32_t); + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit4Dc: { + int32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockDcPowerPeak; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::CurrentEnergyThreshold: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockEnergyThreshold; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::CurrentEnergyCounter: { + uint32_t *pValueCounter = reinterpret_cast(pBuffer); + uint64_t *pValueTS = reinterpret_cast(pBuffer + sizeof(uint32_t)); + *pValueCounter = mockEnergyCounter; + *pValueTS = mockTimeStamp; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t) + sizeof(uint64_t); + } break; + case KmdSysman::Requests::Power::EnergyCounterUnits: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockEnergyUnit; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Power::CurrentEnergyCounter64Bit: { + uint64_t *pValueCounter = reinterpret_cast(pBuffer); + uint64_t *pValueTS = reinterpret_cast(pBuffer + sizeof(uint64_t)); + *pValueCounter = mockEnergyCounter64Bit; + *pValueTS = mockTimeStamp; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint64_t) + sizeof(uint64_t); + } break; + default: { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } break; + } + } + + void setPowerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) override { + uint8_t *pBuffer = reinterpret_cast(pRequest); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderIn); + + switch (pRequest->inRequestId) { + case KmdSysman::Requests::Power::CurrentPowerLimit1: { + int32_t *pValue = reinterpret_cast(pBuffer); + mockPowerLimit1 = *pValue; + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit1Tau: { + int32_t *pValue = reinterpret_cast(pBuffer); + mockTauPowerLimit1 = *pValue; + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit2: { + int32_t *pValue = reinterpret_cast(pBuffer); + mockPowerLimit2 = *pValue; + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit4Ac: { + int32_t *pValue = reinterpret_cast(pBuffer); + mockAcPowerPeak = *pValue; + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + } break; + case KmdSysman::Requests::Power::CurrentPowerLimit4Dc: { + int32_t *pValue = reinterpret_cast(pBuffer); + mockDcPowerPeak = *pValue; + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + } break; + case KmdSysman::Requests::Power::CurrentEnergyThreshold: { + uint32_t *pValue = reinterpret_cast(pBuffer); + mockEnergyThreshold = *pValue; + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + } break; + default: { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } break; + } + } +}; + +} // namespace ult +} // 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 new file mode 100644 index 0000000000..9291729f91 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/power/windows/test_zes_sysman_power.cpp @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#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 ult { + +constexpr uint32_t powerHandleComponentCount = 1u; +class SysmanDevicePowerFixture : 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; + } + + pSysmanDeviceImp->pPowerHandleContext->handleList.clear(); + } + void TearDown() override { + pWddmSysmanImp->pKmdSysManager = pOriginalKmdSysManager; + SysmanDeviceFixture::TearDown(); + } + + std::vector get_power_handles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { + init(true); + + uint32_t count = 0; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, powerHandleComponentCount); +} + +TEST_F(SysmanDevicePowerFixture, GivenInvalidComponentCountWhenEnumeratingPowerDomainThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { + init(true); + + uint32_t count = 0; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, powerHandleComponentCount); + + count = count + 1; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, powerHandleComponentCount); +} + +TEST_F(SysmanDevicePowerFixture, GivenComponentCountZeroWhenEnumeratingPowerDomainThenValidPowerHandlesIsReturned) { + init(true); + + uint32_t count = 0; + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, powerHandleComponentCount); + + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumPowerDomains(pSysmanDevice->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + for (auto handle : handles) { + EXPECT_NE(handle, nullptr); + } +} + +TEST_F(SysmanDevicePowerFixture, DISABLED_GivenValidPowerHandleWhenGettingPowerPropertiesAllowSetToTrueThenCallSucceeds) { + // Setting allow set calls or not + init(true); + + auto handles = get_power_handles(powerHandleComponentCount); + + for (auto handle : handles) { + zes_power_properties_t properties; + + ze_result_t result = zesPowerGetProperties(handle, &properties); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_FALSE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0); + EXPECT_TRUE(properties.canControl); + EXPECT_TRUE(properties.isEnergyThresholdSupported); + EXPECT_EQ(properties.maxLimit, pKmdSysManager->mockMaxPowerLimit); + EXPECT_EQ(properties.minLimit, pKmdSysManager->mockMinPowerLimit); + EXPECT_EQ(properties.defaultLimit, pKmdSysManager->mockTpdDefault); + } +} + +TEST_F(SysmanDevicePowerFixture, DISABLED_GivenValidPowerHandleWhenGettingPowerPropertiesAllowSetToFalseThenCallSucceeds) { + // Setting allow set calls or not + init(false); + + auto handles = get_power_handles(powerHandleComponentCount); + + for (auto handle : handles) { + zes_power_properties_t properties; + + ze_result_t result = zesPowerGetProperties(handle, &properties); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_FALSE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0); + EXPECT_FALSE(properties.canControl); + EXPECT_FALSE(properties.isEnergyThresholdSupported); + EXPECT_EQ(properties.maxLimit, pKmdSysManager->mockMaxPowerLimit); + EXPECT_EQ(properties.minLimit, pKmdSysManager->mockMinPowerLimit); + EXPECT_EQ(properties.defaultLimit, pKmdSysManager->mockTpdDefault); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved) { + // Setting allow set calls or not + init(true); + + auto handles = get_power_handles(powerHandleComponentCount); + + 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, pKmdSysManager->mockEnergyCounter64Bit); + EXPECT_EQ(energyCounter.timestamp, pKmdSysManager->mockTimeStamp); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenGettingPowerLimitsAllowSetToFalseThenCallSucceedsWithValidPowerReadingsRetrieved) { + // Setting allow set calls or not + init(false); + + auto handles = get_power_handles(powerHandleComponentCount); + + for (auto handle : handles) { + zes_power_sustained_limit_t sustained; + zes_power_burst_limit_t burst; + zes_power_peak_limit_t peak; + + ze_result_t result = zesPowerGetLimits(handle, &sustained, &burst, &peak); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_TRUE(sustained.enabled); + EXPECT_EQ(sustained.power, pKmdSysManager->mockPowerLimit1); + EXPECT_EQ(sustained.interval, pKmdSysManager->mockTauPowerLimit1); + EXPECT_TRUE(burst.enabled); + EXPECT_EQ(burst.power, pKmdSysManager->mockPowerLimit2); + EXPECT_EQ(peak.powerAC, pKmdSysManager->mockAcPowerPeak); + EXPECT_EQ(peak.powerDC, pKmdSysManager->mockDcPowerPeak); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerLimitsAllowSetToFalseThenCallFails) { + // Setting allow set calls or not + init(false); + + auto handles = get_power_handles(powerHandleComponentCount); + + for (auto handle : handles) { + zes_power_sustained_limit_t sustained; + zes_power_burst_limit_t burst; + zes_power_peak_limit_t peak; + + ze_result_t result = zesPowerGetLimits(handle, &sustained, &burst, &peak); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + sustained.power += 1000; + + result = zesPowerSetLimits(handle, &sustained, &burst, &peak); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingEnergyThresholdAllowSetToFalseThenCallFails) { + // Setting allow set calls or not + init(false); + + auto handles = get_power_handles(powerHandleComponentCount); + + for (auto handle : handles) { + double energyThreshold = 2000; + + ze_result_t result = zesPowerSetEnergyThreshold(handle, energyThreshold); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingEnergyThresholdAllowSetToTrueThenCallSucceeds) { + // Setting allow set calls or not + init(true); + + auto handles = get_power_handles(powerHandleComponentCount); + + for (auto handle : handles) { + double energyThreshold = 2000; + + ze_result_t result = zesPowerSetEnergyThreshold(handle, energyThreshold); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + zes_energy_threshold_t newEnergyThreshold; + result = zesPowerGetEnergyThreshold(handle, &newEnergyThreshold); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(newEnergyThreshold.threshold, energyThreshold); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandleWhenSettingPowerLimitsAllowSetToTrueThenCallSucceeds) { + // Setting allow set calls or not + init(true); + + auto handles = get_power_handles(powerHandleComponentCount); + + for (auto handle : handles) { + zes_power_sustained_limit_t sustained; + zes_power_burst_limit_t burst; + zes_power_peak_limit_t peak; + + uint32_t powerIncrement = 1500; + uint32_t timeIncrement = 12000; + uint32_t AcPeakPower = 56000; + uint32_t DcPeakPower = 44100; + + ze_result_t result = zesPowerGetLimits(handle, &sustained, &burst, &peak); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + sustained.power += powerIncrement; + sustained.interval += timeIncrement; + burst.power += powerIncrement; + peak.powerAC = AcPeakPower; + peak.powerDC = DcPeakPower; + + result = zesPowerSetLimits(handle, &sustained, &burst, &peak); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + zes_power_sustained_limit_t newSustained; + zes_power_burst_limit_t newBurst; + zes_power_peak_limit_t newPeak; + + result = zesPowerGetLimits(handle, &newSustained, &newBurst, &newPeak); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + EXPECT_EQ(newSustained.power, sustained.power); + EXPECT_EQ(newSustained.interval, sustained.interval); + EXPECT_EQ(newBurst.power, burst.power); + EXPECT_EQ(newPeak.powerAC, peak.powerAC); + EXPECT_EQ(newPeak.powerDC, peak.powerDC); + } +} + +TEST_F(SysmanDevicePowerFixture, GivenValidPowerHandlesWhenCallingSetAndGetPowerLimitExtWhenHwmonInterfaceExistThenUnsupportedFeatureIsReturned) { + // Setting allow set calls or not + init(true); + + auto handles = get_power_handles(powerHandleComponentCount); + for (auto handle : handles) { + uint32_t limitCount = 0; + + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesPowerGetLimitsExt(handle, &limitCount, nullptr)); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesPowerSetLimitsExt(handle, &limitCount, nullptr)); + } +} + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/windows/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/windows/CMakeLists.txt new file mode 100644 index 0000000000..4868ccea74 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/windows/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Copyright (C) 2020-2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(WIN32) + target_sources(${TARGET_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysman_wddm.h + ${CMAKE_CURRENT_SOURCE_DIR}/mock_kmd_sys_manager.h + ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysman_fixture.h + ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysman_driver.h + ${CMAKE_CURRENT_SOURCE_DIR}/test_sysman_driver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_sysman_manager.cpp + ) +endif() diff --git a/level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h b/level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h new file mode 100644 index 0000000000..8992da73c4 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h @@ -0,0 +1,514 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "level_zero/sysman/source/windows/kmd_sys_manager.h" +#include "level_zero/zes_api.h" + +namespace L0 { +namespace ult { + +constexpr uint32_t mockKmdVersionMajor = 1; +constexpr uint32_t mockKmdVersionMinor = 0; +constexpr uint32_t mockKmdPatchNumber = 0; +constexpr uint32_t mockKmdMaxHandlesPerEvent = 20; + +struct MockEventHandle { + HANDLE eventHandle; + bool inited = false; +}; + +uint64_t convertTStoMicroSec(uint64_t TS, uint32_t freq); +namespace KmdSysman = L0::Sysman::KmdSysman; +struct MockKmdSysManager : public L0::Sysman::KmdSysManager { + ze_bool_t allowSetCalls = false; + ze_bool_t fanSupported = false; + uint32_t mockPowerLimit1 = 2500; + NTSTATUS mockEscapeResult = STATUS_SUCCESS; + bool mockRequestSingle = false; + bool mockRequestMultiple = false; + bool requestMultipleSizeDiff = false; + ze_result_t mockRequestSingleResult = ZE_RESULT_ERROR_NOT_AVAILABLE; + ze_result_t mockRequestMultipleResult = ZE_RESULT_ERROR_NOT_AVAILABLE; + + MockEventHandle handles[KmdSysman::Events::MaxEvents][mockKmdMaxHandlesPerEvent]; + + MOCKABLE_VIRTUAL void getInterfaceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setInterfaceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getPowerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + uint8_t *pBuffer = reinterpret_cast(pResponse); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + + if (pRequest->inRequestId == KmdSysman::Requests::Power::CurrentPowerLimit1) { + uint32_t *pPl1 = reinterpret_cast(pBuffer); + *pPl1 = mockPowerLimit1; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } else { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + } + + MOCKABLE_VIRTUAL void setPowerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + uint8_t *pBuffer = reinterpret_cast(pRequest); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderIn); + + if (pRequest->inRequestId == KmdSysman::Requests::Power::CurrentPowerLimit1) { + uint32_t *pPl1 = reinterpret_cast(pBuffer); + mockPowerLimit1 = *pPl1; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + } else { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + } + + MOCKABLE_VIRTUAL void getFrequencyProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setFrequencyProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getActivityProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getPerformanceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setActivityProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getFanProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setFanProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getTemperatureProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setTemperatureProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setPerformanceProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getFpsProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setFpsProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getSchedulerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setSchedulerProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getMemoryProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setMemoryProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getPciProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setPciProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void getGlobalOperationsProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + MOCKABLE_VIRTUAL void setGlobalOperationsProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } + + void retrieveCorrectVersion(KmdSysman::GfxSysmanMainHeaderOut *pHeaderOut) { + pHeaderOut->outNumElements = 1; + pHeaderOut->outTotalSize = 0; + + KmdSysman::GfxSysmanReqHeaderOut *pResponse = reinterpret_cast(pHeaderOut->outBuffer); + uint8_t *pBuffer = nullptr; + + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(KmdSysman::KmdSysmanVersion); + pBuffer = reinterpret_cast(pResponse); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + pHeaderOut->outTotalSize += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + + KmdSysman::KmdSysmanVersion *pCurrentVersion = reinterpret_cast(pBuffer); + pCurrentVersion->majorVersion = mockKmdVersionMajor; + pCurrentVersion->minorVersion = mockKmdVersionMinor; + pCurrentVersion->patchNumber = mockKmdPatchNumber; + + pHeaderOut->outTotalSize += sizeof(KmdSysman::KmdSysmanVersion); + } + + bool validateInputBuffer(KmdSysman::GfxSysmanMainHeaderIn *pHeaderIn) { + uint32_t sizeCheck = pHeaderIn->inTotalsize; + uint8_t *pBufferPtr = pHeaderIn->inBuffer; + + for (uint32_t i = 0; i < pHeaderIn->inNumElements; i++) { + KmdSysman::GfxSysmanReqHeaderIn *pRequest = reinterpret_cast(pBufferPtr); + if (pRequest->inCommand == KmdSysman::Command::Get || + pRequest->inCommand == KmdSysman::Command::Set || + pRequest->inCommand == KmdSysman::Command::RegisterEvent) { + if (pRequest->inComponent >= KmdSysman::Component::InterfaceProperties && pRequest->inComponent < KmdSysman::Component::MaxComponents) { + pBufferPtr += sizeof(KmdSysman::GfxSysmanReqHeaderIn); + sizeCheck -= sizeof(KmdSysman::GfxSysmanReqHeaderIn); + + if (pRequest->inCommand == KmdSysman::Command::Set || + pRequest->inCommand == KmdSysman::Command::RegisterEvent) { + if (pRequest->inDataSize == 0) { + return false; + } + pBufferPtr += pRequest->inDataSize; + sizeCheck -= pRequest->inDataSize; + } + } else { + return false; + } + } else { + return false; + } + } + + if (sizeCheck != 0) { + return false; + } + + return true; + } + + void registerEvent(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + if (!allowSetCalls) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + return; + } + + uint8_t *pBuffer = reinterpret_cast(pRequest); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderIn); + + pResponse->outDataSize = 0; + + switch (pRequest->inRequestId) { + case KmdSysman::Events::EnterD0: + case KmdSysman::Events::EnterD3: + case KmdSysman::Events::EnterTDR: + case KmdSysman::Events::ExitTDR: + case KmdSysman::Events::EnergyThresholdCrossed: { + bool found = false; + for (uint32_t i = 0; i < mockKmdMaxHandlesPerEvent; i++) { + if (!handles[pRequest->inRequestId][i].inited) { + handles[pRequest->inRequestId][i].inited = true; + unsigned long long eventID = *(unsigned long long *)pBuffer; + handles[pRequest->inRequestId][i].eventHandle = reinterpret_cast(eventID); + found = true; + break; + } + } + pResponse->outReturnCode = found ? KmdSysman::KmdSysmanSuccess : KmdSysman::KmdSysmanFail; + } break; + default: + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + break; + } + } + + void signalEvent(uint32_t idEvent) { + + uint32_t arrayID = 0; + if (idEvent & ZES_EVENT_TYPE_FLAG_ENERGY_THRESHOLD_CROSSED) { + arrayID = KmdSysman::Events::EnergyThresholdCrossed; + } + + if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_ENTER) { + arrayID = KmdSysman::Events::EnterD3; + } + + if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_SLEEP_STATE_EXIT) { + arrayID = KmdSysman::Events::EnterD0; + } + + if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_DETACH) { + arrayID = KmdSysman::Events::EnterTDR; + } + + if (idEvent & ZES_EVENT_TYPE_FLAG_DEVICE_ATTACH) { + arrayID = KmdSysman::Events::ExitTDR; + } + + for (uint32_t i = 0; i < mockKmdMaxHandlesPerEvent; i++) { + if (handles[arrayID][i].inited) { + SetEvent(handles[arrayID][i].eventHandle); + } + } + } + + ze_result_t requestSingle(KmdSysman::RequestProperty &In, KmdSysman::ResponseProperty &Out) { + if (mockRequestSingle == false) { + return KmdSysManager::requestSingle(In, Out); + } + return mockRequestSingleResult; + } + + ze_result_t requestMultiple(std::vector &vIn, std::vector &vOut) { + if (mockRequestMultiple == false) { + return KmdSysManager::requestMultiple(vIn, vOut); + } else { + if (requestMultipleSizeDiff == true) { + KmdSysman::ResponseProperty temp; + vOut.push_back(temp); + } + return mockRequestMultipleResult; + } + return ZE_RESULT_SUCCESS; + } + + void setProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + if (!allowSetCalls) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + return; + } + + switch (pRequest->inComponent) { + case KmdSysman::Component::InterfaceProperties: { + setInterfaceProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::PowerComponent: { + setPowerProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::FrequencyComponent: { + setFrequencyProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::ActivityComponent: { + setActivityProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::FanComponent: { + setFanProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::TemperatureComponent: { + setTemperatureProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::FpsComponent: { + setFpsProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::SchedulerComponent: { + setSchedulerProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::MemoryComponent: { + setMemoryProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::PciComponent: { + setPciProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::GlobalOperationsComponent: { + setGlobalOperationsProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::PerformanceComponent: { + setPerformanceProperty(pRequest, pResponse); + } break; + default: { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } break; + } + } + + void getProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) { + switch (pRequest->inComponent) { + case KmdSysman::Component::InterfaceProperties: { + getInterfaceProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::PowerComponent: { + getPowerProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::FrequencyComponent: { + getFrequencyProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::ActivityComponent: { + getActivityProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::FanComponent: { + getFanProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::TemperatureComponent: { + getTemperatureProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::FpsComponent: { + getFpsProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::SchedulerComponent: { + getSchedulerProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::MemoryComponent: { + getMemoryProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::PciComponent: { + getPciProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::GlobalOperationsComponent: { + getGlobalOperationsProperty(pRequest, pResponse); + } break; + case KmdSysman::Component::PerformanceComponent: { + getPerformanceProperty(pRequest, pResponse); + } break; + default: { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } break; + } + } + + NTSTATUS escape(uint32_t escapeOp, uint64_t pInPtr, uint32_t dataInSize, uint64_t pOutPtr, uint32_t dataOutSize) { + if (mockEscapeResult != STATUS_SUCCESS) { + return mockEscapeResult; + } + void *pDataIn = reinterpret_cast(pInPtr); + void *pDataOut = reinterpret_cast(pOutPtr); + + if (pDataIn == nullptr || pDataOut == nullptr) { + return STATUS_UNSUCCESSFUL; + } + + if (dataInSize != sizeof(KmdSysman::GfxSysmanMainHeaderIn) || dataOutSize != sizeof(KmdSysman::GfxSysmanMainHeaderOut)) { + return STATUS_UNSUCCESSFUL; + } + + if (escapeOp != KmdSysman::PcEscapeOperation) { + return STATUS_UNSUCCESSFUL; + } + + KmdSysman::GfxSysmanMainHeaderIn *pSysmanMainHeaderIn = reinterpret_cast(pDataIn); + KmdSysman::GfxSysmanMainHeaderOut *pSysmanMainHeaderOut = reinterpret_cast(pDataOut); + + KmdSysman::KmdSysmanVersion versionSysman; + versionSysman.data = pSysmanMainHeaderIn->inVersion; + + if (versionSysman.majorVersion != KmdSysman::KmdMajorVersion) { + if (versionSysman.majorVersion == 0) { + retrieveCorrectVersion(pSysmanMainHeaderOut); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; + } + + if (pSysmanMainHeaderIn->inTotalsize == 0) { + return STATUS_UNSUCCESSFUL; + } + + if (pSysmanMainHeaderIn->inNumElements == 0) { + return STATUS_UNSUCCESSFUL; + } + + if (!validateInputBuffer(pSysmanMainHeaderIn)) { + return STATUS_UNSUCCESSFUL; + } + + uint8_t *pBufferIn = pSysmanMainHeaderIn->inBuffer; + uint8_t *pBufferOut = pSysmanMainHeaderOut->outBuffer; + uint32_t requestOffset = 0; + uint32_t responseOffset = 0; + pSysmanMainHeaderOut->outTotalSize = 0; + + for (uint32_t i = 0; i < pSysmanMainHeaderIn->inNumElements; i++) { + KmdSysman::GfxSysmanReqHeaderIn *pRequest = reinterpret_cast(pBufferIn); + KmdSysman::GfxSysmanReqHeaderOut *pResponse = reinterpret_cast(pBufferOut); + + switch (pRequest->inCommand) { + case KmdSysman::Command::Get: { + getProperty(pRequest, pResponse); + requestOffset = sizeof(KmdSysman::GfxSysmanReqHeaderIn); + responseOffset = sizeof(KmdSysman::GfxSysmanReqHeaderOut); + responseOffset += pResponse->outDataSize; + } break; + case KmdSysman::Command::Set: { + setProperty(pRequest, pResponse); + requestOffset = sizeof(KmdSysman::GfxSysmanReqHeaderIn); + requestOffset += pRequest->inDataSize; + responseOffset = sizeof(KmdSysman::GfxSysmanReqHeaderOut); + } break; + case KmdSysman::Command::RegisterEvent: { + registerEvent(pRequest, pResponse); + requestOffset = sizeof(KmdSysman::GfxSysmanReqHeaderIn); + requestOffset += pRequest->inDataSize; + responseOffset = sizeof(KmdSysman::GfxSysmanReqHeaderOut); + } break; + default: { + return STATUS_UNSUCCESSFUL; + } break; + } + + pResponse->outRequestId = pRequest->inRequestId; + pResponse->outComponent = pRequest->inComponent; + pBufferIn += requestOffset; + pBufferOut += responseOffset; + pSysmanMainHeaderOut->outTotalSize += responseOffset; + } + + pSysmanMainHeaderOut->outNumElements = pSysmanMainHeaderIn->inNumElements; + pSysmanMainHeaderOut->outStatus = KmdSysman::KmdSysmanSuccess; + + return STATUS_SUCCESS; + } +}; + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_driver.h b/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_driver.h new file mode 100644 index 0000000000..0baa8f7528 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_driver.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "level_zero/sysman/source/sysman_driver_imp.h" + +namespace L0 { +namespace ult { + +struct MockSysmanDriver : public ::L0::Sysman::SysmanDriverImp { + MockSysmanDriver() { + previousDriver = driver; + driver = this; + } + ~MockSysmanDriver() override { + driver = previousDriver; + } + + ze_result_t driverInit(ze_init_flags_t flag) override { + initCalledCount++; + return ZE_RESULT_SUCCESS; + } + + ::L0::Sysman::SysmanDriver *previousDriver = nullptr; + uint32_t initCalledCount = 0; +}; + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h b/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h new file mode 100644 index 0000000000..52e52dd5df --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/test/common/helpers/default_hw_info.h" + +#include "level_zero/sysman/source/sysman_driver_handle_imp.h" +#include "level_zero/sysman/source/windows/os_sysman_imp.h" +#include "level_zero/sysman/test/unit_tests/sources/firmware_util/mock_fw_util_fixture.h" +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_wddm.h" + +using namespace NEO; + +namespace L0 { +namespace ult { + +class PublicWddmSysmanImp : public L0::Sysman::WddmSysmanImp { + public: + using WddmSysmanImp::pFwUtilInterface; + using WddmSysmanImp::pKmdSysManager; +}; + +class SysmanDeviceFixture : public ::testing::Test { + public: + void SetUp() override { + + execEnv = new NEO::ExecutionEnvironment(); + execEnv->prepareRootDeviceEnvironments(numRootDevices); + for (auto i = 0u; i < execEnv->rootDeviceEnvironments.size(); i++) { + execEnv->rootDeviceEnvironments[i]->setHwInfoAndInitHelpers(NEO::defaultHwInfo.get()); + execEnv->rootDeviceEnvironments[i]->osInterface = std::make_unique(); + execEnv->rootDeviceEnvironments[i]->osInterface->setDriverModel(std::make_unique(*execEnv->rootDeviceEnvironments[i])); + } + + driverHandle = std::make_unique(); + driverHandle->initialize(*execEnv); + pSysmanDevice = driverHandle->sysmanDevices[0]; + + pSysmanDeviceImp = static_cast(pSysmanDevice); + pOsSysman = pSysmanDeviceImp->pOsSysman; + pWddmSysmanImp = static_cast(pOsSysman); + pWddmSysmanImp->pFwUtilInterface = new MockFwUtilInterface(); + } + + void TearDown() override { + } + + L0::Sysman::SysmanDevice *pSysmanDevice = nullptr; + L0::Sysman::SysmanDeviceImp *pSysmanDeviceImp = nullptr; + L0::Sysman::OsSysman *pOsSysman = nullptr; + PublicWddmSysmanImp *pWddmSysmanImp = nullptr; + NEO::ExecutionEnvironment *execEnv = nullptr; + std::unique_ptr driverHandle; + const uint32_t numRootDevices = 1u; +}; + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_wddm.h b/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_wddm.h new file mode 100644 index 0000000000..37c3702507 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_wddm.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/test/common/mocks/mock_wddm.h" + +namespace L0 { +namespace ult { + +class SysmanMockWddm : public NEO::WddmMock { + public: + SysmanMockWddm(NEO::RootDeviceEnvironment &rootDeviceEnvironment) : WddmMock(rootDeviceEnvironment) {} +}; + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/windows/test_sysman_driver.cpp b/level_zero/sysman/test/unit_tests/sources/windows/test_sysman_driver.cpp new file mode 100644 index 0000000000..5c62b78634 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/windows/test_sysman_driver.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_driver.h" + +#include "gtest/gtest.h" + +#include +#include + +namespace L0 { +namespace ult { + +TEST(zesInit, whenCallingZesInitThenInitializeOnDriverIsCalled) { + MockSysmanDriver driver; + + auto result = zesInit(ZE_INIT_FLAG_GPU_ONLY); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(1u, driver.initCalledCount); +} + +TEST(zesInit, whenCallingZesInitWithNoFlagsThenInitializeOnDriverIsCalled) { + MockSysmanDriver driver; + + auto result = zesInit(0); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(1u, driver.initCalledCount); +} + +TEST(zesInit, whenCallingZesInitWithoutGpuOnlyFlagThenInitializeOnDriverIsNotCalled) { + MockSysmanDriver driver; + + auto result = zesInit(ZE_INIT_FLAG_VPU_ONLY); + EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, result); + EXPECT_EQ(0u, driver.initCalledCount); +} + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/windows/test_sysman_manager.cpp b/level_zero/sysman/test/unit_tests/sources/windows/test_sysman_manager.cpp new file mode 100644 index 0000000000..5648186860 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/windows/test_sysman_manager.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/windows/os_sysman_imp.h" +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h" + +#include "gtest/gtest.h" + +namespace L0 { +namespace ult { + +class SysmanKmdManagerFixture : public ::testing::Test { + + protected: + MockKmdSysManager *pKmdSysManager = nullptr; + + void SetUp() override { + pKmdSysManager = new MockKmdSysManager; + } + void TearDown() override { + if (pKmdSysManager != nullptr) { + delete pKmdSysManager; + pKmdSysManager = nullptr; + } + } +}; + +TEST_F(SysmanKmdManagerFixture, GivenAllowSetCallsFalseWhenRequestingSingleThenPowerValueIsCorrect) { + pKmdSysManager->allowSetCalls = false; + + ze_result_t result = ZE_RESULT_SUCCESS; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + uint32_t value = 0; + memcpy_s(&value, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + value = static_cast(value); + + EXPECT_EQ(value, pKmdSysManager->mockPowerLimit1); +} + +TEST_F(SysmanKmdManagerFixture, GivenAllowSetCallsTrueWhenRequestingSingleThenPowerValueIsCorrect) { + pKmdSysManager->allowSetCalls = true; + + ze_result_t result = ZE_RESULT_SUCCESS; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + constexpr uint32_t increase = 500; + uint32_t iniitialPl1 = pKmdSysManager->mockPowerLimit1; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = 0; + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + uint32_t value = 0; + memcpy_s(&value, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + value = static_cast(value); + + EXPECT_EQ(value, iniitialPl1); + + value += increase; + + request.commandId = KmdSysman::Command::Set; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = sizeof(uint32_t); + + memcpy_s(request.dataBuffer, sizeof(uint32_t), &value, sizeof(uint32_t)); + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = 0; + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + value = 0; + memcpy_s(&value, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + value = static_cast(value); + + EXPECT_EQ(value, (iniitialPl1 + increase)); +} + +TEST_F(SysmanKmdManagerFixture, GivenAllowSetCallsFalseAndCorruptedDataWhenRequestingSingleThenCallFails) { + pKmdSysManager->allowSetCalls = false; + + ze_result_t result = ZE_RESULT_SUCCESS; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = sizeof(uint64_t); + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); + + request.commandId = KmdSysman::Command::MaxCommands; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = 0; + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::MaxComponents; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = 0; + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::MaxPowerRequests; + request.dataSize = 0; + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); +} + +TEST_F(SysmanKmdManagerFixture, GivenAllowSetCallsTrueAndCorruptedDataWhenRequestingSingleThenCallFails) { + pKmdSysManager->allowSetCalls = true; + + ze_result_t result = ZE_RESULT_SUCCESS; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + uint32_t value = 0; + + request.commandId = KmdSysman::Command::Set; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = 0; + memcpy_s(request.dataBuffer, sizeof(uint32_t), &value, sizeof(uint32_t)); + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); + + request.commandId = KmdSysman::Command::MaxCommands; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = sizeof(uint32_t); + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::MaxComponents; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::MaxPowerRequests; + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_NE(ZE_RESULT_SUCCESS, result); +} + +TEST_F(SysmanKmdManagerFixture, GivenAllowSetCallsFalseAndTDROccuredWhenRequestSingleIsCalledThenErrorDeviceLostIsReturned) { + pKmdSysManager->allowSetCalls = false; + pKmdSysManager->mockEscapeResult = STATUS_DEVICE_REMOVED; + + ze_result_t result = ZE_RESULT_SUCCESS; + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + uint32_t value = 0; + + request.commandId = KmdSysman::Command::Set; + request.componentId = KmdSysman::Component::PowerComponent; + request.requestId = KmdSysman::Requests::Power::CurrentPowerLimit1; + request.dataSize = 0; + memcpy_s(request.dataBuffer, sizeof(uint32_t), &value, sizeof(uint32_t)); + + result = pKmdSysManager->requestSingle(request, response); + + EXPECT_EQ(ZE_RESULT_ERROR_DEVICE_LOST, result); +} + +TEST_F(SysmanKmdManagerFixture, GivenAllowSetCallsFalseAndTDROccuredWhenRequestMultipleIsCalledThenErrorDeviceLostIsReturned) { + pKmdSysManager->allowSetCalls = false; + pKmdSysManager->mockEscapeResult = STATUS_DEVICE_REMOVED; + + ze_result_t result = ZE_RESULT_SUCCESS; + std::vector vRequests = {}; + std::vector vResponses = {}; + KmdSysman::RequestProperty request = {}; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::MemoryComponent; + + request.requestId = KmdSysman::Requests::Memory::MaxBandwidth; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Memory::CurrentBandwidthRead; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Memory::CurrentBandwidthWrite; + vRequests.push_back(request); + + result = pKmdSysManager->requestMultiple(vRequests, vResponses); + EXPECT_EQ(ZE_RESULT_ERROR_DEVICE_LOST, result); +} + +} // namespace ult +} // namespace L0