diff --git a/level_zero/tools/source/sysman/linux/CMakeLists.txt b/level_zero/tools/source/sysman/linux/CMakeLists.txt index e281caf263..ec9cd9c915 100644 --- a/level_zero/tools/source/sysman/linux/CMakeLists.txt +++ b/level_zero/tools/source/sysman/linux/CMakeLists.txt @@ -6,9 +6,11 @@ set(L0_SRCS_TOOLS_SYSMAN_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_sysman_imp.h - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_sysman_imp.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/fs_access.cpp) + ${CMAKE_CURRENT_SOURCE_DIR}/os_sysman_imp.h + ${CMAKE_CURRENT_SOURCE_DIR}/os_sysman_imp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/fs_access.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/pmt.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/pmt.h) if(UNIX) target_sources(${L0_STATIC_LIB_NAME} @@ -17,7 +19,6 @@ target_sources(${L0_STATIC_LIB_NAME} ) endif() -add_subdirectories() # Make our source files visible to parent set_property(GLOBAL PROPERTY L0_SRCS_TOOLS_SYSMAN_LINUX ${L0_SRCS_TOOLS_SYSMAN_LINUX}) diff --git a/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp b/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp index b06f067b02..3a36ab2669 100644 --- a/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp +++ b/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp @@ -31,6 +31,10 @@ ze_result_t LinuxSysmanImp::init() { pSysfsAccess = SysfsAccess::create(myDeviceName); UNRECOVERABLE_IF(nullptr == pSysfsAccess); + pPmt = new PlatformMonitoringTech(); + UNRECOVERABLE_IF(nullptr == pPmt); + pPmt->init(myDeviceName, pFsAccess); + return ZE_RESULT_SUCCESS; } @@ -54,6 +58,11 @@ NEO::Drm &LinuxSysmanImp::getDrm() { return *pDrm; } +PlatformMonitoringTech &LinuxSysmanImp::getPlatformMonitoringTechAccess() { + UNRECOVERABLE_IF(nullptr == pPmt); + return *pPmt; +} + LinuxSysmanImp::LinuxSysmanImp(SysmanImp *pParentSysmanImp) { this->pParentSysmanImp = pParentSysmanImp; } @@ -71,6 +80,10 @@ LinuxSysmanImp::~LinuxSysmanImp() { delete pFsAccess; pFsAccess = nullptr; } + if (nullptr != pPmt) { + delete pPmt; + pPmt = nullptr; + } } OsSysman *OsSysman::create(SysmanImp *pParentSysmanImp) { diff --git a/level_zero/tools/source/sysman/linux/os_sysman_imp.h b/level_zero/tools/source/sysman/linux/os_sysman_imp.h index df4bc87d6a..f53b987960 100644 --- a/level_zero/tools/source/sysman/linux/os_sysman_imp.h +++ b/level_zero/tools/source/sysman/linux/os_sysman_imp.h @@ -11,6 +11,7 @@ #include "level_zero/core/source/device/device.h" #include "level_zero/tools/source/sysman/linux/fs_access.h" +#include "level_zero/tools/source/sysman/linux/pmt.h" #include "level_zero/tools/source/sysman/sysman_imp.h" namespace L0 { @@ -26,6 +27,7 @@ class LinuxSysmanImp : public OsSysman, public NEO::NonCopyableClass { ProcfsAccess &getProcfsAccess(); SysfsAccess &getSysfsAccess(); NEO::Drm &getDrm(); + PlatformMonitoringTech &getPlatformMonitoringTechAccess(); private: LinuxSysmanImp() = delete; @@ -34,6 +36,7 @@ class LinuxSysmanImp : public OsSysman, public NEO::NonCopyableClass { ProcfsAccess *pProcfsAccess = nullptr; SysfsAccess *pSysfsAccess = nullptr; NEO::Drm *pDrm = nullptr; + PlatformMonitoringTech *pPmt = nullptr; }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/linux/pmt.cpp b/level_zero/tools/source/sysman/linux/pmt.cpp new file mode 100644 index 0000000000..fef5d013d5 --- /dev/null +++ b/level_zero/tools/source/sysman/linux/pmt.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/tools/source/sysman/linux/pmt.h" + +#include "shared/source/debug_settings/debug_settings_manager.h" + +#include +#include +#include +#include + +namespace L0 { +const std::string PlatformMonitoringTech::baseTelemDevice("/dev/telem"); +const std::string PlatformMonitoringTech::baseTelemSysFS("/sys/class/pmt_telem/telem"); + +void PlatformMonitoringTech::init(const std::string &deviceName, FsAccess *pFsAccess) { + pmtSupported = false; + + std::string deviceNumber("1"); // Temporarily hardcoded + std::string telemetryDeviceEntry = baseTelemDevice + deviceNumber; + if (!pFsAccess->fileExists(telemetryDeviceEntry)) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Telemetry support not available. No file %s\n", telemetryDeviceEntry.c_str()); + return; + } + + std::string guid; + std::string guidPath = baseTelemSysFS + deviceNumber + std::string("/guid"); + ze_result_t result = pFsAccess->read(guidPath, guid); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Telemetry sysfs entry not available %s\n", guidPath.c_str()); + return; + } + + std::string sizePath = baseTelemSysFS + deviceNumber + std::string("/size"); + result = pFsAccess->read(sizePath, size); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Telemetry sysfs entry not available %s\n", sizePath.c_str()); + return; + } + + std::string offsetPath = baseTelemSysFS + deviceNumber + std::string("/offset"); + result = pFsAccess->read(offsetPath, baseOffset); + if (ZE_RESULT_SUCCESS != result) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Telemetry sysfs entry not available %s\n", offsetPath.c_str()); + return; + } + + int fd = open(static_cast(telemetryDeviceEntry.c_str()), O_RDONLY); + if (fd == -1) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Failure opening telemetry file %s : %s \n", telemetryDeviceEntry.c_str(), strerror(errno)); + return; + } + + mappedMemory = static_cast(mmap(nullptr, static_cast(size), PROT_READ, MAP_SHARED, fd, 0)); + if (mappedMemory == MAP_FAILED) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Failure mapping telemetry file %s : %s \n", telemetryDeviceEntry.c_str(), strerror(errno)); + close(fd); + return; + } + + if (close(fd) == -1) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Failure closing telemetry file %s : %s \n", telemetryDeviceEntry.c_str(), strerror(errno)); + munmap(mappedMemory, size); + return; + } + + mappedMemory += baseOffset; + pmtSupported = true; +} + +PlatformMonitoringTech::~PlatformMonitoringTech() { + if (mappedMemory != nullptr) { + munmap(mappedMemory - baseOffset, size); + } +} + +} // namespace L0 diff --git a/level_zero/tools/source/sysman/linux/pmt.h b/level_zero/tools/source/sysman/linux/pmt.h new file mode 100644 index 0000000000..e94d8903f0 --- /dev/null +++ b/level_zero/tools/source/sysman/linux/pmt.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/helpers/non_copyable_or_moveable.h" + +#include "level_zero/tools/source/sysman/linux/fs_access.h" + +#include + +namespace L0 { + +class PlatformMonitoringTech : public NEO::NonCopyableClass { + public: + PlatformMonitoringTech() = default; + virtual ~PlatformMonitoringTech(); + MOCKABLE_VIRTUAL void init(const std::string &deviceName, FsAccess *pFsAccess); + template + ze_result_t readValue(const std::string key, ReadType &value); + bool isPmtSupported() { return pmtSupported; } + + protected: + bool pmtSupported = false; + char *mappedMemory = nullptr; + + private: + static const std::string baseTelemDevice; + static const std::string baseTelemSysFS; + uint64_t size = 0; + uint64_t baseOffset = 0; +}; + +const std::map keyOffsetMap = { + {"PACKAGE_ENERGY", 0x400}, + {"COMPUTE_TEMPERATURES", 0x68}, + {"SOC_TEMPERATURES", 0x60}, + {"CORE_TEMPERATURES", 0x6c}}; + +template +ze_result_t PlatformMonitoringTech::readValue(const std::string key, ReadType &value) { + if (!pmtSupported) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + auto offset = keyOffsetMap.find(key); + if (offset == keyOffsetMap.end()) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + value = *reinterpret_cast(mappedMemory + offset->second); + return ZE_RESULT_SUCCESS; +} + +} // namespace L0 diff --git a/level_zero/tools/source/sysman/power/linux/CMakeLists.txt b/level_zero/tools/source/sysman/power/linux/CMakeLists.txt index c952f28512..5d5f24167f 100644 --- a/level_zero/tools/source/sysman/power/linux/CMakeLists.txt +++ b/level_zero/tools/source/sysman/power/linux/CMakeLists.txt @@ -5,8 +5,8 @@ # set(L0_SRCS_TOOLS_SYSMAN_POWER_LINUX - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_power_imp.cpp - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_power_imp.h + ${CMAKE_CURRENT_SOURCE_DIR}/os_power_imp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/os_power_imp.h ) if(UNIX) diff --git a/level_zero/tools/source/sysman/power/linux/os_power_imp.cpp b/level_zero/tools/source/sysman/power/linux/os_power_imp.cpp index c21c96fba9..ed773d4871 100644 --- a/level_zero/tools/source/sysman/power/linux/os_power_imp.cpp +++ b/level_zero/tools/source/sysman/power/linux/os_power_imp.cpp @@ -7,15 +7,12 @@ #include "level_zero/tools/source/sysman/power/linux/os_power_imp.h" +#include "level_zero/tools/source/sysman/linux/pmt.h" + #include "sysman/linux/os_sysman_imp.h" namespace L0 { - -ze_result_t LinuxPowerImp::getEnergyCounter(uint64_t &energy) { - - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; -} - +constexpr uint64_t convertJouleToMicroJoule = 1000000u; ze_result_t LinuxPowerImp::getEnergyThreshold(zet_energy_threshold_t *pThreshold) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; @@ -25,14 +22,21 @@ ze_result_t LinuxPowerImp::setEnergyThreshold(double threshold) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } - -LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman) { - LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); - pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); +ze_result_t LinuxPowerImp::getEnergyCounter(uint64_t &energy) { + const std::string key("PACKAGE_ENERGY"); + ze_result_t result = pPmt->readValue(key, energy); + // PMT will return in joules and need to convert into microjoules + energy = energy * convertJouleToMicroJoule; + return result; } bool LinuxPowerImp::isPowerModuleSupported() { - return false; + return pPmt->isPmtSupported(); +} +LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman) { + LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); + pPmt = &pLinuxSysmanImp->getPlatformMonitoringTechAccess(); } OsPower *OsPower::create(OsSysman *pOsSysman) { diff --git a/level_zero/tools/source/sysman/power/linux/os_power_imp.h b/level_zero/tools/source/sysman/power/linux/os_power_imp.h index 749146a3cc..e2d591f9ad 100644 --- a/level_zero/tools/source/sysman/power/linux/os_power_imp.h +++ b/level_zero/tools/source/sysman/power/linux/os_power_imp.h @@ -13,6 +13,7 @@ namespace L0 { class SysfsAccess; +class PlatformMonitoringTech; class LinuxPowerImp : public OsPower, public NEO::NonCopyableClass { public: ze_result_t getEnergyCounter(uint64_t &energy) override; @@ -25,5 +26,6 @@ class LinuxPowerImp : public OsPower, public NEO::NonCopyableClass { protected: SysfsAccess *pSysfsAccess = nullptr; + PlatformMonitoringTech *pPmt = nullptr; }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/temperature/linux/CMakeLists.txt b/level_zero/tools/source/sysman/temperature/linux/CMakeLists.txt index 55c40ef634..26d7e93bba 100644 --- a/level_zero/tools/source/sysman/temperature/linux/CMakeLists.txt +++ b/level_zero/tools/source/sysman/temperature/linux/CMakeLists.txt @@ -5,8 +5,8 @@ # set(L0_SRCS_TOOLS_SYSMAN_TEMPERATURE_LINUX - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_temperature_imp.cpp - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_temperature_imp.h + ${CMAKE_CURRENT_SOURCE_DIR}/os_temperature_imp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/os_temperature_imp.h ) if(UNIX) @@ -16,4 +16,4 @@ if(UNIX) endif() # Make our source files visible to parent -set_property(GLOBAL PROPERTY L0_SRCS_TOOLS_SYSMAN_TEMPERATURE_LINUX ${L0_SRCS_TOOLS_SYSMAN_TEMPERATURE_LINUX}) \ No newline at end of file +set_property(GLOBAL PROPERTY L0_SRCS_TOOLS_SYSMAN_TEMPERATURE_LINUX ${L0_SRCS_TOOLS_SYSMAN_TEMPERATURE_LINUX}) diff --git a/level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.cpp b/level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.cpp index d3158905d6..376df7c7c4 100644 --- a/level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.cpp +++ b/level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.cpp @@ -7,14 +7,71 @@ #include "level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h" +#include "level_zero/tools/source/sysman/linux/pmt.h" + +#include "sysman/linux/os_sysman_imp.h" + namespace L0 { +constexpr uint64_t numSocTemperatureEntries = 7; +constexpr uint32_t numCoreTemperatureEntries = 4; ze_result_t LinuxTemperatureImp::getSensorTemperature(double *pTemperature) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + uint64_t socTemperature = 0; + uint32_t computeTemperature = 0, coreTemperature = 0; + std::string key("COMPUTE_TEMPERATURES"); + ze_result_t result = pPmt->readValue(key, computeTemperature); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + + // GT temperature could be read via 8th to 15th bit in the value read in temperature + computeTemperature = (computeTemperature >> 8) & 0xff; + + switch (type) { + case ZET_TEMP_SENSORS_GPU: + *pTemperature = static_cast(computeTemperature); + break; + case ZET_TEMP_SENSORS_GLOBAL: + key = "SOC_TEMPERATURES"; + result = pPmt->readValue(key, socTemperature); + if (result != ZE_RESULT_SUCCESS) { + break; + } + + uint64_t socTemperatureList[numSocTemperatureEntries]; + for (uint64_t count = 0; count < numSocTemperatureEntries; count++) { + socTemperatureList[count] = (socTemperature >> (8 * count)) & 0xff; + } + // Assign socTemperature so that it contains the maximum temperature provided by all SOC components + socTemperature = *std::max_element(socTemperatureList, socTemperatureList + numSocTemperatureEntries); + + key = "CORE_TEMPERATURES"; + result = pPmt->readValue(key, coreTemperature); + if (result != ZE_RESULT_SUCCESS) { + break; + } + + uint32_t coreTemperatureList[numCoreTemperatureEntries]; + for (uint64_t count = 0; count < numCoreTemperatureEntries; count++) { + coreTemperatureList[count] = (coreTemperature >> (8 * count)) & 0xff; + } + // Assign coreTemperature so that it contains the maximum temperature provided by all SOC components + coreTemperature = *std::max_element(coreTemperatureList, coreTemperatureList + numCoreTemperatureEntries); + + *pTemperature = static_cast(std::max({static_cast(computeTemperature), + static_cast(coreTemperature), socTemperature})); + break; + default: + *pTemperature = 0; + result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + break; + } + + return result; } bool LinuxTemperatureImp::isTempModuleSupported() { - return false; + return pPmt->isPmtSupported(); } void LinuxTemperatureImp::setSensorType(zet_temp_sensors_t sensorType) { @@ -24,6 +81,7 @@ void LinuxTemperatureImp::setSensorType(zet_temp_sensors_t sensorType) { LinuxTemperatureImp::LinuxTemperatureImp(OsSysman *pOsSysman) { LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); + pPmt = &pLinuxSysmanImp->getPlatformMonitoringTechAccess(); } OsTemperature *OsTemperature::create(OsSysman *pOsSysman) { @@ -31,4 +89,4 @@ OsTemperature *OsTemperature::create(OsSysman *pOsSysman) { return static_cast(pLinuxTemperatureImp); } -} // namespace L0 \ No newline at end of file +} // namespace L0 diff --git a/level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h b/level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h index 52575e9d30..e4b1aaff8c 100644 --- a/level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h +++ b/level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h @@ -10,10 +10,10 @@ #include "level_zero/tools/source/sysman/temperature/os_temperature.h" -#include "sysman/linux/os_sysman_imp.h" - namespace L0 { +class SysfsAccess; +class PlatformMonitoringTech; class LinuxTemperatureImp : public OsTemperature, public NEO::NonCopyableClass { public: ze_result_t getSensorTemperature(double *pTemperature) override; @@ -25,6 +25,7 @@ class LinuxTemperatureImp : public OsTemperature, public NEO::NonCopyableClass { protected: SysfsAccess *pSysfsAccess = nullptr; + PlatformMonitoringTech *pPmt = nullptr; zet_temp_sensors_t type; }; -} // namespace L0 \ No newline at end of file +} // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/CMakeLists.txt b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/CMakeLists.txt index 6571c9bd5b..862c324dd0 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/CMakeLists.txt +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/CMakeLists.txt @@ -8,7 +8,7 @@ if(UNIX) target_sources(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/test_sysman_power.cpp - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/mock_sysfs_power.h + ${CMAKE_CURRENT_SOURCE_DIR}/test_sysman_power.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_power.h ) endif() diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h index 8d7569cceb..684a83a6d5 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/mock_sysfs_power.h @@ -6,13 +6,43 @@ */ #pragma once +#include "shared/source/helpers/string.h" + +#include "level_zero/core/test/unit_tests/mock.h" #include "level_zero/tools/source/sysman/power/linux/os_power_imp.h" +#include "sysman/linux/pmt.h" +#include "sysman/power/power_imp.h" +#include "sysman/sysman_imp.h" + namespace L0 { namespace ult { +constexpr uint64_t setEnergyCounter = 83456; +constexpr uint64_t offset = 0x400; +constexpr uint64_t mappedLength = 2048; +class PowerPmt : public PlatformMonitoringTech {}; + +template <> +struct Mock : public PlatformMonitoringTech { + Mock() = default; + ~Mock() override { + delete mappedMemory; + mappedMemory = nullptr; + } + + void init(const std::string &deviceName, FsAccess *pFsAccess) override { + mappedMemory = new char[mappedLength]; + // fill memmory with 8 bytes of data using setEnergyCoutner at offset = 0x400 + for (uint64_t i = 0; i < sizeof(uint64_t); i++) { + mappedMemory[offset + i] = static_cast((setEnergyCounter >> 8 * i) & 0xff); + } + pmtSupported = true; + } +}; class PublicLinuxPowerImp : public L0::LinuxPowerImp { public: + using LinuxPowerImp::pPmt; using LinuxPowerImp::pSysfsAccess; }; } // namespace ult diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_sysman_power.cpp b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_sysman_power.cpp index ec0aea23bc..920be28727 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_sysman_power.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_sysman_power.cpp @@ -6,6 +6,7 @@ */ #include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" +#include "level_zero/tools/source/sysman/power/linux/os_power_imp.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -14,15 +15,19 @@ #include "sysman/power/power_imp.h" using ::testing::_; +using ::testing::NiceMock; namespace L0 { namespace ult { +constexpr uint64_t convertJouleToMicroJoule = 1000000u; class SysmanPowerFixture : public DeviceFixture, public ::testing::Test { protected: std::unique_ptr sysmanImp; zet_sysman_handle_t hSysman; + zet_sysman_pwr_handle_t hSysmanPowerHandle; + Mock *pPmt = nullptr; PowerImp *pPowerImp = nullptr; PublicLinuxPowerImp linuxPowerImp; @@ -31,44 +36,40 @@ class SysmanPowerFixture : public DeviceFixture, public ::testing::Test { DeviceFixture::SetUp(); sysmanImp = std::make_unique(device->toHandle()); + pPmt = new NiceMock>; OsPower *pOsPower = nullptr; + FsAccess *pFsAccess = nullptr; + const std::string deviceName("device"); + pPmt->init(deviceName, pFsAccess); + linuxPowerImp.pPmt = pPmt; pOsPower = static_cast(&linuxPowerImp); pPowerImp = new PowerImp(); pPowerImp->pOsPower = pOsPower; + pPowerImp->init(); + sysmanImp->pPowerHandleContext->handleList.push_back(pPowerImp); hSysman = sysmanImp->toHandle(); + hSysmanPowerHandle = pPowerImp->toHandle(); } void TearDown() override { - //pOsPower is static_cast of LinuxPowerImp class , hence in cleanup assign to nullptr - if (pPowerImp != nullptr) { - pPowerImp->pOsPower = nullptr; - delete pPowerImp; - pPowerImp = nullptr; + // pOsPower is static_cast of LinuxPowerImp class , hence in cleanup assign to nullptr + pPowerImp->pOsPower = nullptr; + + if (pPmt != nullptr) { + delete pPmt; + pPmt = nullptr; } DeviceFixture::TearDown(); } }; -TEST_F(SysmanPowerFixture, GivenValidOSPowerHandleWhenCheckingForPowerSupportThenExpectFalseToBeReturned) { - EXPECT_FALSE(pPowerImp->pOsPower->isPowerModuleSupported()); -} - -TEST_F(SysmanPowerFixture, GivenValidOSPowerHandleWhenCallingGetEnergyThresholdExpectUnsupportedFeatureReturned) { - zet_energy_threshold_t threshold; - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pPowerImp->pOsPower->getEnergyThreshold(&threshold)); -} - -TEST_F(SysmanPowerFixture, GivenValidOSPowerHandleWhenCallingSetEnergyThresholdExpectUnsupportedFeatureReturned) { - double threshold = 0; - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pPowerImp->pOsPower->setEnergyThreshold(threshold)); -} TEST_F(SysmanPowerFixture, GivenComponentCountZeroWhenCallingZetSysmanPowerGetThenZeroCountIsReturnedAndVerifySysmanPowerGetCallSucceeds) { uint32_t count = 0; ze_result_t result = zetSysmanPowerGet(hSysman, &count, NULL); EXPECT_EQ(ZE_RESULT_SUCCESS, result); - EXPECT_EQ(count, 0u); + EXPECT_EQ(count, 1u); uint32_t testcount = count + 1; @@ -77,5 +78,25 @@ TEST_F(SysmanPowerFixture, GivenComponentCountZeroWhenCallingZetSysmanPowerGetTh EXPECT_EQ(ZE_RESULT_SUCCESS, result); EXPECT_EQ(testcount, count); } + +TEST_F(SysmanPowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyCounterThenValidPowerReadingsRetrieved) { + zet_power_energy_counter_t energyCounter; + uint64_t expectedEnergyCounter = convertJouleToMicroJoule * setEnergyCounter; + ASSERT_EQ(ZE_RESULT_SUCCESS, zetSysmanPowerGetEnergyCounter(hSysmanPowerHandle, &energyCounter)); + EXPECT_EQ(energyCounter.energy, expectedEnergyCounter); +} + +TEST_F(SysmanPowerFixture, GivenValidPowerHandleWhenGettingPowerEnergyThresholdThenUnsupportedFeatureErrorIsReturned) { + zet_energy_threshold_t threshold; + + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zetSysmanPowerGetEnergyThreshold(hSysmanPowerHandle, &threshold)); +} + +TEST_F(SysmanPowerFixture, GivenValidPowerHandleWhenSettingPowerEnergyThresholdThenUnsupportedFeatureErrorIsReturned) { + double threshold = 0; + + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zetSysmanPowerSetEnergyThreshold(hSysmanPowerHandle, threshold)); +} + } // namespace ult } // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/CMakeLists.txt b/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/CMakeLists.txt index 846a47eb1e..3615029fc6 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/CMakeLists.txt +++ b/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/CMakeLists.txt @@ -8,7 +8,7 @@ if(UNIX) target_sources(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/test_sysman_temperature.cpp - ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/mock_sysfs_temperature.h + ${CMAKE_CURRENT_SOURCE_DIR}/test_sysman_temperature.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_temperature.h ) endif() \ No newline at end of file diff --git a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/mock_sysfs_temperature.h b/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/mock_sysfs_temperature.h index de50c05279..5b57dffc68 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/mock_sysfs_temperature.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/mock_sysfs_temperature.h @@ -6,9 +6,12 @@ */ #pragma once +#include "shared/source/helpers/string.h" + #include "level_zero/core/test/unit_tests/mock.h" #include "level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h" +#include "sysman/linux/pmt.h" #include "sysman/sysman_imp.h" #include "sysman/temperature/temperature_imp.h" @@ -21,9 +24,45 @@ using ::testing::_; namespace L0 { namespace ult { +constexpr uint8_t computeIndex = 9; +constexpr uint8_t globalIndex = 3; +constexpr uint8_t tempArr[16] = {0x12, 0x23, 0x43, 0xde, 0xa3, 0xce, 0x23, 0x11, 0x45, 0x32, 0x67, 0x47, 0xac, 0x21, 0x03, 0x90}; +constexpr uint64_t offsetCompute = 0x60; +constexpr uint64_t mappedLength = 256; +class TemperaturePmt : public PlatformMonitoringTech { + public: + using PlatformMonitoringTech::mappedMemory; +}; + +template <> +struct Mock : public TemperaturePmt { + Mock() = default; + ~Mock() override { + if (mappedMemory != nullptr) { + delete mappedMemory; + mappedMemory = nullptr; + } + } + + void setVal(bool val) { + isPmtSupported = val; + } + + void init(const std::string &deviceName, FsAccess *pFsAccess) override { + mappedMemory = new char[mappedLength]; + for (uint64_t i = 0; i < sizeof(tempArr) / sizeof(uint8_t); i++) { + mappedMemory[offsetCompute + i] = tempArr[i]; + } + pmtSupported = isPmtSupported; + } + + private: + bool isPmtSupported = false; +}; class PublicLinuxTemperatureImp : public L0::LinuxTemperatureImp { public: + using LinuxTemperatureImp::pPmt; using LinuxTemperatureImp::pSysfsAccess; using LinuxTemperatureImp::type; }; diff --git a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_sysman_temperature.cpp b/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_sysman_temperature.cpp index 053d7ad400..979f31afd5 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_sysman_temperature.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_sysman_temperature.cpp @@ -11,57 +11,115 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "mock_sysfs_temperature.h" +#include "sysman/linux/os_sysman_imp.h" +#include "sysman/temperature/temperature_imp.h" + +using ::testing::_; +using ::testing::NiceMock; namespace L0 { namespace ult { +constexpr uint32_t handleCount = 2u; // We are creating two temp handles +const std::string deviceName("testDevice"); class SysmanTemperatureFixture : public DeviceFixture, public ::testing::Test { protected: std::unique_ptr sysmanImp; zet_sysman_handle_t hSysman; - OsTemperature *pOsTemperature = nullptr; - PublicLinuxTemperatureImp linuxTemperatureImp; - TemperatureImp *pTemperatureImp = nullptr; + Mock *pPmt = nullptr; + + TemperatureImp *pTemperatureImp[handleCount] = {}; + zet_sysman_temp_handle_t hSysmanTempHandle[handleCount]; + PublicLinuxTemperatureImp linuxTemperatureImp[handleCount]; + void SetUp() override { DeviceFixture::SetUp(); sysmanImp = std::make_unique(device->toHandle()); - pOsTemperature = static_cast(&linuxTemperatureImp); - pTemperatureImp = new TemperatureImp(); - pTemperatureImp->pOsTemperature = pOsTemperature; - pTemperatureImp->init(); + pPmt = new NiceMock>; + FsAccess *pFsAccess = nullptr; + pPmt->setVal(true); + pPmt->init(deviceName, pFsAccess); + + for (uint32_t i = 0; i < handleCount; i++) { + linuxTemperatureImp[i].pPmt = pPmt; + OsTemperature *pOsTemperature = static_cast(&linuxTemperatureImp[i]); + pTemperatureImp[i] = new TemperatureImp(); + pTemperatureImp[i]->pOsTemperature = pOsTemperature; + pTemperatureImp[i]->init(); + pTemperatureImp[i]->pOsTemperature->setSensorType(static_cast(i)); + sysmanImp->pTempHandleContext->handleList.push_back(pTemperatureImp[i]); + hSysmanTempHandle[i] = pTemperatureImp[i]->toHandle(); + } hSysman = sysmanImp->toHandle(); } void TearDown() override { - //pOsTemperature is static_cast of LinuxTemperatureImp class , hence in cleanup assign to nullptr - pTemperatureImp->pOsTemperature = nullptr; - if (pTemperatureImp != nullptr) { - delete pTemperatureImp; - pTemperatureImp = nullptr; + // pOsTemperatureGlobal is static_cast of LinuxTemperatureImp class , hence in cleanup assign to nullptr + pTemperatureImp[0]->pOsTemperature = nullptr; + pTemperatureImp[1]->pOsTemperature = nullptr; + + if (pPmt != nullptr) { + delete pPmt; + pPmt = nullptr; } DeviceFixture::TearDown(); } }; -TEST_F(SysmanTemperatureFixture, GivenValidOSTempHandleWhenCheckingForTempSupportThenExpectFalseToBeReturned) { - EXPECT_FALSE(pOsTemperature->isTempModuleSupported()); -} - -TEST_F(SysmanTemperatureFixture, GivenValidOSTemperatureHandleWhenSettingTemperatureSensorThenSameSetSensorIsRetrieved) { - pOsTemperature->setSensorType(ZET_TEMP_SENSORS_GPU); - EXPECT_EQ(linuxTemperatureImp.type, ZET_TEMP_SENSORS_GPU); - - pOsTemperature->setSensorType(ZET_TEMP_SENSORS_GLOBAL); - EXPECT_EQ(linuxTemperatureImp.type, ZET_TEMP_SENSORS_GLOBAL); -} - TEST_F(SysmanTemperatureFixture, GivenComponentCountZeroWhenCallingZetSysmanTemperatureGetThenZeroCountIsReturnedAndVerifySysmanTemperatureGetCallSucceeds) { uint32_t count = 0; ze_result_t result = zetSysmanTemperatureGet(hSysman, &count, NULL); EXPECT_EQ(ZE_RESULT_SUCCESS, result); - EXPECT_EQ(count, 0u); + EXPECT_EQ(count, handleCount); uint32_t testcount = count + 1; result = zetSysmanTemperatureGet(hSysman, &testcount, NULL); EXPECT_EQ(ZE_RESULT_SUCCESS, result); EXPECT_EQ(testcount, count); } + +TEST_F(SysmanTemperatureFixture, GivenValidTempHandleWhenGettingGPUTemperatureThenValidTemperatureReadingsRetrieved) { + double temperature; + ASSERT_EQ(ZE_RESULT_SUCCESS, zetSysmanTemperatureGetState(hSysmanTempHandle[1], &temperature)); + EXPECT_EQ(temperature, static_cast(tempArr[computeIndex])); +} + +TEST_F(SysmanTemperatureFixture, GivenValidTempHandleWhenGettingGlobalTemperatureThenValidTemperatureReadingsRetrieved) { + double temperature; + ASSERT_EQ(ZE_RESULT_SUCCESS, zetSysmanTemperatureGetState(hSysmanTempHandle[0], &temperature)); + EXPECT_EQ(temperature, static_cast(tempArr[globalIndex])); +} + +TEST_F(SysmanTemperatureFixture, GivenValidTempHandleWhenGettingUnsupportedSensorsTemperatureThenUnsupportedReturned) { + double pTemperature = 0; + pTemperatureImp[0]->pOsTemperature->setSensorType(ZET_TEMP_SENSORS_MEMORY); + pTemperatureImp[1]->pOsTemperature->setSensorType(ZET_TEMP_SENSORS_MEMORY); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pTemperatureImp[0]->pOsTemperature->getSensorTemperature(&pTemperature)); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pTemperatureImp[1]->pOsTemperature->getSensorTemperature(&pTemperature)); +} + +TEST_F(SysmanTemperatureFixture, GivenPmtSupportNotAvailableWhenCheckingForTempModuleSupportThenTempModuleSupportShouldReturnFalse) { + //delete previously allocated memory, allocated by init() call in SetUp() + if (pPmt->mappedMemory != nullptr) { + delete pPmt->mappedMemory; + pPmt->mappedMemory = nullptr; + } + pPmt->setVal(false); + FsAccess *pFsAccess = nullptr; + pPmt->init(deviceName, pFsAccess); + EXPECT_FALSE(pTemperatureImp[0]->pOsTemperature->isTempModuleSupported()); + EXPECT_FALSE(pTemperatureImp[1]->pOsTemperature->isTempModuleSupported()); +} + +TEST_F(SysmanTemperatureFixture, GivenPmtSupportAvailableWhenCheckingForTempModuleSupportThenTempModuleSupportShouldReturnTrue) { + //delete previously allocated memory, allocated by init() call in SetUp() + if (pPmt->mappedMemory != nullptr) { + delete pPmt->mappedMemory; + pPmt->mappedMemory = nullptr; + } + pPmt->setVal(true); + FsAccess *pFsAccess = nullptr; + pPmt->init(deviceName, pFsAccess); + EXPECT_TRUE(pTemperatureImp[0]->pOsTemperature->isTempModuleSupported()); + EXPECT_TRUE(pTemperatureImp[1]->pOsTemperature->isTempModuleSupported()); +} + } // namespace ult } // namespace L0