diff --git a/level_zero/tools/source/sysman/fan/linux/os_fan_imp.cpp b/level_zero/tools/source/sysman/fan/linux/os_fan_imp.cpp index ee37d5390c..405cda4c79 100644 --- a/level_zero/tools/source/sysman/fan/linux/os_fan_imp.cpp +++ b/level_zero/tools/source/sysman/fan/linux/os_fan_imp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -7,7 +7,7 @@ #include "level_zero/tools/source/sysman/fan/linux/os_fan_imp.h" -#include "level_zero/tools/source/sysman/linux/pmt.h" +#include "level_zero/tools/source/sysman/linux/pmt/pmt.h" #include "sysman/linux/os_sysman_imp.h" diff --git a/level_zero/tools/source/sysman/linux/CMakeLists.txt b/level_zero/tools/source/sysman/linux/CMakeLists.txt index 023009d788..66e6c7279c 100644 --- a/level_zero/tools/source/sysman/linux/CMakeLists.txt +++ b/level_zero/tools/source/sysman/linux/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2019-2020 Intel Corporation +# Copyright (C) 2019-2021 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -9,8 +9,6 @@ set(L0_SRCS_TOOLS_SYSMAN_LINUX ${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) 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 92e8d581e3..59bddd1851 100644 --- a/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp +++ b/level_zero/tools/source/sysman/linux/os_sysman_imp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -34,9 +34,14 @@ ze_result_t LinuxSysmanImp::init() { pSysfsAccess = SysfsAccess::create(myDeviceName); UNRECOVERABLE_IF(nullptr == pSysfsAccess); - pPmt = new PlatformMonitoringTech(); - UNRECOVERABLE_IF(nullptr == pPmt); - pPmt->init(myDeviceName, pFsAccess); + std::string realRootPath; + result = pSysfsAccess->getRealPath("device", realRootPath); + if (ZE_RESULT_SUCCESS != result) { + return result; + } + auto rootPciPathOfGpuDevice = getPciRootPortDirectoryPath(realRootPath); + PlatformMonitoringTech::create(pParentSysmanDeviceImp->deviceHandles, pFsAccess, rootPciPathOfGpuDevice, mapOfSubDeviceIdToPmtObject); + pPmuInterface = PmuInterface::create(this); UNRECOVERABLE_IF(nullptr == pPmuInterface); @@ -83,9 +88,29 @@ SysmanDeviceImp *LinuxSysmanImp::getSysmanDeviceImp() { return pParentSysmanDeviceImp; } -PlatformMonitoringTech &LinuxSysmanImp::getPlatformMonitoringTechAccess() { - UNRECOVERABLE_IF(nullptr == pPmt); - return *pPmt; +std::string LinuxSysmanImp::getPciRootPortDirectoryPath(std::string realPciPath) { + size_t loc; + // we need to change the absolute path to two levels up to get + // the Discrete card's root port. + // the root port is always at a fixed distance as defined in HW + uint8_t nLevel = 2; + while (nLevel > 0) { + loc = realPciPath.find_last_of('/'); + if (loc == std::string::npos) { + break; + } + realPciPath = realPciPath.substr(0, loc); + nLevel--; + } + return realPciPath; +} + +PlatformMonitoringTech *LinuxSysmanImp::getPlatformMonitoringTechAccess(uint32_t subDeviceId) { + auto subDeviceIdToPmtEntry = mapOfSubDeviceIdToPmtObject.find(subDeviceId); + if (subDeviceIdToPmtEntry == mapOfSubDeviceIdToPmtObject.end()) { + return nullptr; + } + return subDeviceIdToPmtEntry->second; } LinuxSysmanImp::LinuxSysmanImp(SysmanDeviceImp *pParentSysmanDeviceImp) { @@ -113,14 +138,13 @@ LinuxSysmanImp::~LinuxSysmanImp() { delete pFwUtilInterface; pFwUtilInterface = nullptr; } - if (nullptr != pPmt) { - delete pPmt; - pPmt = nullptr; - } if (nullptr != pPmuInterface) { delete pPmuInterface; pPmuInterface = nullptr; } + for (auto &subDeviceIdToPmtEntry : mapOfSubDeviceIdToPmtObject) { + delete subDeviceIdToPmtEntry.second; + } } OsSysman *OsSysman::create(SysmanDeviceImp *pParentSysmanDeviceImp) { 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 c46201eb91..ea93da5cdc 100644 --- a/level_zero/tools/source/sysman/linux/os_sysman_imp.h +++ b/level_zero/tools/source/sysman/linux/os_sysman_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -13,11 +13,13 @@ #include "level_zero/core/source/device/device.h" #include "level_zero/tools/source/sysman/linux/firmware_util/firmware_util.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/linux/pmt/pmt.h" #include "level_zero/tools/source/sysman/linux/pmu/pmu_imp.h" #include "level_zero/tools/source/sysman/linux/xml_parser/xml_parser.h" #include "level_zero/tools/source/sysman/sysman_imp.h" +#include + namespace L0 { class PmuInterface; @@ -35,20 +37,21 @@ class LinuxSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass { ProcfsAccess &getProcfsAccess(); SysfsAccess &getSysfsAccess(); NEO::Drm &getDrm(); - PlatformMonitoringTech &getPlatformMonitoringTechAccess(); + PlatformMonitoringTech *getPlatformMonitoringTechAccess(uint32_t subDeviceId); Device *getDeviceHandle(); SysmanDeviceImp *getSysmanDeviceImp(); + std::string getPciRootPortDirectoryPath(std::string realPciPath); protected: XmlParser *pXmlParser = nullptr; FsAccess *pFsAccess = nullptr; ProcfsAccess *pProcfsAccess = nullptr; SysfsAccess *pSysfsAccess = nullptr; - PlatformMonitoringTech *pPmt = nullptr; NEO::Drm *pDrm = nullptr; Device *pDevice = nullptr; PmuInterface *pPmuInterface = nullptr; FirmwareUtil *pFwUtilInterface = nullptr; + std::map mapOfSubDeviceIdToPmtObject; private: LinuxSysmanImp() = delete; diff --git a/level_zero/tools/source/sysman/linux/pmt.cpp b/level_zero/tools/source/sysman/linux/pmt.cpp deleted file mode 100644 index ac818efde9..0000000000 --- a/level_zero/tools/source/sysman/linux/pmt.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2020-2021 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_telemetry/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 deleted file mode 100644 index d5895a2efc..0000000000 --- a/level_zero/tools/source/sysman/linux/pmt.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 : NEO::NonCopyableOrMovableClass { - 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/linux/pmt/CMakeLists.txt b/level_zero/tools/source/sysman/linux/pmt/CMakeLists.txt new file mode 100644 index 0000000000..3acf7aa0b4 --- /dev/null +++ b/level_zero/tools/source/sysman/linux/pmt/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# Copyright (C) 2020-2021 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(L0_SRCS_TOOLS_SYSMAN_LINUX_PMT + ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/pmt.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/pmt.h +) +if(UNIX) + target_sources(${L0_STATIC_LIB_NAME} + PRIVATE + ${L0_SRCS_TOOLS_SYSMAN_LINUX_PMT} + ) +endif() +# Make our source files visible to parent +set_property(GLOBAL PROPERTY L0_SRCS_TOOLS_SYSMAN_PMT_LINUX ${L0_SRCS_TOOLS_SYSMAN_PMT_LINUX}) diff --git a/level_zero/tools/source/sysman/linux/pmt/pmt.cpp b/level_zero/tools/source/sysman/linux/pmt/pmt.cpp new file mode 100644 index 0000000000..2e8c331a19 --- /dev/null +++ b/level_zero/tools/source/sysman/linux/pmt/pmt.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2020-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "level_zero/tools/source/sysman/linux/pmt/pmt.h" + +#include "shared/source/debug_settings/debug_settings_manager.h" + +#include +#include +#include +#include +#include + +namespace L0 { +const std::string PlatformMonitoringTech::devfs("/dev/"); +const std::string PlatformMonitoringTech::baseTelemSysFS("/sys/class/pmt_telemetry"); +const std::string PlatformMonitoringTech::telem("telem"); +uint32_t PlatformMonitoringTech::rootDeviceTelemNodeIndex = 0; + +const std::map deviceKeyOffsetMap = { + {"PACKAGE_ENERGY", 0x400}, + {"COMPUTE_TEMPERATURES", 0x68}, + {"SOC_TEMPERATURES", 0x60}, + {"CORE_TEMPERATURES", 0x6c}}; + +ze_result_t PlatformMonitoringTech::enumerateRootTelemIndex(FsAccess *pFsAccess, std::string &rootPciPathOfGpuDevice) { + std::vector listOfTelemNodes; + auto result = pFsAccess->listDirectory(baseTelemSysFS, listOfTelemNodes); + if (ZE_RESULT_SUCCESS != result) { + return result; + } + + // Exmaple: For below directory + // # /sys/class/pmt_telemetry$ ls + // telem1 telem2 telem3 + // Then listOfTelemNodes would contain telem1, telem2, telem3 + std::sort(listOfTelemNodes.begin(), listOfTelemNodes.end()); // sort listOfTelemNodes, to arange telem nodes in ascending order + for (const auto &telemNode : listOfTelemNodes) { + std::string realPathOfTelemNode; + result = pFsAccess->getRealPath(baseTelemSysFS + "/" + telemNode, realPathOfTelemNode); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + // Check if Telemetry node(say telem1) and rootPciPathOfGpuDevice share same PCI Root port + if (realPathOfTelemNode.compare(0, rootPciPathOfGpuDevice.size(), rootPciPathOfGpuDevice) == 0) { + // Example: If + // rootPciPathOfGpuDevice = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0"; + // realPathOfTelemNode = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem1"; + // Thus As realPathOfTelemNode consists of rootPciPathOfGpuDevice, hence both telemNode and GPU device share same PCI Root. + auto indexString = telemNode.substr(telem.size(), telemNode.size()); + rootDeviceTelemNodeIndex = stoi(indexString); // if telemNode is telemN, then rootDeviceTelemNodeIndex = N + return ZE_RESULT_SUCCESS; + } + } + return result; +} + +void PlatformMonitoringTech::init(FsAccess *pFsAccess) { + auto getErrorVal = [](auto err) { + if ((EPERM == err) || (EACCES == err)) { + return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS; + } else if (ENOENT == err) { + return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE; + } else { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + }; + + std::string telemNode = telem + std::to_string(rootDeviceTelemNodeIndex); + if (isSubdevice) { + uint32_t telemNodeIndex = 0; + // If rootDeviceTelemNode is telem1, then rootDeviceTelemNodeIndex = 1 + // And thus for subdevice0 --> telem node will be telem2, + // for subdevice1 --> telem node will be telem3 etc + telemNodeIndex = rootDeviceTelemNodeIndex + subdeviceId + 1; + telemNode = telem + std::to_string(telemNodeIndex); + } + std::string baseTelemSysFSNode = baseTelemSysFS + "/" + telemNode; + std::string telemetryDeviceEntry = devfs + telemNode; + if (!pFsAccess->fileExists(telemetryDeviceEntry)) { + NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, + "Telemetry support not available. No file %s\n", telemetryDeviceEntry.c_str()); + retVal = ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE; + return; + } + + std::string guid; + std::string guidPath = baseTelemSysFSNode + 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()); + retVal = result; + return; + } + keyOffsetMap = deviceKeyOffsetMap; + + std::string sizePath = baseTelemSysFSNode + 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()); + retVal = result; + return; + } + + std::string offsetPath = baseTelemSysFSNode + 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()); + retVal = result; + 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)); + retVal = getErrorVal(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); + retVal = getErrorVal(errno); + 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); + mappedMemory = nullptr; + retVal = getErrorVal(errno); + return; + } + + mappedMemory += baseOffset; +} + +PlatformMonitoringTech::PlatformMonitoringTech(FsAccess *pFsAccess, ze_bool_t onSubdevice, + uint32_t subdeviceId) : subdeviceId(subdeviceId), isSubdevice(onSubdevice) { + init(pFsAccess); +} + +void PlatformMonitoringTech::create(const std::vector &deviceHandles, + FsAccess *pFsAccess, std::string &rootPciPathOfGpuDevice, + std::map &mapOfSubDeviceIdToPmtObject) { + if (ZE_RESULT_SUCCESS == PlatformMonitoringTech::enumerateRootTelemIndex(pFsAccess, rootPciPathOfGpuDevice)) { + for (const auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + auto pPmt = new PlatformMonitoringTech(pFsAccess, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId); + UNRECOVERABLE_IF(nullptr == pPmt); + mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt); + } + } +} + +PlatformMonitoringTech::~PlatformMonitoringTech() { + if (mappedMemory != nullptr) { + munmap(mappedMemory - baseOffset, size); + } +} + +} // namespace L0 diff --git a/level_zero/tools/source/sysman/linux/pmt/pmt.h b/level_zero/tools/source/sysman/linux/pmt/pmt.h new file mode 100644 index 0000000000..6c3fe8778c --- /dev/null +++ b/level_zero/tools/source/sysman/linux/pmt/pmt.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2020-2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/helpers/non_copyable_or_moveable.h" + +#include "level_zero/core/source/device/device.h" +#include "level_zero/tools/source/sysman/linux/fs_access.h" + +#include + +namespace L0 { + +class PlatformMonitoringTech : NEO::NonCopyableOrMovableClass { + public: + PlatformMonitoringTech() = delete; + PlatformMonitoringTech(FsAccess *pFsAccess, ze_bool_t onSubdevice, uint32_t subdeviceId); + virtual ~PlatformMonitoringTech(); + + template + ze_result_t readValue(const std::string key, ReadType &value); + static ze_result_t enumerateRootTelemIndex(FsAccess *pFsAccess, std::string &rootPciPathOfGpuDevice); + static void create(const std::vector &deviceHandles, + FsAccess *pFsAccess, std::string &rootPciPathOfGpuDevice, + std::map &mapOfSubDeviceIdToPmtObject); + + protected: + char *mappedMemory = nullptr; + static uint32_t rootDeviceTelemNodeIndex; + std::map keyOffsetMap; + + private: + void init(FsAccess *pFsAccess); + static const std::string devfs; + static const std::string baseTelemSysFS; + static const std::string telem; + uint64_t size = 0; + uint64_t baseOffset = 0; + uint32_t subdeviceId = 0; + ze_bool_t isSubdevice = 0; + ze_result_t retVal = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +}; + +template +ze_result_t PlatformMonitoringTech::readValue(const std::string key, ReadType &value) { + if (mappedMemory == nullptr) { + return retVal; + } + + auto offset = keyOffsetMap.find(key); + if (offset == keyOffsetMap.end()) { + return retVal; + } + value = *reinterpret_cast(mappedMemory + offset->second); + return ZE_RESULT_SUCCESS; +} + +} // namespace L0 diff --git a/level_zero/tools/source/sysman/pci/linux/os_pci_imp.cpp b/level_zero/tools/source/sysman/pci/linux/os_pci_imp.cpp index 65d885ed6f..6ad7984215 100644 --- a/level_zero/tools/source/sysman/pci/linux/os_pci_imp.cpp +++ b/level_zero/tools/source/sysman/pci/linux/os_pci_imp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2020 Intel Corporation + * Copyright (C) 2019-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -10,7 +10,6 @@ #include "level_zero/tools/source/sysman/linux/fs_access.h" #include "level_zero/tools/source/sysman/sysman_const.h" -#include "sysman/linux/os_sysman_imp.h" #include "sysman/pci/pci_imp.h" namespace L0 { @@ -20,15 +19,6 @@ const std::string LinuxPciImp::resourceFile("device/resource"); const std::string LinuxPciImp::maxLinkSpeedFile("device/max_link_speed"); const std::string LinuxPciImp::maxLinkWidthFile("device/max_link_width"); -std::string LinuxPciImp::changeDirNLevelsUp(std::string realRootPath, uint8_t nLevel) { - size_t loc; - while (nLevel > 0) { - loc = realRootPath.find_last_of('/'); - realRootPath = realRootPath.substr(0, loc); - nLevel--; - } - return realRootPath; -} ze_result_t LinuxPciImp::getProperties(zes_pci_properties_t *properties) { properties->haveBandwidthCounters = false; properties->havePacketCounters = false; @@ -52,14 +42,14 @@ ze_result_t LinuxPciImp::getMaxLinkSpeed(double &maxLinkSpeed) { std::string rootPortPath; std::string realRootPath; result = pSysfsAccess->getRealPath(deviceDir, realRootPath); - // we need to change the absolute path to two levels up to get actual - // values of speed and width at the Discrete card's root port. - // the root port is always at a fixed distance as defined in HW - rootPortPath = changeDirNLevelsUp(realRootPath, 2); if (ZE_RESULT_SUCCESS != result) { maxLinkSpeed = 0; return result; } + + // we need to get actual values of speed and width at the Discrete card's root port. + rootPortPath = pLinuxSysmanImp->getPciRootPortDirectoryPath(realRootPath); + result = pfsAccess->read(rootPortPath + '/' + "max_link_speed", maxLinkSpeed); if (ZE_RESULT_SUCCESS != result) { maxLinkSpeed = 0; @@ -81,14 +71,14 @@ ze_result_t LinuxPciImp::getMaxLinkWidth(int32_t &maxLinkwidth) { std::string rootPortPath; std::string realRootPath; result = pSysfsAccess->getRealPath(deviceDir, realRootPath); - // we need to change the absolute path to two levels up to get actual - // values of speed and width at the Discrete card's root port. - // the root port is always at a fixed distance as defined in HW - rootPortPath = changeDirNLevelsUp(realRootPath, 2); if (ZE_RESULT_SUCCESS != result) { maxLinkwidth = -1; return result; } + + // we need to get actual values of speed and width at the Discrete card's root port. + rootPortPath = pLinuxSysmanImp->getPciRootPortDirectoryPath(realRootPath); + result = pfsAccess->read(rootPortPath + '/' + "max_link_width", maxLinkwidth); if (ZE_RESULT_SUCCESS != result) { maxLinkwidth = -1; @@ -163,7 +153,7 @@ ze_result_t LinuxPciImp::getState(zes_pci_state_t *state) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } LinuxPciImp::LinuxPciImp(OsSysman *pOsSysman) { - LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); + pLinuxSysmanImp = static_cast(pOsSysman); pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); pfsAccess = &pLinuxSysmanImp->getFsAccess(); Device *pDevice = pLinuxSysmanImp->getDeviceHandle(); diff --git a/level_zero/tools/source/sysman/pci/linux/os_pci_imp.h b/level_zero/tools/source/sysman/pci/linux/os_pci_imp.h index 24e5e76450..e983d8abd8 100644 --- a/level_zero/tools/source/sysman/pci/linux/os_pci_imp.h +++ b/level_zero/tools/source/sysman/pci/linux/os_pci_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -8,6 +8,7 @@ #pragma once #include "shared/source/helpers/non_copyable_or_moveable.h" +#include "sysman/linux/os_sysman_imp.h" #include "sysman/pci/os_pci.h" namespace L0 { @@ -30,7 +31,7 @@ class LinuxPciImp : public OsPci, NEO::NonCopyableOrMovableClass { protected: SysfsAccess *pSysfsAccess = nullptr; FsAccess *pfsAccess = nullptr; - std::string changeDirNLevelsUp(std::string realRootPath, uint8_t nLevel); + LinuxSysmanImp *pLinuxSysmanImp = nullptr; private: static const std::string deviceDir; 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 dc54c00124..beec358b5b 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 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -7,7 +7,7 @@ #include "level_zero/tools/source/sysman/power/linux/os_power_imp.h" -#include "level_zero/tools/source/sysman/linux/pmt.h" +#include "level_zero/tools/source/sysman/linux/pmt/pmt.h" #include "level_zero/tools/source/sysman/sysman_const.h" #include "sysman/linux/os_sysman_imp.h" @@ -54,11 +54,13 @@ ze_result_t LinuxPowerImp::setEnergyThreshold(double threshold) { } bool LinuxPowerImp::isPowerModuleSupported() { - return pPmt->isPmtSupported(); + return (pPmt != nullptr); } LinuxPowerImp::LinuxPowerImp(OsSysman *pOsSysman) { LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); - pPmt = &pLinuxSysmanImp->getPlatformMonitoringTechAccess(); + // Lets hardcode subDeviceId to 0, as we are expecting this code to execute on device without subdevice + uint32_t subDeviceId = 0; + pPmt = pLinuxSysmanImp->getPlatformMonitoringTechAccess(subDeviceId); } 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 eb37752c59..8c34370499 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 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -10,6 +10,8 @@ #include "level_zero/tools/source/sysman/power/os_power.h" +#include + namespace L0 { class SysfsAccess; diff --git a/level_zero/tools/source/sysman/sysman_const.h b/level_zero/tools/source/sysman/sysman_const.h index 8ced566b74..988f8db2fb 100644 --- a/level_zero/tools/source/sysman/sysman_const.h +++ b/level_zero/tools/source/sysman/sysman_const.h @@ -39,7 +39,5 @@ constexpr uint64_t convertJouleToMicroJoule = 1000000u; constexpr uint64_t minTimeoutModeHeartbeat = 5000u; constexpr uint64_t minTimeoutInMicroSeconds = 1000u; constexpr uint16_t milliSecsToMicroSecs = 1000; -constexpr uint64_t numSocTemperatureEntries = 7; -constexpr uint32_t numCoreTemperatureEntries = 4; constexpr uint32_t milliFactor = 1000u; constexpr uint32_t microFacor = milliFactor * milliFactor; \ No newline at end of file diff --git a/level_zero/tools/source/sysman/sysman_imp.cpp b/level_zero/tools/source/sysman/sysman_imp.cpp index 685dd4e630..8f543ce8cd 100644 --- a/level_zero/tools/source/sysman/sysman_imp.cpp +++ b/level_zero/tools/source/sysman/sysman_imp.cpp @@ -60,7 +60,6 @@ SysmanDeviceImp::~SysmanDeviceImp() { void SysmanDeviceImp::init() { uint32_t subDeviceCount = 0; - std::vector deviceHandles; // We received a device handle. Check for subdevices in this device Device::fromHandle(hCoreDevice)->getSubDevices(&subDeviceCount, nullptr); if (subDeviceCount == 0) { @@ -81,7 +80,7 @@ void SysmanDeviceImp::init() { pFabricPortHandleContext->init(); } if (pTempHandleContext) { - pTempHandleContext->init(); + pTempHandleContext->init(deviceHandles); } if (pPci) { pPci->init(); diff --git a/level_zero/tools/source/sysman/sysman_imp.h b/level_zero/tools/source/sysman/sysman_imp.h index 2c39ae2dc3..a170de4bda 100644 --- a/level_zero/tools/source/sysman/sysman_imp.h +++ b/level_zero/tools/source/sysman/sysman_imp.h @@ -25,6 +25,7 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass { void init(); ze_device_handle_t hCoreDevice = nullptr; + std::vector deviceHandles; // handles of all subdevices OsSysman *pOsSysman = nullptr; Pci *pPci = nullptr; GlobalOperations *pGlobalOperations = nullptr; diff --git a/level_zero/tools/source/sysman/temperature/linux/CMakeLists.txt b/level_zero/tools/source/sysman/temperature/linux/CMakeLists.txt index 9c2482bea7..442f3c333b 100644 --- a/level_zero/tools/source/sysman/temperature/linux/CMakeLists.txt +++ b/level_zero/tools/source/sysman/temperature/linux/CMakeLists.txt @@ -1,11 +1,11 @@ # -# Copyright (C) 2020 Intel Corporation +# Copyright (C) 2020-2021 Intel Corporation # # SPDX-License-Identifier: MIT # set(L0_SRCS_TOOLS_SYSMAN_TEMPERATURE_LINUX - ${CMAKE_CURRENT_SOURCE_DIR}/os_temperature_imp.cpp + ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/os_temperature_imp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_temperature_imp.h ) 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 3a6b99d881..1a177c721b 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 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -7,22 +7,95 @@ #include "level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h" -#include "level_zero/tools/source/sysman/linux/pmt.h" +#include "level_zero/tools/source/sysman/linux/pmt/pmt.h" #include "sysman/linux/os_sysman_imp.h" namespace L0 { +constexpr uint32_t numSocTemperatureEntries = 7; // entries would be PCH, DRAM, SA, PSF, DE, PCIE, TYPEC +constexpr uint32_t numCoreTemperatureEntries = 4; // entries would be CORE0, CORE1, CORE2, CORE3 +constexpr uint32_t numComputeTemperatureEntries = 3; // entries would be IA, GT and LLC +constexpr uint32_t invalidMaxTemperature = 125; +constexpr uint32_t invalidMinTemperature = 10; + ze_result_t LinuxTemperatureImp::getProperties(zes_temp_properties_t *pProperties) { pProperties->type = type; - pProperties->onSubdevice = false; + pProperties->onSubdevice = 0; pProperties->subdeviceId = 0; + if (isSubdevice) { + pProperties->onSubdevice = isSubdevice; + pProperties->subdeviceId = subdeviceId; + } return ZE_RESULT_SUCCESS; } -ze_result_t LinuxTemperatureImp::getSensorTemperature(double *pTemperature) { +ze_result_t LinuxTemperatureImp::getGlobalMaxTemperatureNoSubDevice(double *pTemperature) { + auto isValidTemperature = [](auto temperature) { + if ((temperature > invalidMaxTemperature) || (temperature < invalidMinTemperature)) { + return false; + } + return true; + }; + + auto getMaxTemperature = [&](auto temperature, auto numTemperatureEntries) { + uint32_t maxTemperature = 0; + for (uint32_t count = 0; count < numTemperatureEntries; count++) { + uint32_t localTemperatureVal = (temperature >> (8 * count)) & 0xff; + if (isValidTemperature(localTemperatureVal)) { + if (localTemperatureVal > maxTemperature) { + maxTemperature = localTemperatureVal; + } + } + } + return maxTemperature; + }; + + uint32_t computeTemperature = 0; + std::string key("COMPUTE_TEMPERATURES"); + ze_result_t result = pPmt->readValue(key, computeTemperature); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + // Check max temperature among IA, GT and LLC sensors across COMPUTE_TEMPERATURES + uint32_t maxComputeTemperature = getMaxTemperature(computeTemperature, numComputeTemperatureEntries); + + uint32_t coreTemperature = 0; + key = "CORE_TEMPERATURES"; + result = pPmt->readValue(key, coreTemperature); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + // Check max temperature among CORE0, CORE1, CORE2, CORE3 sensors across CORE_TEMPERATURES + uint32_t maxCoreTemperature = getMaxTemperature(coreTemperature, numCoreTemperatureEntries); + uint64_t socTemperature = 0; - uint32_t computeTemperature = 0, coreTemperature = 0; + key = "SOC_TEMPERATURES"; + result = pPmt->readValue(key, socTemperature); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + // Check max temperature among PCH, DRAM, SA, PSF, DE, PCIE, TYPEC sensors across SOC_TEMPERATURES + uint32_t maxSocTemperature = getMaxTemperature(socTemperature, numSocTemperatureEntries); + + *pTemperature = static_cast(std::max({maxComputeTemperature, maxCoreTemperature, maxSocTemperature})); + + return result; +} + +ze_result_t LinuxTemperatureImp::getGlobalMaxTemperature(double *pTemperature) { + if (!isSubdevice) { + return getGlobalMaxTemperatureNoSubDevice(pTemperature); + } + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t LinuxTemperatureImp::getGlobalMinTemperature(double *pTemperature) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t LinuxTemperatureImp::getGpuMaxTemperatureNoSubDevice(double *pTemperature) { + uint32_t computeTemperature = 0; std::string key("COMPUTE_TEMPERATURES"); ze_result_t result = pPmt->readValue(key, computeTemperature); if (result != ZE_RESULT_SUCCESS) { @@ -31,63 +104,92 @@ ze_result_t LinuxTemperatureImp::getSensorTemperature(double *pTemperature) { // GT temperature could be read via 8th to 15th bit in the value read in temperature computeTemperature = (computeTemperature >> 8) & 0xff; + *pTemperature = static_cast(computeTemperature); + return ZE_RESULT_SUCCESS; +} - if (type == ZES_TEMP_SENSORS_GPU) { - *pTemperature = static_cast(computeTemperature); - } else if (type == ZES_TEMP_SENSORS_GLOBAL) { - key = "SOC_TEMPERATURES"; - result = pPmt->readValue(key, socTemperature); +ze_result_t LinuxTemperatureImp::getGpuMaxTemperature(double *pTemperature) { + if (!isSubdevice) { + return getGpuMaxTemperatureNoSubDevice(pTemperature); + } + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t LinuxTemperatureImp::getGpuMinTemperature(double *pTemperature) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t LinuxTemperatureImp::getMemoryMaxTemperature(double *pTemperature) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ze_result_t LinuxTemperatureImp::getSensorTemperature(double *pTemperature) { + ze_result_t result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + switch (type) { + case ZES_TEMP_SENSORS_GLOBAL: + result = getGlobalMaxTemperature(pTemperature); if (result != ZE_RESULT_SUCCESS) { return result; } - - 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); + break; + case ZES_TEMP_SENSORS_GPU: + result = getGpuMaxTemperature(pTemperature); if (result != ZE_RESULT_SUCCESS) { return result; } - - uint32_t coreTemperatureList[numCoreTemperatureEntries]; - for (uint64_t count = 0; count < numCoreTemperatureEntries; count++) { - coreTemperatureList[count] = (coreTemperature >> (8 * count)) & 0xff; + break; + case ZES_TEMP_SENSORS_MEMORY: + result = getMemoryMaxTemperature(pTemperature); + if (result != ZE_RESULT_SUCCESS) { + return result; } - // 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})); - } else { + break; + case ZES_TEMP_SENSORS_GLOBAL_MIN: + result = getGlobalMinTemperature(pTemperature); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + break; + case ZES_TEMP_SENSORS_GPU_MIN: + result = getGpuMinTemperature(pTemperature); + if (result != ZE_RESULT_SUCCESS) { + return result; + } + break; + default: *pTemperature = 0; result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + break; } return result; } bool LinuxTemperatureImp::isTempModuleSupported() { - return pPmt->isPmtSupported(); + if (!isSubdevice) { + if ((type == ZES_TEMP_SENSORS_MEMORY) || (type == ZES_TEMP_SENSORS_GLOBAL_MIN) || + (type == ZES_TEMP_SENSORS_GPU_MIN)) { + return false; + } + } + + return (pPmt != nullptr); } void LinuxTemperatureImp::setSensorType(zes_temp_sensors_t sensorType) { type = sensorType; } -LinuxTemperatureImp::LinuxTemperatureImp(OsSysman *pOsSysman) { +LinuxTemperatureImp::LinuxTemperatureImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, + uint32_t subdeviceId) : subdeviceId(subdeviceId), isSubdevice(onSubdevice) { LinuxSysmanImp *pLinuxSysmanImp = static_cast(pOsSysman); - pPmt = &pLinuxSysmanImp->getPlatformMonitoringTechAccess(); + pPmt = pLinuxSysmanImp->getPlatformMonitoringTechAccess(subdeviceId); } -OsTemperature *OsTemperature::create(OsSysman *pOsSysman, zes_temp_sensors_t sensorType) { - LinuxTemperatureImp *pLinuxTemperatureImp = new LinuxTemperatureImp(pOsSysman); +std::unique_ptr OsTemperature::create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_temp_sensors_t sensorType) { + std::unique_ptr pLinuxTemperatureImp = std::make_unique(pOsSysman, onSubdevice, subdeviceId); pLinuxTemperatureImp->setSensorType(sensorType); - return static_cast(pLinuxTemperatureImp); + return pLinuxTemperatureImp; } } // 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 a94be8e67a..da209f8712 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 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -10,6 +10,8 @@ #include "level_zero/tools/source/sysman/temperature/os_temperature.h" +#include + namespace L0 { class SysfsAccess; @@ -20,12 +22,23 @@ class LinuxTemperatureImp : public OsTemperature, NEO::NonCopyableOrMovableClass ze_result_t getSensorTemperature(double *pTemperature) override; bool isTempModuleSupported() override; void setSensorType(zes_temp_sensors_t sensorType); - LinuxTemperatureImp(OsSysman *pOsSysman); + LinuxTemperatureImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId); LinuxTemperatureImp() = default; ~LinuxTemperatureImp() override = default; protected: PlatformMonitoringTech *pPmt = nullptr; zes_temp_sensors_t type = ZES_TEMP_SENSORS_GLOBAL; + + private: + ze_result_t getGlobalMaxTemperature(double *pTemperature); + ze_result_t getGlobalMinTemperature(double *pTemperature); + ze_result_t getGpuMaxTemperature(double *pTemperature); + ze_result_t getGpuMinTemperature(double *pTemperature); + ze_result_t getMemoryMaxTemperature(double *pTemperature); + ze_result_t getGlobalMaxTemperatureNoSubDevice(double *pTemperature); + ze_result_t getGpuMaxTemperatureNoSubDevice(double *pTemperature); + uint32_t subdeviceId = 0; + ze_bool_t isSubdevice = 0; }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/temperature/os_temperature.h b/level_zero/tools/source/sysman/temperature/os_temperature.h index c4b3de956d..69e8e4c8ae 100644 --- a/level_zero/tools/source/sysman/temperature/os_temperature.h +++ b/level_zero/tools/source/sysman/temperature/os_temperature.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -9,6 +9,8 @@ #include +#include + namespace L0 { struct OsSysman; @@ -17,7 +19,7 @@ class OsTemperature { virtual ze_result_t getProperties(zes_temp_properties_t *pProperties) = 0; virtual ze_result_t getSensorTemperature(double *pTemperature) = 0; virtual bool isTempModuleSupported() = 0; - static OsTemperature *create(OsSysman *pOsSysman, zes_temp_sensors_t sensorType); + static std::unique_ptr create(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId, zes_temp_sensors_t sensorType); virtual ~OsTemperature() = default; }; diff --git a/level_zero/tools/source/sysman/temperature/temperature.cpp b/level_zero/tools/source/sysman/temperature/temperature.cpp index fc6462435f..e53532b268 100644 --- a/level_zero/tools/source/sysman/temperature/temperature.cpp +++ b/level_zero/tools/source/sysman/temperature/temperature.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -17,8 +17,8 @@ TemperatureHandleContext::~TemperatureHandleContext() { } } -void TemperatureHandleContext::createHandle(zes_temp_sensors_t type) { - Temperature *pTemperature = new TemperatureImp(pOsSysman, type); +void TemperatureHandleContext::createHandle(const ze_device_handle_t &deviceHandle, zes_temp_sensors_t type) { + Temperature *pTemperature = new TemperatureImp(deviceHandle, pOsSysman, type); if (pTemperature->initSuccess == true) { handleList.push_back(pTemperature); } else { @@ -26,10 +26,14 @@ void TemperatureHandleContext::createHandle(zes_temp_sensors_t type) { } } -void TemperatureHandleContext::init() { - createHandle(ZES_TEMP_SENSORS_GLOBAL); - createHandle(ZES_TEMP_SENSORS_GPU); - createHandle(ZES_TEMP_SENSORS_MEMORY); +void TemperatureHandleContext::init(std::vector &deviceHandles) { + for (const auto &deviceHandle : deviceHandles) { + createHandle(deviceHandle, ZES_TEMP_SENSORS_GLOBAL); + createHandle(deviceHandle, ZES_TEMP_SENSORS_GLOBAL_MIN); + createHandle(deviceHandle, ZES_TEMP_SENSORS_GPU); + createHandle(deviceHandle, ZES_TEMP_SENSORS_GPU_MIN); + createHandle(deviceHandle, ZES_TEMP_SENSORS_MEMORY); + } } ze_result_t TemperatureHandleContext::temperatureGet(uint32_t *pCount, zes_temp_handle_t *phTemperature) { diff --git a/level_zero/tools/source/sysman/temperature/temperature.h b/level_zero/tools/source/sysman/temperature/temperature.h index 7c4cf21db0..da96d14c74 100644 --- a/level_zero/tools/source/sysman/temperature/temperature.h +++ b/level_zero/tools/source/sysman/temperature/temperature.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -36,7 +36,7 @@ struct TemperatureHandleContext { TemperatureHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){}; ~TemperatureHandleContext(); - void init(); + void init(std::vector &deviceHandles); ze_result_t temperatureGet(uint32_t *pCount, zes_temp_handle_t *phTemperature); @@ -44,7 +44,7 @@ struct TemperatureHandleContext { std::vector handleList = {}; private: - void createHandle(zes_temp_sensors_t type); + void createHandle(const ze_device_handle_t &deviceHandle, zes_temp_sensors_t type); }; } // namespace L0 \ No newline at end of file diff --git a/level_zero/tools/source/sysman/temperature/temperature_imp.cpp b/level_zero/tools/source/sysman/temperature/temperature_imp.cpp index 6559554676..536734c1d3 100644 --- a/level_zero/tools/source/sysman/temperature/temperature_imp.cpp +++ b/level_zero/tools/source/sysman/temperature/temperature_imp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -35,16 +35,15 @@ void TemperatureImp::init() { } } -TemperatureImp::TemperatureImp(OsSysman *pOsSysman, zes_temp_sensors_t type) { - pOsTemperature = OsTemperature::create(pOsSysman, type); +TemperatureImp::TemperatureImp(const ze_device_handle_t &deviceHandle, OsSysman *pOsSysman, zes_temp_sensors_t type) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + pOsTemperature = OsTemperature::create(pOsSysman, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId, type); init(); } TemperatureImp::~TemperatureImp() { - if (nullptr != pOsTemperature) { - delete pOsTemperature; - pOsTemperature = nullptr; - } } } // namespace L0 \ No newline at end of file diff --git a/level_zero/tools/source/sysman/temperature/temperature_imp.h b/level_zero/tools/source/sysman/temperature/temperature_imp.h index c703e27e22..3eaeebe89a 100644 --- a/level_zero/tools/source/sysman/temperature/temperature_imp.h +++ b/level_zero/tools/source/sysman/temperature/temperature_imp.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,10 +20,10 @@ class TemperatureImp : public Temperature, NEO::NonCopyableOrMovableClass { ze_result_t temperatureGetState(double *pTemperature) override; TemperatureImp() = default; - TemperatureImp(OsSysman *pOsSysman, zes_temp_sensors_t type); + TemperatureImp(const ze_device_handle_t &deviceHandle, OsSysman *pOsSysman, zes_temp_sensors_t type); ~TemperatureImp() override; - OsTemperature *pOsTemperature = nullptr; + std::unique_ptr pOsTemperature = nullptr; void init(); }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/temperature/windows/os_temperature_imp.cpp b/level_zero/tools/source/sysman/temperature/windows/os_temperature_imp.cpp index 1535720343..a3f2b3076d 100644 --- a/level_zero/tools/source/sysman/temperature/windows/os_temperature_imp.cpp +++ b/level_zero/tools/source/sysman/temperature/windows/os_temperature_imp.cpp @@ -120,6 +120,9 @@ ze_result_t WddmTemperatureImp::getSensorTemperature(double *pTemperature) { } bool WddmTemperatureImp::isTempModuleSupported() { + if ((type == ZES_TEMP_SENSORS_GLOBAL_MIN) || (type == ZES_TEMP_SENSORS_GPU_MIN)) { + return false; + } KmdSysman::RequestProperty request; KmdSysman::ResponseProperty response; @@ -140,10 +143,10 @@ WddmTemperatureImp::WddmTemperatureImp(OsSysman *pOsSysman) { pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); } -OsTemperature *OsTemperature::create(OsSysman *pOsSysman, zes_temp_sensors_t sensorType) { - WddmTemperatureImp *pWddmTemperatureImp = new WddmTemperatureImp(pOsSysman); +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 static_cast(pWddmTemperatureImp); + return std::move(pWddmTemperatureImp); } } // namespace L0 \ No newline at end of file diff --git a/level_zero/tools/test/black_box_tests/zello_sysman.cpp b/level_zero/tools/test/black_box_tests/zello_sysman.cpp index 2d4cac4ada..dd6003d6ca 100644 --- a/level_zero/tools/test/black_box_tests/zello_sysman.cpp +++ b/level_zero/tools/test/black_box_tests/zello_sysman.cpp @@ -194,6 +194,21 @@ void testSysmanPower(ze_device_handle_t &device) { } } +std::string getTemperatureSensorType(zes_temp_sensors_t type) { + static const std::map mgetSensorType{ + {ZES_TEMP_SENSORS_GLOBAL, "ZES_TEMP_SENSORS_GLOBAL"}, + {ZES_TEMP_SENSORS_GPU, "ZES_TEMP_SENSORS_GPU"}, + {ZES_TEMP_SENSORS_MEMORY, "ZES_TEMP_SENSORS_MEMORY"}, + {ZES_TEMP_SENSORS_GLOBAL_MIN, "ZES_TEMP_SENSORS_GLOBAL_MIN"}, + {ZES_TEMP_SENSORS_GPU_MIN, "ZES_TEMP_SENSORS_GPU_MIN"}, + {ZES_TEMP_SENSORS_MEMORY_MIN, "ZES_TEMP_SENSORS_MEMORY_MIN"}}; + auto i = mgetSensorType.find(type); + if (i == mgetSensorType.end()) + return "NOT SUPPORTED MODE Engine avalialbe"; + else + return mgetSensorType.at(type); +} + void testSysmanTemperature(ze_device_handle_t &device) { std::cout << std::endl << " ---- Temperature tests ---- " << std::endl; @@ -207,10 +222,14 @@ void testSysmanTemperature(ze_device_handle_t &device) { VALIDATECALL(zesDeviceEnumTemperatureSensors(device, &count, handles.data())); for (const auto &handle : handles) { + zes_temp_properties_t properties = {}; + VALIDATECALL(zesTemperatureGetProperties(handle, &properties)); + double temperature; VALIDATECALL(zesTemperatureGetState(handle, &temperature)); if (verbose) { - std::cout << "temperature current state is: " << temperature << std::endl; + std::cout << "For subDevice " << properties.subdeviceId << " temperature current state for " + << getTemperatureSensorType(properties.type) << " is: " << temperature << std::endl; } } } diff --git a/level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h b/level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h index 53d76d388f..25af995a4d 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -31,10 +31,10 @@ class SysmanMockDrm : public Drm { class PublicLinuxSysmanImp : public L0::LinuxSysmanImp { public: + using LinuxSysmanImp::mapOfSubDeviceIdToPmtObject; using LinuxSysmanImp::pDrm; using LinuxSysmanImp::pFsAccess; using LinuxSysmanImp::pFwUtilInterface; - using LinuxSysmanImp::pPmt; using LinuxSysmanImp::pPmuInterface; using LinuxSysmanImp::pProcfsAccess; using LinuxSysmanImp::pSysfsAccess; diff --git a/level_zero/tools/test/unit_tests/sources/sysman/linux/test_sysman.cpp b/level_zero/tools/test/unit_tests/sources/sysman/linux/test_sysman.cpp index 99fc7c8ebb..39d964ae4e 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/linux/test_sysman.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/linux/test_sysman.cpp @@ -88,16 +88,6 @@ TEST_F(SysmanDeviceFixture, GivenInvalidPidWhenCallingProcfsAccessIsAliveThenErr EXPECT_FALSE(ProcfsAccess.isAlive(reinterpret_cast<::pid_t>(-1))); } -TEST_F(SysmanDeviceFixture, GivenPmtHandleWhenCallinggetPlatformMonitoringTechAccessThenCreatedPmtHandleWillBeRetrieved) { - if (pLinuxSysmanImp->pPmt != nullptr) { - //delete previously allocated pPmt - delete pLinuxSysmanImp->pPmt; - pLinuxSysmanImp->pPmt = nullptr; - } - pLinuxSysmanImp->pPmt = new PlatformMonitoringTech(); - EXPECT_EQ(&pLinuxSysmanImp->getPlatformMonitoringTechAccess(), pLinuxSysmanImp->pPmt); -} - TEST_F(SysmanDeviceFixture, GivenValidDeviceHandleThenSameHandleIsRetrievedFromOsSpecificCode) { EXPECT_EQ(pLinuxSysmanImp->getDeviceHandle(), device); } @@ -112,6 +102,18 @@ TEST_F(SysmanDeviceFixture, GivenPmuInterfaceHandleWhenCallinggetPmuInterfaceThe EXPECT_EQ(pLinuxSysmanImp->getPmuInterface(), pLinuxSysmanImp->pPmuInterface); } +TEST_F(SysmanDeviceFixture, GivenValidPciPathWhileGettingRootPciPortThenReturnedPathIs2LevelUpThenTheCurrentPath) { + const std::string mockBdf = "0000:00:02.0"; + const std::string mockRealPath = "/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/0000:02:01.0/" + mockBdf; + const std::string mockRealPath2LevelsUp = "/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0"; + + std::string pciRootPort1 = pLinuxSysmanImp->getPciRootPortDirectoryPath(mockRealPath); + EXPECT_EQ(pciRootPort1, mockRealPath2LevelsUp); + + std::string pciRootPort2 = pLinuxSysmanImp->getPciRootPortDirectoryPath("device"); + EXPECT_EQ(pciRootPort2, "device"); +} + TEST_F(SysmanMultiDeviceFixture, GivenValidDeviceHandleHavingSubdevicesWhenValidatingSysmanHandlesForSubdevicesThenSysmanHandleForSubdeviceWillBeSameAsSysmanHandleForDevice) { uint32_t count = 0; EXPECT_EQ(ZE_RESULT_SUCCESS, device->getSubDevices(&count, nullptr)); diff --git a/level_zero/tools/test/unit_tests/sources/sysman/pci/linux/mock_sysfs_pci.h b/level_zero/tools/test/unit_tests/sources/sysman/pci/linux/mock_sysfs_pci.h index 8b8009cfb3..6093b25d46 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/pci/linux/mock_sysfs_pci.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/pci/linux/mock_sysfs_pci.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -136,7 +136,6 @@ struct Mock : public PciSysfsAccess { class PublicLinuxPciImp : public L0::LinuxPciImp { public: - using LinuxPciImp::changeDirNLevelsUp; using LinuxPciImp::pfsAccess; using LinuxPciImp::pSysfsAccess; }; diff --git a/level_zero/tools/test/unit_tests/sources/sysman/pci/linux/test_zes_pci.cpp b/level_zero/tools/test/unit_tests/sources/sysman/pci/linux/test_zes_pci.cpp index 6037ad7c41..a1f6982ceb 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/pci/linux/test_zes_pci.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/pci/linux/test_zes_pci.cpp @@ -207,12 +207,6 @@ TEST_F(ZesPciFixture, GivenValidSysmanHandleWhenCallingzetSysmanPciGetBarsThenVe } } -TEST_F(ZesPciFixture, GivenValidPathWhileCallingchangeDirNLevelsUpThenReturnedPathIsNLevelUpThenTheCurrentPath) { - PublicLinuxPciImp *pOsPci = static_cast(pPciImp->pOsPci); - std::string testMockRealPath2LevelsUp = pOsPci->changeDirNLevelsUp(mockRealPath, 2); - EXPECT_EQ(testMockRealPath2LevelsUp, mockRealPath2LevelsUp); -} - TEST_F(ZesPciFixture, GivenValidSysmanHandleWhenCallingzetSysmanPciGetStateThenVerifyzetSysmanPciGetStateCallReturnNotSupported) { zes_pci_state_t state; EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesDevicePciGetState(device, &state)); 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 57c07e2bc7..dd9752221a 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 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -11,7 +11,7 @@ #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/linux/pmt/pmt.h" #include "sysman/power/power_imp.h" #include "sysman/sysman_imp.h" @@ -21,29 +21,90 @@ constexpr uint64_t setEnergyCounter = 83456; constexpr uint64_t offset = 0x400; constexpr uint64_t mappedLength = 2048; const std::string deviceName("device"); -FsAccess *pFsAccess = nullptr; -class PowerPmt : public PlatformMonitoringTech {}; +const std::string baseTelemSysFS("/sys/class/pmt_telemetry"); + +class PowerPmt : public PlatformMonitoringTech { + public: + PowerPmt(FsAccess *pFsAccess, ze_bool_t onSubdevice, uint32_t subdeviceId) : PlatformMonitoringTech(pFsAccess, onSubdevice, subdeviceId) {} + using PlatformMonitoringTech::keyOffsetMap; +}; template <> -struct Mock : public PlatformMonitoringTech { - Mock() = default; +struct Mock : public PowerPmt { ~Mock() override { - delete mappedMemory; - mappedMemory = nullptr; + if (mappedMemory != nullptr) { + delete mappedMemory; + mappedMemory = nullptr; + } + rootDeviceTelemNodeIndex = 0; } - void init(const std::string &deviceName, FsAccess *pFsAccess) override { + Mock(FsAccess *pFsAccess, ze_bool_t onSubdevice, uint32_t subdeviceId) : PowerPmt(pFsAccess, onSubdevice, subdeviceId) {} + + void mockedInit(FsAccess *pFsAccess) { mappedMemory = new char[mappedLength]; + std::string rootPciPathOfGpuDevice = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0"; + if (ZE_RESULT_SUCCESS != PlatformMonitoringTech::enumerateRootTelemIndex(pFsAccess, rootPciPathOfGpuDevice)) { + return; + } + // 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 PowerFsAccess : public FsAccess {}; + +template <> +struct Mock : public PowerFsAccess { + ze_result_t listDirectorySuccess(const std::string directory, std::vector &listOfTelemNodes) { + if (directory.compare(baseTelemSysFS) == 0) { + listOfTelemNodes.push_back("telem1"); + listOfTelemNodes.push_back("telem2"); + listOfTelemNodes.push_back("telem3"); + listOfTelemNodes.push_back("telem4"); + listOfTelemNodes.push_back("telem5"); + return ZE_RESULT_SUCCESS; + } + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + ze_result_t listDirectoryFailure(const std::string directory, std::vector &events) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + ze_result_t getRealPathSuccess(const std::string path, std::string &buf) { + if (path.compare("/sys/class/pmt_telemetry/telem1") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:86:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem1"; + } else if (path.compare("/sys/class/pmt_telemetry/telem2") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:86:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem2"; + } else if (path.compare("/sys/class/pmt_telemetry/telem3") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem3"; + } else if (path.compare("/sys/class/pmt_telemetry/telem4") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem4"; + } else if (path.compare("/sys/class/pmt_telemetry/telem5") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem5"; + } else { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + return ZE_RESULT_SUCCESS; + } + + ze_result_t getRealPathFailure(const std::string path, std::string &buf) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + MOCK_METHOD(ze_result_t, listDirectory, (const std::string path, std::vector &list), (override)); + MOCK_METHOD(ze_result_t, getRealPath, (const std::string path, std::string &buf), (override)); + Mock() = default; +}; + class PublicLinuxPowerImp : public L0::LinuxPowerImp { public: + PublicLinuxPowerImp(OsSysman *pOsSysman) : LinuxPowerImp(pOsSysman) {} using LinuxPowerImp::pPmt; }; } // namespace ult diff --git a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power.cpp b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power.cpp index f177294bb6..14d79496a1 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/power/linux/test_zes_power.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -18,21 +18,54 @@ namespace ult { constexpr uint64_t convertJouleToMicroJoule = 1000000u; constexpr uint32_t powerHandleComponentCount = 1u; +const std::map deviceKeyOffsetMapPower = { + {"PACKAGE_ENERGY", 0x400}, + {"COMPUTE_TEMPERATURES", 0x68}, + {"SOC_TEMPERATURES", 0x60}, + {"CORE_TEMPERATURES", 0x6c}}; + class SysmanDevicePowerFixture : public SysmanDeviceFixture { protected: + std::unique_ptr pPublicLinuxPowerImp; std::unique_ptr> pPmt; - PlatformMonitoringTech *pPmtOld = nullptr; + std::unique_ptr> pFsAccess; + FsAccess *pFsAccessOriginal = nullptr; + OsPower *pOsPowerOriginal = nullptr; + std::vector deviceHandles; void SetUp() override { SysmanDeviceFixture::SetUp(); - pPmtOld = pLinuxSysmanImp->pPmt; - pPmt = std::make_unique>>(); - pPmt->init(deviceName, pFsAccess); - pLinuxSysmanImp->pPmt = pPmt.get(); + pFsAccess = std::make_unique>>(); + pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + ON_CALL(*pFsAccess.get(), listDirectory(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::listDirectorySuccess)); + ON_CALL(*pFsAccess.get(), getRealPath(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::getRealPathSuccess)); + + uint32_t subDeviceCount = 0; + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr); + if (subDeviceCount == 0) { + deviceHandles.resize(1, device->toHandle()); + } else { + deviceHandles.resize(subDeviceCount, nullptr); + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data()); + } + + for (auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + auto pPmt = new NiceMock>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId); + pPmt->mockedInit(pFsAccess.get()); + pPmt->keyOffsetMap = deviceKeyOffsetMapPower; + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt); + } + pSysmanDeviceImp->pPowerHandleContext->init(); } void TearDown() override { SysmanDeviceFixture::TearDown(); - pLinuxSysmanImp->pPmt = pPmtOld; + pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; } std::vector get_power_handles(uint32_t count) { 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 4bd172941a..3b8b859f96 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 @@ -1,5 +1,5 @@ # -# Copyright (C) 2020 Intel Corporation +# Copyright (C) 2020-2021 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -8,7 +8,7 @@ if(UNIX) target_sources(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt - ${CMAKE_CURRENT_SOURCE_DIR}/test_zes_temperature.cpp + ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/test_zes_temperature.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_temperature.h ) endif() 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 64d4790943..7323a8b95c 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 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -8,49 +8,119 @@ #pragma once #include "level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h" -#include "sysman/linux/pmt.h" +#include "sysman/linux/pmt/pmt.h" #include "sysman/temperature/temperature_imp.h" 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 uint8_t tempArrForSubDevices[28] = {0x12, 0, 0, 0, 0, 0, 0, 0, 0x45, 0, 0, 0, 0x6f, 0, 0, 0, 0x34, 0, 0, 0, 0x16, 0, 0, 0, 0x1d, 0, 0, 0}; +constexpr uint64_t offsetForSubDevices = 28; +constexpr uint8_t memory0MaxTempIndex = 0; +constexpr uint8_t memory1MaxTempIndex = 8; +constexpr uint8_t subDeviceMinTempIndex = 12; +constexpr uint8_t subDeviceMaxTempIndex = 16; +constexpr uint8_t gtMinTempIndex = 20; +constexpr uint8_t gtMaxTempIndex = 24; + +constexpr uint8_t tempArrForNoSubDevices[19] = {0x12, 0x23, 0x43, 0xde, 0xa3, 0xce, 0x23, 0x11, 0x45, 0x32, 0x67, 0x47, 0xac, 0x21, 0x03, 0x90, 0, 0, 0}; +constexpr uint64_t offsetForNoSubDevices = 0x60; +constexpr uint8_t computeIndexForNoSubDevices = 9; +constexpr uint8_t globalIndexForNoSubDevices = 3; + constexpr uint64_t mappedLength = 256; +const std::string baseTelemSysFS("/sys/class/pmt_telemetry"); class TemperaturePmt : public PlatformMonitoringTech { public: + TemperaturePmt(FsAccess *pFsAccess, ze_bool_t onSubdevice, uint32_t subdeviceId) : PlatformMonitoringTech(pFsAccess, onSubdevice, subdeviceId) {} + using PlatformMonitoringTech::keyOffsetMap; using PlatformMonitoringTech::mappedMemory; }; template <> struct Mock : public TemperaturePmt { - Mock() = default; + Mock(FsAccess *pFsAccess, ze_bool_t onSubdevice, uint32_t subdeviceId) : TemperaturePmt(pFsAccess, onSubdevice, subdeviceId) {} ~Mock() override { if (mappedMemory != nullptr) { delete mappedMemory; mappedMemory = nullptr; } + rootDeviceTelemNodeIndex = 0; } - void setVal(bool val) { - isPmtSupported = val; - } - - void init(const std::string &deviceName, FsAccess *pFsAccess) override { + void mockedInit(FsAccess *pFsAccess) { mappedMemory = new char[mappedLength]; - for (uint64_t i = 0; i < sizeof(tempArr) / sizeof(uint8_t); i++) { - mappedMemory[offsetCompute + i] = tempArr[i]; + std::string rootPciPathOfGpuDevice = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0"; + if (ZE_RESULT_SUCCESS != PlatformMonitoringTech::enumerateRootTelemIndex(pFsAccess, rootPciPathOfGpuDevice)) { + return; + } + // Fill mappedMemory to validate cases when there are subdevices + for (uint64_t i = 0; i < sizeof(tempArrForSubDevices) / sizeof(uint8_t); i++) { + mappedMemory[offsetForSubDevices + i] = tempArrForSubDevices[i]; + } + // Fill mappedMemory to validate cases when there are no subdevices + for (uint64_t i = 0; i < sizeof(tempArrForNoSubDevices) / sizeof(uint8_t); i++) { + mappedMemory[offsetForNoSubDevices + i] = tempArrForNoSubDevices[i]; } - pmtSupported = isPmtSupported; } - private: - bool isPmtSupported = false; + void mockedInitWithoutMappedMemory(FsAccess *pFsAccess) { + std::string rootPciPathOfGpuDevice = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0"; + if (ZE_RESULT_SUCCESS != PlatformMonitoringTech::enumerateRootTelemIndex(pFsAccess, rootPciPathOfGpuDevice)) { + return; + } + } +}; + +class TemperatureFsAccess : public FsAccess {}; + +template <> +struct Mock : public TemperatureFsAccess { + ze_result_t listDirectorySuccess(const std::string directory, std::vector &listOfTelemNodes) { + if (directory.compare(baseTelemSysFS) == 0) { + listOfTelemNodes.push_back("telem1"); + listOfTelemNodes.push_back("telem2"); + listOfTelemNodes.push_back("telem3"); + listOfTelemNodes.push_back("telem4"); + listOfTelemNodes.push_back("telem5"); + return ZE_RESULT_SUCCESS; + } + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + ze_result_t listDirectoryFailure(const std::string directory, std::vector &events) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + ze_result_t getRealPathSuccess(const std::string path, std::string &buf) { + if (path.compare("/sys/class/pmt_telemetry/telem1") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:86:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem1"; + } else if (path.compare("/sys/class/pmt_telemetry/telem2") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:86:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem2"; + } else if (path.compare("/sys/class/pmt_telemetry/telem3") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem3"; + } else if (path.compare("/sys/class/pmt_telemetry/telem4") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem4"; + } else if (path.compare("/sys/class/pmt_telemetry/telem5") == 0) { + buf = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8e:00.1/pmt_telemetry/telem5"; + } else { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + return ZE_RESULT_SUCCESS; + } + + ze_result_t getRealPathFailure(const std::string path, std::string &buf) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + MOCK_METHOD(ze_result_t, listDirectory, (const std::string path, std::vector &list), (override)); + MOCK_METHOD(ze_result_t, getRealPath, (const std::string path, std::string &buf), (override)); + Mock() = default; }; class PublicLinuxTemperatureImp : public L0::LinuxTemperatureImp { public: + PublicLinuxTemperatureImp(OsSysman *pOsSysman, ze_bool_t onSubdevice, uint32_t subdeviceId) : LinuxTemperatureImp(pOsSysman, onSubdevice, subdeviceId) {} using LinuxTemperatureImp::pPmt; 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 deleted file mode 100644 index a28a06ba23..0000000000 --- a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_sysman_temperature.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2020 Intel Corporation - * - * SPDX-License-Identifier: MIT - * - */ - -#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" -#include "level_zero/tools/source/sysman/sysman_imp.h" -#include "level_zero/tools/source/sysman/temperature/linux/os_temperature_imp.h" - -#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; - 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()); - 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; - linuxTemperatureImp[i].setSensorType(static_cast(i)); - OsTemperature *pOsTemperature = static_cast(&linuxTemperatureImp[i]); - pTemperatureImp[i] = new TemperatureImp(); - pTemperatureImp[i]->pOsTemperature = pOsTemperature; - pTemperatureImp[i]->init(); - sysmanImp->pTempHandleContext->handleList.push_back(pTemperatureImp[i]); - hSysmanTempHandle[i] = pTemperatureImp[i]->toZetHandle(); - } - hSysman = sysmanImp->toHandle(); - } - void TearDown() override { - // 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, GivenComponentCountZeroWhenCallingZetSysmanTemperatureGetThenZeroCountIsReturnedAndVerifySysmanTemperatureGetCallSucceeds) { - uint32_t count = 0; - ze_result_t result = zetSysmanTemperatureGet(hSysman, &count, NULL); - EXPECT_EQ(ZE_RESULT_SUCCESS, result); - 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; - linuxTemperatureImp[0].setSensorType(ZET_TEMP_SENSORS_MEMORY); - OsTemperature *pOsTemperatureTest1 = static_cast(&linuxTemperatureImp[0]); - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsTemperatureTest1->getSensorTemperature(&pTemperature)); - - linuxTemperatureImp[1].setSensorType(ZET_TEMP_SENSORS_MEMORY); - OsTemperature *pOsTemperatureTest2 = static_cast(&linuxTemperatureImp[1]); - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pOsTemperatureTest2->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()); -} - -class ZetPublicLinuxSysmanImpTemperature : public L0::LinuxSysmanImp { - public: - using LinuxSysmanImp::pPmt; - ZetPublicLinuxSysmanImpTemperature(SysmanImp *pParentSysmanImp) : LinuxSysmanImp(pParentSysmanImp) {} -}; - -TEST_F(SysmanTemperatureFixture, GivenOsSysmanPointerWhenCreatingOsTemperaturePointerThenValidOsTemperatureIsCreated) { - auto pLinuxSysmanImpTest = std::make_unique(sysmanImp.get()); - pLinuxSysmanImpTest->pPmt = new PlatformMonitoringTech(); - auto pOsSysmanTest = static_cast(pLinuxSysmanImpTest.get()); - auto pOsTemperatureTest = OsTemperature::create(pOsSysmanTest, ZES_TEMP_SENSORS_GLOBAL); - EXPECT_NE(pOsTemperatureTest, nullptr); - delete pOsTemperatureTest; -} - -} // namespace ult -} // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_zes_temperature.cpp b/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_zes_temperature.cpp index da7f0dc2aa..18e67add9c 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_zes_temperature.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/temperature/linux/test_zes_temperature.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -10,25 +10,58 @@ namespace L0 { namespace ult { -constexpr uint32_t handleComponentCount = 3u; -const std::string deviceName("testDevice"); -FsAccess *pFsAccessTemp = nullptr; -class SysmanDeviceTemperatureFixture : public SysmanDeviceFixture { +std::string rootPciPathOfGpuDevice = "/sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0"; +constexpr uint32_t handleComponentCountForSubDevices = 10u; +constexpr uint32_t handleComponentCountForNoSubDevices = 2u; +constexpr uint32_t invalidMaxTemperature = 125; +constexpr uint32_t invalidMinTemperature = 10; + +const std::map deviceKeyOffsetMapTemperature = { + {"PACKAGE_ENERGY", 0x420}, + {"COMPUTE_TEMPERATURES", 0x68}, + {"SOC_TEMPERATURES", 0x60}, + {"CORE_TEMPERATURES", 0x6c}}; + +class SysmanMultiDeviceTemperatureFixture : public SysmanMultiDeviceFixture { protected: - std::unique_ptr> pPmt; - PlatformMonitoringTech *pPmtOld = nullptr; + std::unique_ptr pPublicLinuxTemperatureImp; + std::unique_ptr> pFsAccess; + FsAccess *pFsAccessOriginal = nullptr; + std::vector deviceHandles; void SetUp() override { - SysmanDeviceFixture::SetUp(); - pPmtOld = pLinuxSysmanImp->pPmt; - pPmt = std::make_unique>>(); - pPmt->setVal(true); - pPmt->init(deviceName, pFsAccessTemp); - pLinuxSysmanImp->pPmt = pPmt.get(); - pSysmanDeviceImp->pTempHandleContext->init(); + SysmanMultiDeviceFixture::SetUp(); + pFsAccess = std::make_unique>>(); + pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + ON_CALL(*pFsAccess.get(), listDirectory(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::listDirectorySuccess)); + ON_CALL(*pFsAccess.get(), getRealPath(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::getRealPathSuccess)); + + uint32_t subDeviceCount = 0; + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr); + if (subDeviceCount == 0) { + deviceHandles.resize(1, device->toHandle()); + } else { + deviceHandles.resize(subDeviceCount, nullptr); + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data()); + } + + for (auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + auto pPmt = new NiceMock>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId); + pPmt->mockedInit(pFsAccess.get()); + pPmt->keyOffsetMap = deviceKeyOffsetMapTemperature; + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt); + } + + pSysmanDeviceImp->pTempHandleContext->init(deviceHandles); } void TearDown() override { - SysmanDeviceFixture::TearDown(); - pLinuxSysmanImp->pPmt = pPmtOld; + SysmanMultiDeviceFixture::TearDown(); + pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; } std::vector get_temp_handles(uint32_t count) { @@ -38,101 +71,214 @@ class SysmanDeviceTemperatureFixture : public SysmanDeviceFixture { } }; -TEST_F(SysmanDeviceTemperatureFixture, GivenComponentCountZeroWhenCallingZetSysmanTemperatureGetThenZeroCountIsReturnedAndVerifySysmanTemperatureGetCallSucceeds) { +TEST_F(SysmanMultiDeviceTemperatureFixture, GivenComponentCountZeroWhenCallingZetSysmanTemperatureGetThenZeroCountIsReturnedAndVerifySysmanTemperatureGetCallSucceeds) { uint32_t count = 0; ze_result_t result = zesDeviceEnumTemperatureSensors(device->toHandle(), &count, NULL); EXPECT_EQ(ZE_RESULT_SUCCESS, result); - EXPECT_EQ(count, handleComponentCount); + EXPECT_EQ(count, handleComponentCountForSubDevices); uint32_t testcount = count + 1; result = zesDeviceEnumTemperatureSensors(device->toHandle(), &testcount, NULL); EXPECT_EQ(ZE_RESULT_SUCCESS, result); - EXPECT_EQ(testcount, handleComponentCount); + EXPECT_EQ(testcount, handleComponentCountForSubDevices); count = 0; std::vector handles(count, nullptr); EXPECT_EQ(zesDeviceEnumTemperatureSensors(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); - EXPECT_EQ(count, handleComponentCount); + EXPECT_EQ(count, handleComponentCountForSubDevices); } -TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingGPUTemperatureThenValidTemperatureReadingsRetrieved) { - auto handles = get_temp_handles(handleComponentCount); - double temperature; - ASSERT_EQ(ZE_RESULT_SUCCESS, zesTemperatureGetState(handles[1], &temperature)); - EXPECT_EQ(temperature, static_cast(tempArr[computeIndex])); -} - -TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingGlobalTemperatureThenValidTemperatureReadingsRetrieved) { - auto handles = get_temp_handles(handleComponentCount); - double temperature; - ASSERT_EQ(ZE_RESULT_SUCCESS, zesTemperatureGetState(handles[0], &temperature)); - EXPECT_EQ(temperature, static_cast(tempArr[globalIndex])); -} - -TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingUnsupportedSensorsTemperatureThenUnsupportedReturned) { - auto pTemperatureImpMemory = std::make_unique(pOsSysman, ZES_TEMP_SENSORS_GLOBAL_MIN); - auto pLinuxTemperatureImpMemory = static_cast(pTemperatureImpMemory->pOsTemperature); - double pTemperature = 0; - EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pLinuxTemperatureImpMemory->getSensorTemperature(&pTemperature)); -} - -TEST_F(SysmanDeviceTemperatureFixture, 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 *pFsAccessTemp = nullptr; - pPmt->init(deviceName, pFsAccessTemp); - auto handles = get_temp_handles(handleComponentCount); - for (auto handle : handles) { - auto pTemperatureImpTest = static_cast(L0::Temperature::fromHandle(handle)); - EXPECT_FALSE(pTemperatureImpTest->pOsTemperature->isTempModuleSupported()); - } -} - -TEST_F(SysmanDeviceTemperatureFixture, 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 *pFsAccessTemp = nullptr; - pPmt->init(deviceName, pFsAccessTemp); - auto handles = get_temp_handles(handleComponentCount); - for (auto handle : handles) { - auto pTemperatureImpTest = static_cast(L0::Temperature::fromHandle(handle)); - EXPECT_TRUE(pTemperatureImpTest->pOsTemperature->isTempModuleSupported()); - } -} - -TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingTemperaturePropertiesThenUnsupportedIsReturned) { - auto handles = get_temp_handles(handleComponentCount); +TEST_F(SysmanMultiDeviceTemperatureFixture, GivenValidTempHandleWhenGettingTemperatureThenValidTemperatureReadingsRetrieved) { + auto handles = get_temp_handles(handleComponentCountForSubDevices); for (auto handle : handles) { zes_temp_properties_t properties = {}; EXPECT_EQ(ZE_RESULT_SUCCESS, zesTemperatureGetProperties(handle, &properties)); - EXPECT_FALSE(properties.onSubdevice); - EXPECT_EQ(properties.subdeviceId, 0u); + double temperature; + ASSERT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesTemperatureGetState(handle, &temperature)); } } -TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingTemperatureConfigThenUnsupportedIsReturned) { - auto handles = get_temp_handles(handleComponentCount); +TEST_F(SysmanMultiDeviceTemperatureFixture, GivenValidTempHandleWhenGettingTemperatureConfigThenUnsupportedIsReturned) { + auto handles = get_temp_handles(handleComponentCountForSubDevices); 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 = get_temp_handles(handleComponentCount); +TEST_F(SysmanMultiDeviceTemperatureFixture, GivenValidTempHandleWhenSettingTemperatureConfigThenUnsupportedIsReturned) { + auto handles = get_temp_handles(handleComponentCountForSubDevices); for (auto handle : handles) { zes_temp_config_t config = {}; EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesTemperatureSetConfig(handle, &config)); } } +TEST_F(SysmanMultiDeviceTemperatureFixture, GivenCreatePmtObjectsWhenRootTileIndexEnumeratesSuccessfulThenValidatePmtObjectsReceivedAndBranches) { + std::map mapOfSubDeviceIdToPmtObject; + PlatformMonitoringTech::create(deviceHandles, pFsAccess.get(), rootPciPathOfGpuDevice, mapOfSubDeviceIdToPmtObject); + uint32_t deviceHandlesIndex = 0; + for (auto &subDeviceIdToPmtEntry : mapOfSubDeviceIdToPmtObject) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(deviceHandles[deviceHandlesIndex++])->getProperties(&deviceProperties); + EXPECT_NE(subDeviceIdToPmtEntry.second, nullptr); + EXPECT_EQ(subDeviceIdToPmtEntry.first, deviceProperties.subdeviceId); + delete subDeviceIdToPmtEntry.second; // delete memory to avoid mem leak here, as we finished our test validation just above. + } +} + +class SysmanDeviceTemperatureFixture : public SysmanDeviceFixture { + protected: + std::unique_ptr pPublicLinuxTemperatureImp; + std::unique_ptr> pFsAccess; + FsAccess *pFsAccessOriginal = nullptr; + std::vector deviceHandles; + void SetUp() override { + SysmanDeviceFixture::SetUp(); + pFsAccess = std::make_unique>>(); + pFsAccessOriginal = pLinuxSysmanImp->pFsAccess; + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + ON_CALL(*pFsAccess.get(), listDirectory(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::listDirectorySuccess)); + ON_CALL(*pFsAccess.get(), getRealPath(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::getRealPathSuccess)); + + uint32_t subDeviceCount = 0; + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr); + if (subDeviceCount == 0) { + deviceHandles.resize(1, device->toHandle()); + } else { + deviceHandles.resize(subDeviceCount, nullptr); + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data()); + } + + for (auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + auto pPmt = new NiceMock>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId); + pPmt->mockedInit(pFsAccess.get()); + pPmt->keyOffsetMap = deviceKeyOffsetMapTemperature; + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt); + } + + pSysmanDeviceImp->pTempHandleContext->init(deviceHandles); + } + void TearDown() override { + SysmanDeviceFixture::TearDown(); + pLinuxSysmanImp->pFsAccess = pFsAccessOriginal; + } + + std::vector get_temp_handles(uint32_t count) { + std::vector handles(count, nullptr); + EXPECT_EQ(zesDeviceEnumTemperatureSensors(device->toHandle(), &count, handles.data()), ZE_RESULT_SUCCESS); + return handles; + } +}; + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingGPUAndGlobalTemperatureThenValidTemperatureReadingsRetrieved) { + auto handles = get_temp_handles(handleComponentCountForNoSubDevices); + for (auto &handle : handles) { + zes_temp_properties_t properties = {}; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesTemperatureGetProperties(handle, &properties)); + double temperature; + ASSERT_EQ(ZE_RESULT_SUCCESS, zesTemperatureGetState(handle, &temperature)); + if (properties.type == ZES_TEMP_SENSORS_GLOBAL) { + uint8_t maxTemp = 0; + for (uint64_t i = 0; i < sizeof(tempArrForNoSubDevices) / sizeof(uint8_t); i++) { + if ((tempArrForNoSubDevices[i] > invalidMaxTemperature) || + (tempArrForNoSubDevices[i] < invalidMinTemperature) || (maxTemp > tempArrForNoSubDevices[i])) { + continue; + } + maxTemp = tempArrForNoSubDevices[i]; + } + EXPECT_EQ(temperature, static_cast(maxTemp)); + } + if (properties.type == ZES_TEMP_SENSORS_GPU) { + EXPECT_EQ(temperature, static_cast(tempArrForNoSubDevices[computeIndexForNoSubDevices])); + } + } +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleAndPmtReadValueFailsWhenGettingTemperatureThenFailureReturned) { + // delete previously allocated pPmt objects + for (auto &subDeviceIdToPmtEntry : pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject) { + delete subDeviceIdToPmtEntry.second; + } + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.clear(); + // delete previously created temp handles + for (auto &handle : pSysmanDeviceImp->pTempHandleContext->handleList) { + delete handle; + handle = nullptr; + pSysmanDeviceImp->pTempHandleContext->handleList.pop_back(); + } + for (auto &deviceHandle : deviceHandles) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(deviceHandle)->getProperties(&deviceProperties); + auto pPmt = new NiceMock>(pFsAccess.get(), deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId); + pPmt->mockedInitWithoutMappedMemory(pFsAccess.get()); + pPmt->keyOffsetMap = deviceKeyOffsetMapTemperature; + pLinuxSysmanImp->mapOfSubDeviceIdToPmtObject.emplace(deviceProperties.subdeviceId, pPmt); + } + + pSysmanDeviceImp->pTempHandleContext->init(deviceHandles); + auto handles = get_temp_handles(handleComponentCountForNoSubDevices); + for (auto &handle : handles) { + double temperature; + ASSERT_EQ(ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE, zesTemperatureGetState(handle, &temperature)); + } +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingUnsupportedSensorsTemperatureThenUnsupportedReturned) { + ze_device_properties_t deviceProperties = {}; + Device::fromHandle(device->toHandle())->getProperties(&deviceProperties); + auto pPublicLinuxTemperatureImp = std::make_unique(pOsSysman, deviceProperties.flags & ZE_DEVICE_PROPERTY_FLAG_SUBDEVICE, + deviceProperties.subdeviceId); + pPublicLinuxTemperatureImp->setSensorType(ZES_TEMP_SENSORS_MEMORY_MIN); + double temperature; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, pPublicLinuxTemperatureImp->getSensorTemperature(&temperature)); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidateEnumerateRootTelemIndexWhengetRealPathFailsThenFailureReturned) { + ON_CALL(*pFsAccess.get(), getRealPath(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::getRealPathFailure)); + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, + PlatformMonitoringTech::enumerateRootTelemIndex(pFsAccess.get(), rootPciPathOfGpuDevice)); + + ON_CALL(*pFsAccess.get(), listDirectory(_, _)) + .WillByDefault(::testing::Invoke(pFsAccess.get(), &Mock::listDirectoryFailure)); + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, + PlatformMonitoringTech::enumerateRootTelemIndex(pFsAccess.get(), rootPciPathOfGpuDevice)); + + std::map mapOfSubDeviceIdToPmtObject; + PlatformMonitoringTech::create(deviceHandles, pFsAccess.get(), rootPciPathOfGpuDevice, mapOfSubDeviceIdToPmtObject); + EXPECT_TRUE(mapOfSubDeviceIdToPmtObject.empty()); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenValidatePmtReadValueWhenkeyOffsetMapIsNotThereThenFailureReturned) { + auto pPmt = std::make_unique>>(pFsAccess.get(), 0, 0); + pPmt->mockedInit(pFsAccess.get()); + pPmt->keyOffsetMap = deviceKeyOffsetMapTemperature; + uint8_t val = 0; + EXPECT_EQ(ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE, pPmt->readValue("SOMETHING", val)); +} + +TEST_F(SysmanDeviceTemperatureFixture, GivenCreatePmtObjectsWhenRootTileIndexEnumeratesSuccessfulThenValidatePmtObjectsReceivedAndBranches) { + std::map mapOfSubDeviceIdToPmtObject1; + PlatformMonitoringTech::create(deviceHandles, pFsAccess.get(), rootPciPathOfGpuDevice, mapOfSubDeviceIdToPmtObject1); + for (auto &subDeviceIdToPmtEntry : mapOfSubDeviceIdToPmtObject1) { + EXPECT_NE(subDeviceIdToPmtEntry.second, nullptr); + EXPECT_EQ(subDeviceIdToPmtEntry.first, 0u); // We know that subdeviceID is zero as core device didnt have any subdevices + delete subDeviceIdToPmtEntry.second; // delete memory to avoid mem leak here, as we finished our test validation just above. + } + + std::map mapOfSubDeviceIdToPmtObject2; + std::vector testHandleVector; + // If empty device handle vector is provided then empty map is retrieved + PlatformMonitoringTech::create(testHandleVector, pFsAccess.get(), rootPciPathOfGpuDevice, mapOfSubDeviceIdToPmtObject2); + EXPECT_TRUE(mapOfSubDeviceIdToPmtObject2.empty()); +} + } // namespace ult } // namespace L0 diff --git a/level_zero/tools/test/unit_tests/sources/sysman/temperature/windows/test_zes_temperature.cpp b/level_zero/tools/test/unit_tests/sources/sysman/temperature/windows/test_zes_temperature.cpp index c18b4ce993..0b15e3a41d 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/temperature/windows/test_zes_temperature.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/temperature/windows/test_zes_temperature.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -18,6 +18,7 @@ class SysmanDeviceTemperatureFixture : public SysmanDeviceFixture { protected: Mock *pKmdSysManager = nullptr; KmdSysManager *pOriginalKmdSysManager = nullptr; + std::vector deviceHandles; void SetUp() override { SysmanDeviceFixture::SetUp(); @@ -34,7 +35,16 @@ class SysmanDeviceTemperatureFixture : public SysmanDeviceFixture { } pSysmanDeviceImp->pTempHandleContext->handleList.clear(); - pSysmanDeviceImp->pTempHandleContext->init(); + uint32_t subDeviceCount = 0; + // We received a device handle. Check for subdevices in this device + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, nullptr); + if (subDeviceCount == 0) { + deviceHandles.resize(1, device->toHandle()); + } else { + deviceHandles.resize(subDeviceCount, nullptr); + Device::fromHandle(device->toHandle())->getSubDevices(&subDeviceCount, deviceHandles.data()); + } + pSysmanDeviceImp->pTempHandleContext->init(deviceHandles); } void TearDown() override { SysmanDeviceFixture::TearDown(); @@ -121,8 +131,8 @@ TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingGlobalTemp } TEST_F(SysmanDeviceTemperatureFixture, GivenValidTempHandleWhenGettingUnsupportedSensorsTemperatureThenUnsupportedReturned) { - auto pTemperatureImpMemory = std::make_unique(pOsSysman, ZES_TEMP_SENSORS_GLOBAL_MIN); - auto pWddmTemperatureImp = static_cast(pTemperatureImpMemory->pOsTemperature); + auto pTemperatureImpMemory = std::make_unique(deviceHandles[0], pOsSysman, 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)); }