xref: /openbmc/smbios-mdr/src/cpu.cpp (revision 5a122a6e)
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