diff --git a/level_zero/sysman/source/temperature/windows/os_temperature_imp.cpp b/level_zero/sysman/source/temperature/windows/os_temperature_imp.cpp index 2eae4de0f5..554b68d22b 100644 --- a/level_zero/sysman/source/temperature/windows/os_temperature_imp.cpp +++ b/level_zero/sysman/source/temperature/windows/os_temperature_imp.cpp @@ -7,25 +7,142 @@ #include "level_zero/sysman/source/temperature/windows/os_temperature_imp.h" +#include "level_zero/sysman/source/windows/kmd_sys_manager.h" + namespace L0 { namespace Sysman { ze_result_t WddmTemperatureImp::getProperties(zes_temp_properties_t *pProperties) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + uint32_t value = 0; + std::vector vRequests = {}; + std::vector vResponses = {}; + KmdSysman::RequestProperty request = {}; + + pProperties->type = this->type; + pProperties->onSubdevice = false; + pProperties->subdeviceId = 0; + + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::TemperatureComponent; + + switch (this->type) { + case ZES_TEMP_SENSORS_GLOBAL: + request.paramInfo = KmdSysman::TemperatureDomainsType::TemperatureDomainPackage; + break; + case ZES_TEMP_SENSORS_GPU: + request.paramInfo = KmdSysman::TemperatureDomainsType::TemperatureDomainDGPU; + break; + case ZES_TEMP_SENSORS_MEMORY: + request.paramInfo = KmdSysman::TemperatureDomainsType::TemperatureDomainHBM; + break; + default: + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + break; + } + + request.requestId = KmdSysman::Requests::Temperature::TempCriticalEventSupported; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Temperature::TempThreshold1EventSupported; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Temperature::TempThreshold2EventSupported; + vRequests.push_back(request); + + request.requestId = KmdSysman::Requests::Temperature::MaxTempSupported; + 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->isCriticalTempSupported, sizeof(ze_bool_t), vResponses[0].dataBuffer, sizeof(ze_bool_t)); + } + + if (vResponses[1].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->isThreshold1Supported, sizeof(ze_bool_t), vResponses[1].dataBuffer, sizeof(ze_bool_t)); + } + + if (vResponses[2].returnCode == KmdSysman::Success) { + memcpy_s(&pProperties->isThreshold2Supported, sizeof(ze_bool_t), vResponses[2].dataBuffer, sizeof(ze_bool_t)); + } + + if (vResponses[3].returnCode == KmdSysman::Success) { + memcpy_s(&value, sizeof(uint32_t), vResponses[3].dataBuffer, sizeof(uint32_t)); + pProperties->maxTemperature = static_cast(value); + } + + return ZE_RESULT_SUCCESS; } ze_result_t WddmTemperatureImp::getSensorTemperature(double *pTemperature) { - 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::TemperatureComponent; + request.requestId = KmdSysman::Requests::Temperature::CurrentTemperature; + + switch (type) { + case ZES_TEMP_SENSORS_GLOBAL: + request.paramInfo = KmdSysman::TemperatureDomainsType::TemperatureDomainPackage; + break; + case ZES_TEMP_SENSORS_GPU: + request.paramInfo = KmdSysman::TemperatureDomainsType::TemperatureDomainDGPU; + break; + case ZES_TEMP_SENSORS_MEMORY: + request.paramInfo = KmdSysman::TemperatureDomainsType::TemperatureDomainHBM; + break; + default: + *pTemperature = 0; + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + break; + } + + status = pKmdSysManager->requestSingle(request, response); + + if (status != ZE_RESULT_SUCCESS) { + return status; + } + + uint32_t value = 0; + memcpy_s(&value, sizeof(uint32_t), response.dataBuffer, sizeof(uint32_t)); + *pTemperature = static_cast(value); + + return status; } bool WddmTemperatureImp::isTempModuleSupported() { - return false; + if ((type == ZES_TEMP_SENSORS_GLOBAL_MIN) || (type == ZES_TEMP_SENSORS_GPU_MIN)) { + return false; + } + KmdSysman::RequestProperty request; + KmdSysman::ResponseProperty response; + + request.paramInfo = static_cast(type); + request.commandId = KmdSysman::Command::Get; + request.componentId = KmdSysman::Component::TemperatureComponent; + request.requestId = KmdSysman::Requests::Temperature::CurrentTemperature; + + return (pKmdSysManager->requestSingle(request, response) == ZE_RESULT_SUCCESS); } -WddmTemperatureImp::WddmTemperatureImp(OsSysman *pOsSysman) {} +void WddmTemperatureImp::setSensorType(zes_temp_sensors_t sensorType) { + type = sensorType; +} + +WddmTemperatureImp::WddmTemperatureImp(OsSysman *pOsSysman) { + WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); + pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); +} std::unique_ptr OsTemperature::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_temp_sensors_t sensorType) { std::unique_ptr pWddmTemperatureImp = std::make_unique(pOsSysman); + pWddmTemperatureImp->setSensorType(sensorType); return std::move(pWddmTemperatureImp); } diff --git a/level_zero/sysman/source/temperature/windows/os_temperature_imp.h b/level_zero/sysman/source/temperature/windows/os_temperature_imp.h index bc1e33697b..0572f78ed7 100644 --- a/level_zero/sysman/source/temperature/windows/os_temperature_imp.h +++ b/level_zero/sysman/source/temperature/windows/os_temperature_imp.h @@ -19,10 +19,14 @@ class WddmTemperatureImp : public OsTemperature, NEO::NonCopyableOrMovableClass ze_result_t getProperties(zes_temp_properties_t *pProperties) override; ze_result_t getSensorTemperature(double *pTemperature) override; bool isTempModuleSupported() override; - + void setSensorType(zes_temp_sensors_t sensorType); WddmTemperatureImp(OsSysman *pOsSysman); WddmTemperatureImp() = default; ~WddmTemperatureImp() override = default; + + protected: + KmdSysManager *pKmdSysManager = nullptr; + zes_temp_sensors_t type = ZES_TEMP_SENSORS_GLOBAL; }; } // namespace Sysman diff --git a/level_zero/sysman/test/unit_tests/sources/temperature/windows/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/temperature/windows/CMakeLists.txt new file mode 100644 index 0000000000..f36bf2f0da --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/temperature/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}/mock_temperature.h + ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_temperature.cpp + ) +endif() diff --git a/level_zero/sysman/test/unit_tests/sources/temperature/windows/mock_temperature.h b/level_zero/sysman/test/unit_tests/sources/temperature/windows/mock_temperature.h new file mode 100644 index 0000000000..0829a82db8 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/temperature/windows/mock_temperature.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "level_zero/sysman/source/temperature/temperature_imp.h" +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_kmd_sys_manager.h" + +namespace L0 { +namespace ult { + +constexpr uint32_t temperatureHandleComponentCount = 3u; + +struct TemperatureKmdSysManager : public MockKmdSysManager { + uint32_t mockTempDomainCount = temperatureHandleComponentCount; + uint32_t mockTempGlobal = 26; + uint32_t mockTempGPU = 25; + uint32_t mockTempMemory = 23; + uint32_t mockMaxTemperature = 100; + zes_temp_sensors_t mockSensorTypes[3] = {ZES_TEMP_SENSORS_GLOBAL, ZES_TEMP_SENSORS_GPU, ZES_TEMP_SENSORS_MEMORY}; + + void getTemperatureProperty(KmdSysman::GfxSysmanReqHeaderIn *pRequest, KmdSysman::GfxSysmanReqHeaderOut *pResponse) override { + uint8_t *pBuffer = reinterpret_cast(pResponse); + pBuffer += sizeof(KmdSysman::GfxSysmanReqHeaderOut); + + KmdSysman::TemperatureDomainsType domain = static_cast(pRequest->inCommandParam); + + if (domain < KmdSysman::TemperatureDomainsType::TemperatureDomainPackage || domain >= KmdSysman::TemperatureDomainsType::TempetatureMaxDomainTypes) { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + return; + } + + switch (pRequest->inRequestId) { + case KmdSysman::Requests::Temperature::NumTemperatureDomains: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockTempDomainCount; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Temperature::TempCriticalEventSupported: + case KmdSysman::Requests::Temperature::TempThreshold1EventSupported: + case KmdSysman::Requests::Temperature::TempThreshold2EventSupported: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Temperature::MaxTempSupported: { + uint32_t *pValue = reinterpret_cast(pBuffer); + *pValue = mockMaxTemperature; + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + case KmdSysman::Requests::Temperature::CurrentTemperature: { + uint32_t *pValue = reinterpret_cast(pBuffer); + switch (domain) { + case KmdSysman::TemperatureDomainsType::TemperatureDomainPackage: { + *pValue = mockTempGlobal; + } break; + case KmdSysman::TemperatureDomainsType::TemperatureDomainDGPU: { + *pValue = mockTempGPU; + } break; + case KmdSysman::TemperatureDomainsType::TemperatureDomainHBM: { + *pValue = mockTempMemory; + } break; + } + pResponse->outReturnCode = KmdSysman::KmdSysmanSuccess; + pResponse->outDataSize = sizeof(uint32_t); + } break; + default: { + pResponse->outDataSize = 0; + pResponse->outReturnCode = KmdSysman::KmdSysmanFail; + } break; + } + } +}; + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/temperature/windows/test_zes_temperature.cpp b/level_zero/sysman/test/unit_tests/sources/temperature/windows/test_zes_temperature.cpp new file mode 100644 index 0000000000..db7b9c7f95 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/temperature/windows/test_zes_temperature.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2020-2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/sysman/source/temperature/windows/os_temperature_imp.h" +#include "level_zero/sysman/test/unit_tests/sources/temperature/windows/mock_temperature.h" +#include "level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h" + +namespace L0 { +namespace ult { + +class SysmanDeviceTemperatureFixture : public SysmanDeviceFixture { + + protected: + std::unique_ptr pKmdSysManager = nullptr; + L0::Sysman::KmdSysManager *pOriginalKmdSysManager = nullptr; + std::vector deviceHandles; + void SetUp() override { + SysmanDeviceFixture::SetUp(); + + pKmdSysManager.reset(new TemperatureKmdSysManager); + pKmdSysManager->allowSetCalls = true; + + pOriginalKmdSysManager = pWddmSysmanImp->pKmdSysManager; + pWddmSysmanImp->pKmdSysManager = pKmdSysManager.get(); + + pSysmanDeviceImp->pTempHandleContext->handleList.clear(); + } + void TearDown() override { + pWddmSysmanImp->pKmdSysManager = pOriginalKmdSysManager; + SysmanDeviceFixture::TearDown(); + } + + std::vector getTempHandles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +TEST_F(SysmanDeviceTemperatureFixture, GivenComponentCountZeroWhenEnumeratingTemperatureSensorsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { + uint32_t count = 0; + EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, temperatureHandleComponentCount); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenInvalidComponentCountWhenEnumeratingTemperatureSensorsThenValidCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { + uint32_t count = 0; + EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, temperatureHandleComponentCount); + + count = count + 1; + EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, temperatureHandleComponentCount); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenComponentCountZeroWhenEnumeratingTemperatureSensorsThenValidPowerHandlesIsReturned) { + uint32_t count = 0; + EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, nullptr), ZE_RESULT_SUCCESS); + EXPECT_EQ(count, temperatureHandleComponentCount); + + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumTemperatureSensors(pSysmanDevice->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + for (auto handle : handles) { + EXPECT_NE(handle, nullptr); + } +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidPowerHandleWhenGettingTemperaturePropertiesAllowSetToTrueThenCallSucceeds) { + auto handles = getTempHandles(temperatureHandleComponentCount); + uint32_t sensorTypeIndex = 0; + for (auto handle : handles) { + zes_temp_properties_t properties; + + ze_result_t result = zesTemperatureGetProperties(handle, &properties); + + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_FALSE(properties.onSubdevice); + EXPECT_EQ(properties.subdeviceId, 0); + EXPECT_FALSE(properties.isCriticalTempSupported); + EXPECT_FALSE(properties.isThreshold1Supported); + EXPECT_FALSE(properties.isThreshold2Supported); + EXPECT_EQ(properties.maxTemperature, pKmdSysManager->mockMaxTemperature); + EXPECT_EQ(properties.type, pKmdSysManager->mockSensorTypes[sensorTypeIndex++]); + } +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingMemoryTemperatureThenValidTemperatureReadingsRetrieved) { + auto handles = getTempHandles(temperatureHandleComponentCount); + double temperature; + ASSERT_EQ(ZE_RESULT_SUCCESS, zesTemperatureGetState(handles[ZES_TEMP_SENSORS_MEMORY], &temperature)); + EXPECT_EQ(temperature, static_cast(pKmdSysManager->mockTempMemory)); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingGPUTemperatureThenValidTemperatureReadingsRetrieved) { + auto handles = getTempHandles(temperatureHandleComponentCount); + double temperature; + ASSERT_EQ(ZE_RESULT_SUCCESS, zesTemperatureGetState(handles[ZES_TEMP_SENSORS_GPU], &temperature)); + EXPECT_EQ(temperature, static_cast(pKmdSysManager->mockTempGPU)); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingGlobalTemperatureThenValidTemperatureReadingsRetrieved) { + auto handles = getTempHandles(temperatureHandleComponentCount); + double temperature; + ASSERT_EQ(ZE_RESULT_SUCCESS, zesTemperatureGetState(handles[ZES_TEMP_SENSORS_GLOBAL], &temperature)); + EXPECT_EQ(temperature, static_cast(pKmdSysManager->mockTempGlobal)); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingUnsupportedSensorsTemperatureThenUnsupportedReturned) { + auto pTemperatureImpMemory = std::make_unique(pOsSysman, false, 0, ZES_TEMP_SENSORS_GLOBAL_MIN); + auto pWddmTemperatureImp = static_cast(pTemperatureImpMemory->pOsTemperature.get()); + double pTemperature = 0; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pWddmTemperatureImp->getSensorTemperature(&pTemperature)); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingTemperatureConfigThenUnsupportedIsReturned) { + auto handles = getTempHandles(temperatureHandleComponentCount); + for (auto handle : handles) { + zes_temp_config_t config = {}; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesTemperatureGetConfig(handle, &config)); + } +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenSettingTemperatureConfigThenUnsupportedIsReturned) { + auto handles = getTempHandles(temperatureHandleComponentCount); + for (auto handle : handles) { + zes_temp_config_t config = {}; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesTemperatureSetConfig(handle, &config)); + } +} + +} // namespace ult +} // namespace L0