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