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 if ((cpuInfo->status & socketPopulatedMask) == 0) 156 { 157 // Don't attempt to fill in any other details if the CPU is not present. 158 present(false); 159 return; 160 } 161 present(true); 162 163 // this class is for type CPU //offset 5h 164 family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h 165 manufacturer(cpuInfo->manufacturer, cpuInfo->length, 166 dataIn); // offset 7h 167 id(cpuInfo->id); // offset 8h 168 169 // Step, EffectiveFamily, EffectiveModel computation for Intel processors. 170 std::map<uint8_t, const char*>::const_iterator it = 171 familyTable.find(cpuInfo->family); 172 if (it != familyTable.end()) 173 { 174 std::string familyStr = it->second; 175 if ((familyStr.find(" Xeon ") != std::string::npos) || 176 (familyStr.find(" Intel ") != std::string::npos)) 177 { 178 // Processor ID field 179 // SteppinID: 4; 180 // Model: 4; 181 // Family: 4; 182 // Type: 2; 183 // Reserved1: 2; 184 // XModel: 4; 185 // XFamily: 8; 186 // Reserved2: 4; 187 uint16_t cpuStep = cpuInfo->id & 0xf; 188 uint16_t cpuModel = (cpuInfo->id & 0xf0) >> 4; 189 uint16_t cpuFamily = (cpuInfo->id & 0xf00) >> 8; 190 uint16_t cpuXModel = (cpuInfo->id & 0xf0000) >> 16; 191 uint16_t cpuXFamily = (cpuInfo->id & 0xff00000) >> 20; 192 step(cpuStep); 193 if (cpuFamily == 0xf) 194 { 195 effectiveFamily(cpuXFamily + cpuFamily); 196 } 197 else 198 { 199 effectiveFamily(cpuFamily); 200 } 201 if (cpuFamily == 0x6 || cpuFamily == 0xf) 202 { 203 effectiveModel((cpuXModel << 4) | cpuModel); 204 } 205 else 206 { 207 effectiveModel(cpuModel); 208 } 209 } 210 } 211 212 version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h 213 maxSpeedInMhz(cpuInfo->maxSpeed); // offset 14h 214 serialNumber(cpuInfo->serialNum, cpuInfo->length, 215 dataIn); // offset 20h 216 partNumber(cpuInfo->partNum, cpuInfo->length, 217 dataIn); // offset 22h 218 if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah 219 { 220 coreCount(cpuInfo->coreCount); 221 } 222 else 223 { 224 coreCount(cpuInfo->coreCount2); 225 } 226 227 if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh) 228 { 229 threadCount(cpuInfo->threadCount); 230 } 231 else 232 { 233 threadCount(cpuInfo->threadCount2); 234 } 235 236 characteristics(cpuInfo->characteristics); // offset 26h 237 238 if (!motherboardPath.empty()) 239 { 240 std::vector<std::tuple<std::string, std::string, std::string>> assocs; 241 assocs.emplace_back("chassis", "processors", motherboardPath); 242 association::associations(assocs); 243 } 244 } 245 246 } // namespace smbios 247 } // namespace phosphor 248