1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #include "cpu.hpp" 18 19 #include <bitset> 20 #include <map> 21 22 namespace phosphor 23 { 24 namespace smbios 25 { 26 27 void Cpu::socket(const uint8_t positionNum, const uint8_t structLen, 28 uint8_t* dataIn) 29 { 30 std::string result = positionToString(positionNum, structLen, dataIn); 31 32 processor::socket(result); 33 34 location::locationCode(result); 35 } 36 37 static constexpr uint8_t processorFamily2Indicator = 0xfe; 38 void Cpu::family(const uint8_t family, const uint16_t family2) 39 { 40 std::map<uint8_t, const char*>::const_iterator it = 41 familyTable.find(family); 42 if (it == familyTable.end()) 43 { 44 processor::family("Unknown Processor Family"); 45 } 46 else if (it->first == processorFamily2Indicator) 47 { 48 std::map<uint16_t, const char*>::const_iterator it2 = 49 family2Table.find(family2); 50 if (it2 == family2Table.end()) 51 { 52 processor::family("Unknown Processor Family"); 53 } 54 else 55 { 56 processor::family(it2->second); 57 processor::effectiveFamily(family2); 58 } 59 } 60 else 61 { 62 processor::family(it->second); 63 processor::effectiveFamily(family); 64 } 65 } 66 67 void Cpu::manufacturer(const uint8_t positionNum, const uint8_t structLen, 68 uint8_t* dataIn) 69 { 70 std::string result = positionToString(positionNum, structLen, dataIn); 71 72 asset::manufacturer(result); 73 } 74 75 void Cpu::partNumber(const uint8_t positionNum, const uint8_t structLen, 76 uint8_t* dataIn) 77 { 78 std::string result = positionToString(positionNum, structLen, dataIn); 79 80 asset::partNumber(result); 81 } 82 83 void Cpu::serialNumber(const uint8_t positionNum, const uint8_t structLen, 84 uint8_t* dataIn) 85 { 86 std::string result = positionToString(positionNum, structLen, dataIn); 87 88 asset::serialNumber(result); 89 } 90 91 void Cpu::version(const uint8_t positionNum, const uint8_t structLen, 92 uint8_t* dataIn) 93 { 94 std::string result; 95 96 result = positionToString(positionNum, structLen, dataIn); 97 98 rev::version(result); 99 } 100 101 void Cpu::characteristics(uint16_t value) 102 { 103 std::vector<processor::Capability> result; 104 std::optional<processor::Capability> cap; 105 106 std::bitset<16> charBits = value; 107 for (uint8_t index = 0; index < charBits.size(); index++) 108 { 109 if (charBits.test(index)) 110 { 111 if ((cap = characteristicsTable[index])) 112 { 113 result.emplace_back(*cap); 114 } 115 } 116 } 117 118 processor::characteristics(result); 119 } 120 121 void Cpu::assetTagString(const uint8_t positionNum, const uint8_t structLen, 122 uint8_t* dataIn) 123 { 124 std::string result = positionToString(positionNum, structLen, dataIn); 125 assetTagType::assetTag(result); 126 } 127 128 static constexpr uint8_t maxOldVersionCount = 0xff; 129 void Cpu::infoUpdate(uint8_t* smbiosTableStorage, 130 const std::string& motherboard) 131 { 132 storage = smbiosTableStorage; 133 motherboardPath = motherboard; 134 135 uint8_t* dataIn = storage; 136 137 dataIn = getSMBIOSTypePtr(dataIn, processorsType); 138 if (dataIn == nullptr) 139 { 140 return; 141 } 142 143 for (uint8_t index = 0; index < cpuNum; index++) 144 { 145 dataIn = smbiosNextPtr(dataIn); 146 if (dataIn == nullptr) 147 { 148 return; 149 } 150 dataIn = getSMBIOSTypePtr(dataIn, processorsType); 151 if (dataIn == nullptr) 152 { 153 return; 154 } 155 } 156 157 auto cpuInfo = reinterpret_cast<struct ProcessorInfo*>(dataIn); 158 159 socket(cpuInfo->socketDesignation, cpuInfo->length, dataIn); // offset 4h 160 161 constexpr uint32_t socketPopulatedMask = 1 << 6; 162 constexpr uint32_t statusMask = 0x07; 163 if ((cpuInfo->status & socketPopulatedMask) == 0) 164 { 165 // Don't attempt to fill in any other details if the CPU is not present. 166 present(false); 167 functional(false); 168 return; 169 } 170 present(true); 171 if ((cpuInfo->status & statusMask) == 1) 172 { 173 functional(true); 174 } 175 else 176 { 177 functional(false); 178 } 179 180 // this class is for type CPU //offset 5h 181 family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h 182 manufacturer(cpuInfo->manufacturer, cpuInfo->length, 183 dataIn); // offset 7h 184 id(cpuInfo->id); // offset 8h 185 186 // Step, EffectiveFamily, EffectiveModel computation for Intel processors. 187 std::map<uint8_t, const char*>::const_iterator it = 188 familyTable.find(cpuInfo->family); 189 if (it != familyTable.end()) 190 { 191 std::string familyStr = it->second; 192 if ((familyStr.find(" Xeon ") != std::string::npos) || 193 (familyStr.find(" Intel ") != std::string::npos) || 194 (familyStr.find(" Zen ") != std::string::npos)) 195 { 196 // Processor ID field 197 // SteppinID: 4; 198 // Model: 4; 199 // Family: 4; 200 // Type: 2; 201 // Reserved1: 2; 202 // XModel: 4; 203 // XFamily: 8; 204 // Reserved2: 4; 205 uint16_t cpuStep = cpuInfo->id & 0xf; 206 uint16_t cpuModel = (cpuInfo->id & 0xf0) >> 4; 207 uint16_t cpuFamily = (cpuInfo->id & 0xf00) >> 8; 208 uint16_t cpuXModel = (cpuInfo->id & 0xf0000) >> 16; 209 uint16_t cpuXFamily = (cpuInfo->id & 0xff00000) >> 20; 210 step(cpuStep); 211 if (cpuFamily == 0xf) 212 { 213 effectiveFamily(cpuXFamily + cpuFamily); 214 } 215 else 216 { 217 effectiveFamily(cpuFamily); 218 } 219 if (cpuFamily == 0x6 || cpuFamily == 0xf) 220 { 221 effectiveModel((cpuXModel << 4) | cpuModel); 222 } 223 else 224 { 225 effectiveModel(cpuModel); 226 } 227 } 228 } 229 230 version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h 231 maxSpeedInMhz(cpuInfo->maxSpeed); // offset 14h 232 serialNumber(cpuInfo->serialNum, cpuInfo->length, 233 dataIn); // offset 20h 234 assetTagString(cpuInfo->assetTag, cpuInfo->length, 235 dataIn); // offset 21h 236 partNumber(cpuInfo->partNum, cpuInfo->length, 237 dataIn); // offset 22h 238 if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah 239 { 240 coreCount(cpuInfo->coreCount); 241 } 242 else 243 { 244 coreCount(cpuInfo->coreCount2); 245 } 246 247 if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh) 248 { 249 threadCount(cpuInfo->threadCount); 250 } 251 else 252 { 253 threadCount(cpuInfo->threadCount2); 254 } 255 256 characteristics(cpuInfo->characteristics); // offset 26h 257 258 if (!motherboardPath.empty()) 259 { 260 std::vector<std::tuple<std::string, std::string, std::string>> assocs; 261 assocs.emplace_back("chassis", "processors", motherboardPath); 262 association::associations(assocs); 263 } 264 } 265 266 } // namespace smbios 267 } // namespace phosphor 268