143c6a1daSCheng C Yang /* 243c6a1daSCheng C Yang // Copyright (c) 2018 Intel Corporation 343c6a1daSCheng C Yang // 443c6a1daSCheng C Yang // Licensed under the Apache License, Version 2.0 (the "License"); 543c6a1daSCheng C Yang // you may not use this file except in compliance with the License. 643c6a1daSCheng C Yang // You may obtain a copy of the License at 743c6a1daSCheng C Yang // 843c6a1daSCheng C Yang // http://www.apache.org/licenses/LICENSE-2.0 943c6a1daSCheng C Yang // 1043c6a1daSCheng C Yang // Unless required by applicable law or agreed to in writing, software 1143c6a1daSCheng C Yang // distributed under the License is distributed on an "AS IS" BASIS, 1243c6a1daSCheng C Yang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1343c6a1daSCheng C Yang // See the License for the specific language governing permissions and 1443c6a1daSCheng C Yang // limitations under the License. 1543c6a1daSCheng C Yang */ 1643c6a1daSCheng C Yang 1743c6a1daSCheng C Yang #include "cpu.hpp" 1843c6a1daSCheng C Yang 1918a5ab91SZhikui Ren #include <bitset> 2043c6a1daSCheng C Yang #include <map> 2143c6a1daSCheng C Yang 2243c6a1daSCheng C Yang namespace phosphor 2343c6a1daSCheng C Yang { 2443c6a1daSCheng C Yang namespace smbios 2543c6a1daSCheng C Yang { 2643c6a1daSCheng C Yang 2718a5ab91SZhikui Ren void Cpu::socket(const uint8_t positionNum, const uint8_t structLen, 2843c6a1daSCheng C Yang uint8_t* dataIn) 2943c6a1daSCheng C Yang { 3043c6a1daSCheng C Yang std::string result = positionToString(positionNum, structLen, dataIn); 3143c6a1daSCheng C Yang 3218a5ab91SZhikui Ren processor::socket(result); 3331720397SJie Yang 3431720397SJie Yang location::locationCode(result); 3543c6a1daSCheng C Yang } 3643c6a1daSCheng C Yang 37800bb700SCharles Boyer static constexpr uint8_t processorFamily2Indicator = 0xfe; 38800bb700SCharles Boyer void Cpu::family(const uint8_t family, const uint16_t family2) 3943c6a1daSCheng C Yang { 40800bb700SCharles Boyer std::map<uint8_t, const char*>::const_iterator it = 41800bb700SCharles Boyer familyTable.find(family); 4243c6a1daSCheng C Yang if (it == familyTable.end()) 4343c6a1daSCheng C Yang { 4418a5ab91SZhikui Ren processor::family("Unknown Processor Family"); 4543c6a1daSCheng C Yang } 46800bb700SCharles Boyer else if (it->first == processorFamily2Indicator) 47800bb700SCharles Boyer { 48800bb700SCharles Boyer std::map<uint16_t, const char*>::const_iterator it2 = 49800bb700SCharles Boyer family2Table.find(family2); 50800bb700SCharles Boyer if (it2 == family2Table.end()) 51800bb700SCharles Boyer { 52800bb700SCharles Boyer processor::family("Unknown Processor Family"); 53800bb700SCharles Boyer } 54800bb700SCharles Boyer else 55800bb700SCharles Boyer { 56800bb700SCharles Boyer processor::family(it2->second); 5719849573SJiaqing Zhao processor::effectiveFamily(family2); 58800bb700SCharles Boyer } 59800bb700SCharles Boyer } 6043c6a1daSCheng C Yang else 6143c6a1daSCheng C Yang { 6218a5ab91SZhikui Ren processor::family(it->second); 6319849573SJiaqing Zhao processor::effectiveFamily(family); 6443c6a1daSCheng C Yang } 6543c6a1daSCheng C Yang } 6643c6a1daSCheng C Yang 6718a5ab91SZhikui Ren void Cpu::manufacturer(const uint8_t positionNum, const uint8_t structLen, 6843c6a1daSCheng C Yang uint8_t* dataIn) 6943c6a1daSCheng C Yang { 7043c6a1daSCheng C Yang std::string result = positionToString(positionNum, structLen, dataIn); 7143c6a1daSCheng C Yang 7218a5ab91SZhikui Ren asset::manufacturer(result); 7343c6a1daSCheng C Yang } 7443c6a1daSCheng C Yang 75e643169dSCharles Boyer void Cpu::partNumber(const uint8_t positionNum, const uint8_t structLen, 76e643169dSCharles Boyer uint8_t* dataIn) 77e643169dSCharles Boyer { 78e643169dSCharles Boyer std::string result = positionToString(positionNum, structLen, dataIn); 79e643169dSCharles Boyer 80e643169dSCharles Boyer asset::partNumber(result); 81e643169dSCharles Boyer } 82e643169dSCharles Boyer 83e643169dSCharles Boyer void Cpu::serialNumber(const uint8_t positionNum, const uint8_t structLen, 84e643169dSCharles Boyer uint8_t* dataIn) 85e643169dSCharles Boyer { 86e643169dSCharles Boyer std::string result = positionToString(positionNum, structLen, dataIn); 87e643169dSCharles Boyer 88e643169dSCharles Boyer asset::serialNumber(result); 89e643169dSCharles Boyer } 90e643169dSCharles Boyer 9118a5ab91SZhikui Ren void Cpu::version(const uint8_t positionNum, const uint8_t structLen, 9243c6a1daSCheng C Yang uint8_t* dataIn) 9343c6a1daSCheng C Yang { 9443c6a1daSCheng C Yang std::string result; 9543c6a1daSCheng C Yang 9643c6a1daSCheng C Yang result = positionToString(positionNum, structLen, dataIn); 9743c6a1daSCheng C Yang 9818a5ab91SZhikui Ren rev::version(result); 9943c6a1daSCheng C Yang } 10043c6a1daSCheng C Yang 10118a5ab91SZhikui Ren void Cpu::characteristics(uint16_t value) 10243c6a1daSCheng C Yang { 10318a5ab91SZhikui Ren std::vector<processor::Capability> result; 10418a5ab91SZhikui Ren std::optional<processor::Capability> cap; 10543c6a1daSCheng C Yang 10618a5ab91SZhikui Ren std::bitset<16> charBits = value; 10718a5ab91SZhikui Ren for (uint8_t index = 0; index < charBits.size(); index++) 10843c6a1daSCheng C Yang { 10918a5ab91SZhikui Ren if (charBits.test(index)) 11018a5ab91SZhikui Ren { 11118a5ab91SZhikui Ren if (cap = characteristicsTable[index]) 11218a5ab91SZhikui Ren { 11318a5ab91SZhikui Ren result.emplace_back(*cap); 11443c6a1daSCheng C Yang } 11543c6a1daSCheng C Yang } 11643c6a1daSCheng C Yang } 11743c6a1daSCheng C Yang 11818a5ab91SZhikui Ren processor::characteristics(result); 11943c6a1daSCheng C Yang } 12043c6a1daSCheng C Yang 12143c6a1daSCheng C Yang static constexpr uint8_t maxOldVersionCount = 0xff; 122*5a122a6eSBrandon Kim void Cpu::infoUpdate(uint8_t* smbiosTableStorage, 123*5a122a6eSBrandon Kim const std::string& motherboard) 12443c6a1daSCheng C Yang { 125*5a122a6eSBrandon Kim storage = smbiosTableStorage; 126*5a122a6eSBrandon Kim motherboardPath = motherboard; 127*5a122a6eSBrandon Kim 12843c6a1daSCheng C Yang uint8_t* dataIn = storage; 12943c6a1daSCheng C Yang 13043c6a1daSCheng C Yang dataIn = getSMBIOSTypePtr(dataIn, processorsType); 13143c6a1daSCheng C Yang if (dataIn == nullptr) 13243c6a1daSCheng C Yang { 13343c6a1daSCheng C Yang return; 13443c6a1daSCheng C Yang } 13543c6a1daSCheng C Yang 13643c6a1daSCheng C Yang for (uint8_t index = 0; index < cpuNum; index++) 13743c6a1daSCheng C Yang { 13843c6a1daSCheng C Yang dataIn = smbiosNextPtr(dataIn); 13943c6a1daSCheng C Yang if (dataIn == nullptr) 14043c6a1daSCheng C Yang { 14143c6a1daSCheng C Yang return; 14243c6a1daSCheng C Yang } 14343c6a1daSCheng C Yang dataIn = getSMBIOSTypePtr(dataIn, processorsType); 14443c6a1daSCheng C Yang if (dataIn == nullptr) 14543c6a1daSCheng C Yang { 14643c6a1daSCheng C Yang return; 14743c6a1daSCheng C Yang } 14843c6a1daSCheng C Yang } 14943c6a1daSCheng C Yang 15043c6a1daSCheng C Yang auto cpuInfo = reinterpret_cast<struct ProcessorInfo*>(dataIn); 15143c6a1daSCheng C Yang 152563570dfSJonathan Doman socket(cpuInfo->socketDesignation, cpuInfo->length, dataIn); // offset 4h 153563570dfSJonathan Doman 154563570dfSJonathan Doman constexpr uint32_t socketPopulatedMask = 1 << 6; 155563570dfSJonathan Doman if ((cpuInfo->status & socketPopulatedMask) == 0) 156563570dfSJonathan Doman { 157563570dfSJonathan Doman // Don't attempt to fill in any other details if the CPU is not present. 158563570dfSJonathan Doman present(false); 159563570dfSJonathan Doman return; 160563570dfSJonathan Doman } 161563570dfSJonathan Doman present(true); 162563570dfSJonathan Doman 16318a5ab91SZhikui Ren // this class is for type CPU //offset 5h 164800bb700SCharles Boyer family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h 16518a5ab91SZhikui Ren manufacturer(cpuInfo->manufacturer, cpuInfo->length, 16643c6a1daSCheng C Yang dataIn); // offset 7h 16718a5ab91SZhikui Ren id(cpuInfo->id); // offset 8h 16859616938SZhikui Ren 16959616938SZhikui Ren // Step, EffectiveFamily, EffectiveModel computation for Intel processors. 17059616938SZhikui Ren std::map<uint8_t, const char*>::const_iterator it = 17159616938SZhikui Ren familyTable.find(cpuInfo->family); 17259616938SZhikui Ren if (it != familyTable.end()) 17359616938SZhikui Ren { 17459616938SZhikui Ren std::string familyStr = it->second; 17559616938SZhikui Ren if ((familyStr.find(" Xeon ") != std::string::npos) || 17659616938SZhikui Ren (familyStr.find(" Intel ") != std::string::npos)) 17759616938SZhikui Ren { 17859616938SZhikui Ren // Processor ID field 17959616938SZhikui Ren // SteppinID: 4; 18059616938SZhikui Ren // Model: 4; 18159616938SZhikui Ren // Family: 4; 18259616938SZhikui Ren // Type: 2; 18359616938SZhikui Ren // Reserved1: 2; 18459616938SZhikui Ren // XModel: 4; 18559616938SZhikui Ren // XFamily: 8; 18659616938SZhikui Ren // Reserved2: 4; 18759616938SZhikui Ren uint16_t cpuStep = cpuInfo->id & 0xf; 18859616938SZhikui Ren uint16_t cpuModel = (cpuInfo->id & 0xf0) >> 4; 18959616938SZhikui Ren uint16_t cpuFamily = (cpuInfo->id & 0xf00) >> 8; 19059616938SZhikui Ren uint16_t cpuXModel = (cpuInfo->id & 0xf0000) >> 16; 19159616938SZhikui Ren uint16_t cpuXFamily = (cpuInfo->id & 0xff00000) >> 20; 19259616938SZhikui Ren step(cpuStep); 19359616938SZhikui Ren if (cpuFamily == 0xf) 19459616938SZhikui Ren { 19559616938SZhikui Ren effectiveFamily(cpuXFamily + cpuFamily); 19659616938SZhikui Ren } 19759616938SZhikui Ren else 19859616938SZhikui Ren { 19959616938SZhikui Ren effectiveFamily(cpuFamily); 20059616938SZhikui Ren } 20159616938SZhikui Ren if (cpuFamily == 0x6 || cpuFamily == 0xf) 20259616938SZhikui Ren { 20359616938SZhikui Ren effectiveModel((cpuXModel << 4) | cpuModel); 20459616938SZhikui Ren } 20559616938SZhikui Ren else 20659616938SZhikui Ren { 20759616938SZhikui Ren effectiveModel(cpuModel); 20859616938SZhikui Ren } 20959616938SZhikui Ren } 21059616938SZhikui Ren } 21159616938SZhikui Ren 21218a5ab91SZhikui Ren version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h 21318a5ab91SZhikui Ren maxSpeedInMhz(cpuInfo->maxSpeed); // offset 14h 214e643169dSCharles Boyer serialNumber(cpuInfo->serialNum, cpuInfo->length, 215e643169dSCharles Boyer dataIn); // offset 20h 216e643169dSCharles Boyer partNumber(cpuInfo->partNum, cpuInfo->length, 217e643169dSCharles Boyer dataIn); // offset 22h 21843c6a1daSCheng C Yang if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah 21943c6a1daSCheng C Yang { 22018a5ab91SZhikui Ren coreCount(cpuInfo->coreCount); 22143c6a1daSCheng C Yang } 22243c6a1daSCheng C Yang else 22343c6a1daSCheng C Yang { 22418a5ab91SZhikui Ren coreCount(cpuInfo->coreCount2); 22543c6a1daSCheng C Yang } 22643c6a1daSCheng C Yang 22743c6a1daSCheng C Yang if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh) 22843c6a1daSCheng C Yang { 22918a5ab91SZhikui Ren threadCount(cpuInfo->threadCount); 23043c6a1daSCheng C Yang } 23143c6a1daSCheng C Yang else 23243c6a1daSCheng C Yang { 23318a5ab91SZhikui Ren threadCount(cpuInfo->threadCount2); 23443c6a1daSCheng C Yang } 23543c6a1daSCheng C Yang 23618a5ab91SZhikui Ren characteristics(cpuInfo->characteristics); // offset 26h 237e7cf3195SJie Yang 238e7cf3195SJie Yang if (!motherboardPath.empty()) 239e7cf3195SJie Yang { 240e7cf3195SJie Yang std::vector<std::tuple<std::string, std::string, std::string>> assocs; 241e7cf3195SJie Yang assocs.emplace_back("chassis", "processors", motherboardPath); 242e7cf3195SJie Yang association::associations(assocs); 243e7cf3195SJie Yang } 24443c6a1daSCheng C Yang } 24543c6a1daSCheng C Yang 24643c6a1daSCheng C Yang } // namespace smbios 24743c6a1daSCheng C Yang } // namespace phosphor 248