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 static constexpr uint8_t maxOldVersionCount = 0xff; 122 void Cpu::infoUpdate(uint8_t* smbiosTableStorage, 123 const std::string& motherboard) 124 { 125 storage = smbiosTableStorage; 126 motherboardPath = motherboard; 127 128 uint8_t* dataIn = storage; 129 130 dataIn = getSMBIOSTypePtr(dataIn, processorsType); 131 if (dataIn == nullptr) 132 { 133 return; 134 } 135 136 for (uint8_t index = 0; index < cpuNum; index++) 137 { 138 dataIn = smbiosNextPtr(dataIn); 139 if (dataIn == nullptr) 140 { 141 return; 142 } 143 dataIn = getSMBIOSTypePtr(dataIn, processorsType); 144 if (dataIn == nullptr) 145 { 146 return; 147 } 148 } 149 150 auto cpuInfo = reinterpret_cast<struct ProcessorInfo*>(dataIn); 151 152 socket(cpuInfo->socketDesignation, cpuInfo->length, dataIn); // offset 4h 153 154 constexpr uint32_t socketPopulatedMask = 1 << 6; 155 constexpr uint32_t statusMask = 0x07; 156 if ((cpuInfo->status & socketPopulatedMask) == 0) 157 { 158 // Don't attempt to fill in any other details if the CPU is not present. 159 present(false); 160 functional(false); 161 return; 162 } 163 present(true); 164 if ((cpuInfo->status & statusMask) == 1) 165 { 166 functional(true); 167 } 168 else 169 { 170 functional(false); 171 } 172 173 // this class is for type CPU //offset 5h 174 family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h 175 manufacturer(cpuInfo->manufacturer, cpuInfo->length, 176 dataIn); // offset 7h 177 id(cpuInfo->id); // offset 8h 178 179 // Step, EffectiveFamily, EffectiveModel computation for Intel processors. 180 std::map<uint8_t, const char*>::const_iterator it = 181 familyTable.find(cpuInfo->family); 182 if (it != familyTable.end()) 183 { 184 std::string familyStr = it->second; 185 if ((familyStr.find(" Xeon ") != std::string::npos) || 186 (familyStr.find(" Intel ") != std::string::npos) || 187 (familyStr.find(" Zen ") != std::string::npos)) 188 { 189 // Processor ID field 190 // SteppinID: 4; 191 // Model: 4; 192 // Family: 4; 193 // Type: 2; 194 // Reserved1: 2; 195 // XModel: 4; 196 // XFamily: 8; 197 // Reserved2: 4; 198 uint16_t cpuStep = cpuInfo->id & 0xf; 199 uint16_t cpuModel = (cpuInfo->id & 0xf0) >> 4; 200 uint16_t cpuFamily = (cpuInfo->id & 0xf00) >> 8; 201 uint16_t cpuXModel = (cpuInfo->id & 0xf0000) >> 16; 202 uint16_t cpuXFamily = (cpuInfo->id & 0xff00000) >> 20; 203 step(cpuStep); 204 if (cpuFamily == 0xf) 205 { 206 effectiveFamily(cpuXFamily + cpuFamily); 207 } 208 else 209 { 210 effectiveFamily(cpuFamily); 211 } 212 if (cpuFamily == 0x6 || cpuFamily == 0xf) 213 { 214 effectiveModel((cpuXModel << 4) | cpuModel); 215 } 216 else 217 { 218 effectiveModel(cpuModel); 219 } 220 } 221 } 222 223 version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h 224 maxSpeedInMhz(cpuInfo->maxSpeed); // offset 14h 225 serialNumber(cpuInfo->serialNum, cpuInfo->length, 226 dataIn); // offset 20h 227 partNumber(cpuInfo->partNum, cpuInfo->length, 228 dataIn); // offset 22h 229 if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah 230 { 231 coreCount(cpuInfo->coreCount); 232 } 233 else 234 { 235 coreCount(cpuInfo->coreCount2); 236 } 237 238 if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh) 239 { 240 threadCount(cpuInfo->threadCount); 241 } 242 else 243 { 244 threadCount(cpuInfo->threadCount2); 245 } 246 247 characteristics(cpuInfo->characteristics); // offset 26h 248 249 if (!motherboardPath.empty()) 250 { 251 std::vector<std::tuple<std::string, std::string, std::string>> assocs; 252 assocs.emplace_back("chassis", "processors", motherboardPath); 253 association::associations(assocs); 254 } 255 } 256 257 } // namespace smbios 258 } // namespace phosphor 259