diff options
author | cyang29 <cheng.c.yang@intel.com> | 2018-10-17 17:38:41 +0300 |
---|---|---|
committer | cyang29 <cheng.c.yang@intel.com> | 2018-10-17 17:38:41 +0300 |
commit | aeb90faa6c3e0cdfea9a1b3605f60673fcdff960 (patch) | |
tree | 35f4b20ea2c1ea46bed89859dfb5bbad65d5f5c0 /services | |
parent | 5503c09b879b4baf5cd94c70dbf0856766bade20 (diff) | |
download | provingground-aeb90faa6c3e0cdfea9a1b3605f60673fcdff960.tar.xz |
Add CPU dbus service for MDR V2
Add all CPU information in smbios table and provide dbus
interface for redfish to get CPU information.
Change-Id: I86e3e4b8022e1b211e7a946bb896314b710a0df2
Signed-off-by: cyang29 <cheng.c.yang@intel.com>
Diffstat (limited to 'services')
-rw-r--r-- | services/smbios-mdrv2/CMakeLists.txt | 2 | ||||
-rw-r--r-- | services/smbios-mdrv2/include/cpu.hpp | 173 | ||||
-rw-r--r-- | services/smbios-mdrv2/include/mdrv2.hpp | 6 | ||||
-rw-r--r-- | services/smbios-mdrv2/include/smbios-mdrv2.hpp | 110 | ||||
-rw-r--r-- | services/smbios-mdrv2/src/cpu.cpp | 207 | ||||
-rw-r--r-- | services/smbios-mdrv2/src/mdrv2.cpp | 55 |
6 files changed, 552 insertions, 1 deletions
diff --git a/services/smbios-mdrv2/CMakeLists.txt b/services/smbios-mdrv2/CMakeLists.txt index 8cdf8a9..b707347 100644 --- a/services/smbios-mdrv2/CMakeLists.txt +++ b/services/smbios-mdrv2/CMakeLists.txt @@ -31,7 +31,7 @@ pkg_check_modules (DBUSINTERFACE phosphor-dbus-interfaces REQUIRED) include_directories (${DBUSINTERFACE_INCLUDE_DIRS}) link_directories (${DBUSINTERFACE_LIBRARY_DIRS}) -set (SRC_FILES src/mdrv2.cpp src/smbios-mdrv2-main.cpp) +set (SRC_FILES src/mdrv2.cpp src/smbios-mdrv2-main.cpp src/cpu.cpp) include_directories (${CMAKE_CURRENT_BINARY_DIR}) diff --git a/services/smbios-mdrv2/include/cpu.hpp b/services/smbios-mdrv2/include/cpu.hpp new file mode 100644 index 0000000..3b12c41 --- /dev/null +++ b/services/smbios-mdrv2/include/cpu.hpp @@ -0,0 +1,173 @@ +/* +// Copyright (c) 2018 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#pragma once +#include "smbios-mdrv2.hpp" + +#include <xyz/openbmc_project/Inventory/Item/Cpu/server.hpp> + +namespace phosphor +{ + +namespace smbios +{ + +// Definition follow smbios spec DSP0134 3.0.0 +static const std::map<uint8_t, std::string> processorTypeTable = { + {0x1, "Other"}, {0x2, "Unknown"}, {0x3, "Central Processor"}, + {0x4, "Math Processor"}, {0x5, "DSP Processor"}, {0x6, "Video Processor"}, +}; + +// Definition follow smbios spec DSP0134 3.0.0 +static const std::map<uint8_t, std::string> familyTable = { + {0x1, "Other"}, + {0x2, "Unknown"}, + {0x10, "Pentium II Xeon processor"}, + {0xa1, "Quad-Core Intel Xeon processor 3200 Series"}, + {0xa2, "Dual-Core Intel Xeon processor 3000 Series"}, + {0xa3, "Quad-Core Intel Xeon processor 5300 Series"}, + {0xa4, "Dual-Core Intel Xeon processor 5100 Series"}, + {0xa5, "Dual-Core Intel Xeon processor 5000 Series"}, + {0xa6, "Dual-Core Intel Xeon processor LV"}, + {0xa7, "Dual-Core Intel Xeon processor ULV"}, + {0xa8, "Dual-Core Intel Xeon processor 7100 Series"}, + {0xa9, "Quad-Core Intel Xeon processor 5400 Series"}, + {0xaa, "Quad-Core Intel Xeon processor"}, + {0xab, "Dual-Core Intel Xeon processor 5200 Series"}, + {0xac, "Dual-Core Intel Xeon processor 7200 Series"}, + {0xad, "Quad-Core Intel Xeon processor 7300 Series"}, + {0xae, "Quad-Core Intel Xeon processor 7400 Series"}, + {0xaf, "Multi-Core Intel Xeon processor 7400 Series"}, + {0xb0, "Pentium III Xeon processor"}, + {0xb3, "Intel Xeon processor"}, + {0xb5, "Intel Xeon processor MP"}, + {0xd6, "Multi-Core Intel Xeon processor"}, + {0xd7, "Dual-Core Intel Xeon processor 3xxx Series"}, + {0xd8, "Quad-Core Intel Xeon processor 3xxx Series"}, + {0xd9, "VIA Nano Processor Family"}, + {0xda, "Dual-Core Intel Xeon processor 5xxx Series"}, + {0xdb, "Quad-Core Intel Xeon processor 5xxx Series"}, + {0xdd, "Dual-Core Intel Xeon processor 7xxx Series"}, + {0xde, "Quad-Core Intel Xeon processor 7xxx Series"}, + {0xdf, "Multi-Core Intel Xeon processor 7xxx Series"}, + {0xe0, "Multi-Core Intel Xeon processor 3400 Series"} + +}; + +// Definition follow smbios spec DSP0134 3.0.0 +static const std::string characteristicsTable[16]{"Reserved", + "Unknown", + "64-bit Capable", + "Multi-Core", + "Hardware Thread", + "Execute Protection", + "Enhanced Virtualization", + "Power/Performance Control", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Reserved"}; + +class Cpu : sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu> +{ + public: + Cpu() = delete; + Cpu(const Cpu &) = delete; + Cpu &operator=(const Cpu &) = delete; + Cpu(Cpu &&) = delete; + Cpu &operator=(Cpu &&) = delete; + ~Cpu() = default; + + Cpu(sdbusplus::bus::bus &bus, const std::string &objPath, + const uint8_t &cpuId, uint8_t *smbiosTableStorage) : + sdbusplus::server::object::object< + sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu>( + bus, objPath.c_str()), + cpuNum(cpuId), storage(smbiosTableStorage) + { + processorInfoUpdate(); + } + + void processorInfoUpdate(void); + + std::string processorSocket(std::string value) override; + std::string processorType(std::string value) override; + std::string processorFamily(std::string value) override; + std::string processorManufacturer(std::string value) override; + uint32_t processorId(uint32_t value) override; + std::string processorVersion(std::string value) override; + uint16_t processorMaxSpeed(uint16_t value) override; + std::string processorCharacteristics(std::string value) override; + uint16_t processorCoreCount(uint16_t value) override; + uint16_t processorThreadCount(uint16_t value) override; + + private: + uint8_t cpuNum; + + uint8_t *storage; + + struct ProcessorInfo + { + uint8_t type; + uint8_t length; + uint16_t handle; + uint8_t socketDesignation; + uint8_t processorType; + uint8_t family; + uint8_t manufacturer; + uint64_t id; + uint8_t version; + uint8_t voltage; + uint16_t exClock; + uint16_t maxSpeed; + uint16_t currSpeed; + uint8_t status; + uint8_t upgrade; + uint16_t l1Handle; + uint16_t l2Handle; + uint16_t l3Handle; + uint8_t serialNum; + uint8_t assetTag; + uint8_t partNum; + uint8_t coreCount; + uint8_t coreEnable; + uint8_t threadCount; + uint16_t characteristics; + uint16_t family2; + uint16_t coreCount2; + uint16_t coreEnable2; + uint16_t threadCount2; + } __attribute__((packed)); + + void cpuSocket(const uint8_t positionNum, const uint8_t structLen, + uint8_t *dataIn); + void cpuType(const uint8_t value); + void cpuFamily(const uint8_t value); + void cpuManufacturer(const uint8_t positionNum, const uint8_t structLen, + uint8_t *dataIn); + void cpuVersion(const uint8_t positionNum, const uint8_t structLen, + uint8_t *dataIn); + void cpuCharacteristics(const uint16_t value); +}; + +} // namespace smbios + +} // namespace phosphor diff --git a/services/smbios-mdrv2/include/mdrv2.hpp b/services/smbios-mdrv2/include/mdrv2.hpp index 3a4bb23..dbb4b10 100644 --- a/services/smbios-mdrv2/include/mdrv2.hpp +++ b/services/smbios-mdrv2/include/mdrv2.hpp @@ -15,6 +15,7 @@ */ #pragma once +#include "cpu.hpp" #include "smbios-mdrv2.hpp" #include <sys/stat.h> @@ -33,6 +34,7 @@ namespace smbios { static constexpr const char *mdrV2Path = "/xyz/openbmc_project/Smbios/MDR_V2"; +constexpr const int limitEntryLen = 0xff; class MDR_V2 : sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V2 { @@ -103,6 +105,10 @@ class MDR_V2 : sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V2 bool smbiosIsUpdating(uint8_t index); bool smbiosIsAvailForUpdate(uint8_t index); inline uint8_t smbiosValidFlag(uint8_t index); + void systemInfoUpdate(void); + + int getTotalCpuSlot(void); + std::vector<std::unique_ptr<Cpu>> cpus; }; } // namespace smbios diff --git a/services/smbios-mdrv2/include/smbios-mdrv2.hpp b/services/smbios-mdrv2/include/smbios-mdrv2.hpp index 9591e78..b468ece 100644 --- a/services/smbios-mdrv2/include/smbios-mdrv2.hpp +++ b/services/smbios-mdrv2/include/smbios-mdrv2.hpp @@ -116,3 +116,113 @@ struct MDRSMBIOSHeader uint32_t timestamp; uint32_t dataSize; } __attribute__((packed)); + +static constexpr const char *cpuPath = + "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu"; + +typedef enum +{ + biosType = 0, + systemType = 1, + baseboardType = 2, + chassisType = 3, + processorsType = 4, + memoryControllerType = 5, + memoryModuleInformationType = 6, + cacheType = 7, + portConnectorType = 8, + systemSlots = 9, + onBoardDevicesType = 10, + oemStringsType = 11, + systemCconfigurationOptionsType = 12, + biosLanguageType = 13, + groupAssociatonsType = 14, + systemEventLogType = 15, + physicalMemoryArrayType = 16, + memoryDeviceType = 17, +} SmbiosType; + +static constexpr uint8_t separateLen = 2; + +static inline uint8_t *smbiosNextPtr(uint8_t *smbiosDataIn) +{ + if (smbiosDataIn == nullptr) + { + return nullptr; + } + uint8_t *smbiosData = smbiosDataIn + *(smbiosDataIn + 1); + int len = 0; + while ((*smbiosData | *(smbiosData + 1)) != 0) + { + smbiosData++; + len++; + if (len >= mdrSMBIOSSize) // To avoid endless loop + { + return nullptr; + } + } + return smbiosData + separateLen; +} + +// When first time run getSMBIOSTypePtr, need to send the RegionS[].regionData +// to smbiosDataIn +static inline uint8_t *getSMBIOSTypePtr(uint8_t *smbiosDataIn, uint8_t typeId) +{ + if (smbiosDataIn == nullptr) + { + return nullptr; + } + char *smbiosData = reinterpret_cast<char *>(smbiosDataIn); + while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) + { + if (*smbiosData != typeId) + { + uint32_t len = *(smbiosData + 1); + smbiosData += len; + while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0')) + { + smbiosData++; + len++; + if (len >= mdrSMBIOSSize) // To avoid endless loop + { + return nullptr; + } + } + smbiosData += separateLen; + continue; + } + return reinterpret_cast<uint8_t *>(smbiosData); + } + return nullptr; +} + +static inline std::string positionToString(uint8_t positionNum, + uint8_t structLen, uint8_t *dataIn) +{ + if (dataIn == nullptr) + { + return ""; + } + uint16_t limit = mdrSMBIOSSize; // set a limit to avoid endless loop + + char *target = reinterpret_cast<char *>(dataIn + structLen); + for (uint8_t index = 1; index < positionNum; index++) + { + for (; *target != '\0'; target++) + { + limit--; + if (limit < 1) + { + return ""; + } + } + target++; + if (*target == '\0') + { + return ""; // 0x00 0x00 means end of the entry. + } + } + + std::string result = target; + return result; +} diff --git a/services/smbios-mdrv2/src/cpu.cpp b/services/smbios-mdrv2/src/cpu.cpp new file mode 100644 index 0000000..82f4bdc --- /dev/null +++ b/services/smbios-mdrv2/src/cpu.cpp @@ -0,0 +1,207 @@ +/* +// Copyright (c) 2018 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#include "cpu.hpp" + +#include <map> + +namespace phosphor +{ +namespace smbios +{ + +void Cpu::cpuSocket(const uint8_t positionNum, const uint8_t structLen, + uint8_t *dataIn) +{ + std::string result = positionToString(positionNum, structLen, dataIn); + + processorSocket(result); +} + +std::string Cpu::processorSocket(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorSocket(value); +} + +void Cpu::cpuType(const uint8_t value) +{ + std::map<uint8_t, std::string>::const_iterator it = + processorTypeTable.find(value); + if (it == processorTypeTable.end()) + { + processorType("Unknown Processor Type"); + } + else + { + processorType(it->second); + } +} + +std::string Cpu::processorType(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorType(value); +} + +void Cpu::cpuFamily(const uint8_t value) +{ + std::map<uint8_t, std::string>::const_iterator it = familyTable.find(value); + if (it == familyTable.end()) + { + processorFamily("Unknown Processor Family"); + } + else + { + processorFamily(it->second); + } +} + +std::string Cpu::processorFamily(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorFamily(value); +} + +void Cpu::cpuManufacturer(const uint8_t positionNum, const uint8_t structLen, + uint8_t *dataIn) +{ + std::string result = positionToString(positionNum, structLen, dataIn); + + processorManufacturer(result); +} + +std::string Cpu::processorManufacturer(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorManufacturer(value); +} + +uint32_t Cpu::processorId(uint32_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorId(value); +} + +void Cpu::cpuVersion(const uint8_t positionNum, const uint8_t structLen, + uint8_t *dataIn) +{ + std::string result; + + result = positionToString(positionNum, structLen, dataIn); + + processorVersion(result); +} + +std::string Cpu::processorVersion(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorVersion(value); +} + +uint16_t Cpu::processorMaxSpeed(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorMaxSpeed(value); +} + +void Cpu::cpuCharacteristics(uint16_t value) +{ + std::string result = ""; + for (uint8_t index = 0; index < (8 * sizeof(value)); index++) + { + if (value & 0x01) + { + result += characteristicsTable[index]; + } + value >>= 1; + } + + processorCharacteristics(result); +} + +std::string Cpu::processorCharacteristics(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorCharacteristics(value); +} + +uint16_t Cpu::processorCoreCount(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorCoreCount(value); +} + +uint16_t Cpu::processorThreadCount(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorThreadCount(value); +} + +static constexpr uint8_t maxOldVersionCount = 0xff; +void Cpu::processorInfoUpdate(void) +{ + uint8_t *dataIn = storage; + + dataIn = getSMBIOSTypePtr(dataIn, processorsType); + for (uint8_t index = 0; index < cpuNum; index++) + { + dataIn = smbiosNextPtr(dataIn); + if (dataIn == nullptr) + { + return; + } + dataIn = getSMBIOSTypePtr(dataIn, processorsType); + if (dataIn == nullptr) + { + return; + } + } + + auto cpuInfo = reinterpret_cast<struct ProcessorInfo *>(dataIn); + + cpuSocket(cpuInfo->socketDesignation, cpuInfo->length, + dataIn); // offset 4h + cpuType(cpuInfo->processorType); // offset 5h + cpuFamily(cpuInfo->family); // offset 6h + cpuManufacturer(cpuInfo->manufacturer, cpuInfo->length, + dataIn); // offset 7h + processorId(cpuInfo->id); // offset 8h + cpuVersion(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h + processorMaxSpeed(cpuInfo->maxSpeed); // offset 14h + if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah + { + processorCoreCount(cpuInfo->coreCount); + } + else + { + processorCoreCount(cpuInfo->coreCount2); + } + + if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh) + { + processorThreadCount(cpuInfo->threadCount); + } + else + { + processorThreadCount(cpuInfo->threadCount2); + } + + cpuCharacteristics(cpuInfo->characteristics); // offset 26h +} + +} // namespace smbios +} // namespace phosphor diff --git a/services/smbios-mdrv2/src/mdrv2.cpp b/services/smbios-mdrv2/src/mdrv2.cpp index 3b8858e..38e21e8 100644 --- a/services/smbios-mdrv2/src/mdrv2.cpp +++ b/services/smbios-mdrv2/src/mdrv2.cpp @@ -357,6 +357,60 @@ uint8_t MDR_V2::directoryEntries(uint8_t value) directoryEntries(value); } +void MDR_V2::systemInfoUpdate() +{ + cpus.clear(); + + int num = getTotalCpuSlot(); + if (num == -1) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "get cpu total slot failed"); + return; + } + + for (int index = 0; index < num; index++) + { + std::string path = cpuPath + std::to_string(index); + cpus.emplace_back(std::make_unique<phosphor::smbios::Cpu>( + bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage)); + } +} + +int MDR_V2::getTotalCpuSlot() +{ + uint8_t *dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage; + int num = 0; + + if (dataIn == nullptr) + { + phosphor::logging::log<phosphor::logging::level::ERR>( + "get cpu total slot failed - no storage data"); + return -1; + } + + while (1) + { + dataIn = getSMBIOSTypePtr(dataIn, processorsType); + if (dataIn == nullptr) + { + break; + } + num++; + dataIn = smbiosNextPtr(dataIn); + if (dataIn == nullptr) + { + break; + } + if (num >= limitEntryLen) + { + break; + } + } + + return num; +} + bool MDR_V2::agentSynchronizeData() { struct MDRSMBIOSHeader mdr2SMBIOS; @@ -370,6 +424,7 @@ bool MDR_V2::agentSynchronizeData() } else { + systemInfoUpdate(); smbiosDir.dir[smbiosDirIndex].common.dataVersion = mdr2SMBIOS.dirVer; smbiosDir.dir[smbiosDirIndex].common.timestamp = mdr2SMBIOS.timestamp; smbiosDir.dir[smbiosDirIndex].common.size = mdr2SMBIOS.dataSize; |