xref: /openbmc/smbios-mdr/src/cpu.cpp (revision 0f7704a3)
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 
socket(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)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;
family(const uint8_t family,const uint16_t family2)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 
manufacturer(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)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 
partNumber(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)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 
serialNumber(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)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 
version(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)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 
characteristics(uint16_t value)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         {
111f2d8bb48SJonathan Doman             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;
infoUpdate(uint8_t * smbiosTableStorage,const std::string & motherboard)1225a122a6eSBrandon Kim void Cpu::infoUpdate(uint8_t* smbiosTableStorage,
1235a122a6eSBrandon Kim                      const std::string& motherboard)
12443c6a1daSCheng C Yang {
1255a122a6eSBrandon Kim     storage = smbiosTableStorage;
1265a122a6eSBrandon Kim     motherboardPath = motherboard;
1275a122a6eSBrandon 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;
155e05a5423SDavid Wang     constexpr uint32_t statusMask = 0x07;
156563570dfSJonathan Doman     if ((cpuInfo->status & socketPopulatedMask) == 0)
157563570dfSJonathan Doman     {
158563570dfSJonathan Doman         // Don't attempt to fill in any other details if the CPU is not present.
159563570dfSJonathan Doman         present(false);
160e05a5423SDavid Wang         functional(false);
161563570dfSJonathan Doman         return;
162563570dfSJonathan Doman     }
163563570dfSJonathan Doman     present(true);
164e05a5423SDavid Wang     if ((cpuInfo->status & statusMask) == 1)
165e05a5423SDavid Wang     {
166e05a5423SDavid Wang         functional(true);
167e05a5423SDavid Wang     }
168e05a5423SDavid Wang     else
169e05a5423SDavid Wang     {
170e05a5423SDavid Wang         functional(false);
171e05a5423SDavid Wang     }
172563570dfSJonathan Doman 
17318a5ab91SZhikui Ren     // this class is for type CPU  //offset 5h
174800bb700SCharles Boyer     family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h
17518a5ab91SZhikui Ren     manufacturer(cpuInfo->manufacturer, cpuInfo->length,
17643c6a1daSCheng C Yang                  dataIn);                      // offset 7h
17718a5ab91SZhikui Ren     id(cpuInfo->id);                           // offset 8h
17859616938SZhikui Ren 
17959616938SZhikui Ren     // Step, EffectiveFamily, EffectiveModel computation for Intel processors.
18059616938SZhikui Ren     std::map<uint8_t, const char*>::const_iterator it =
18159616938SZhikui Ren         familyTable.find(cpuInfo->family);
18259616938SZhikui Ren     if (it != familyTable.end())
18359616938SZhikui Ren     {
18459616938SZhikui Ren         std::string familyStr = it->second;
18559616938SZhikui Ren         if ((familyStr.find(" Xeon ") != std::string::npos) ||
186*0f7704a3SKonda Reddy Kachana             (familyStr.find(" Intel ") != std::string::npos) ||
187*0f7704a3SKonda Reddy Kachana             (familyStr.find(" Zen ") != std::string::npos))
18859616938SZhikui Ren         {
18959616938SZhikui Ren             // Processor ID field
19059616938SZhikui Ren             // SteppinID:   4;
19159616938SZhikui Ren             // Model:       4;
19259616938SZhikui Ren             // Family:      4;
19359616938SZhikui Ren             // Type:        2;
19459616938SZhikui Ren             // Reserved1:   2;
19559616938SZhikui Ren             // XModel:      4;
19659616938SZhikui Ren             // XFamily:     8;
19759616938SZhikui Ren             // Reserved2:   4;
19859616938SZhikui Ren             uint16_t cpuStep = cpuInfo->id & 0xf;
19959616938SZhikui Ren             uint16_t cpuModel = (cpuInfo->id & 0xf0) >> 4;
20059616938SZhikui Ren             uint16_t cpuFamily = (cpuInfo->id & 0xf00) >> 8;
20159616938SZhikui Ren             uint16_t cpuXModel = (cpuInfo->id & 0xf0000) >> 16;
20259616938SZhikui Ren             uint16_t cpuXFamily = (cpuInfo->id & 0xff00000) >> 20;
20359616938SZhikui Ren             step(cpuStep);
20459616938SZhikui Ren             if (cpuFamily == 0xf)
20559616938SZhikui Ren             {
20659616938SZhikui Ren                 effectiveFamily(cpuXFamily + cpuFamily);
20759616938SZhikui Ren             }
20859616938SZhikui Ren             else
20959616938SZhikui Ren             {
21059616938SZhikui Ren                 effectiveFamily(cpuFamily);
21159616938SZhikui Ren             }
21259616938SZhikui Ren             if (cpuFamily == 0x6 || cpuFamily == 0xf)
21359616938SZhikui Ren             {
21459616938SZhikui Ren                 effectiveModel((cpuXModel << 4) | cpuModel);
21559616938SZhikui Ren             }
21659616938SZhikui Ren             else
21759616938SZhikui Ren             {
21859616938SZhikui Ren                 effectiveModel(cpuModel);
21959616938SZhikui Ren             }
22059616938SZhikui Ren         }
22159616938SZhikui Ren     }
22259616938SZhikui Ren 
22318a5ab91SZhikui Ren     version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h
22418a5ab91SZhikui Ren     maxSpeedInMhz(cpuInfo->maxSpeed);                   // offset 14h
225e643169dSCharles Boyer     serialNumber(cpuInfo->serialNum, cpuInfo->length,
226e643169dSCharles Boyer                  dataIn);                               // offset 20h
227e643169dSCharles Boyer     partNumber(cpuInfo->partNum, cpuInfo->length,
228e643169dSCharles Boyer                dataIn);                                 // offset 22h
22943c6a1daSCheng C Yang     if (cpuInfo->coreCount < maxOldVersionCount)        // offset 23h or 2Ah
23043c6a1daSCheng C Yang     {
23118a5ab91SZhikui Ren         coreCount(cpuInfo->coreCount);
23243c6a1daSCheng C Yang     }
23343c6a1daSCheng C Yang     else
23443c6a1daSCheng C Yang     {
23518a5ab91SZhikui Ren         coreCount(cpuInfo->coreCount2);
23643c6a1daSCheng C Yang     }
23743c6a1daSCheng C Yang 
23843c6a1daSCheng C Yang     if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh)
23943c6a1daSCheng C Yang     {
24018a5ab91SZhikui Ren         threadCount(cpuInfo->threadCount);
24143c6a1daSCheng C Yang     }
24243c6a1daSCheng C Yang     else
24343c6a1daSCheng C Yang     {
24418a5ab91SZhikui Ren         threadCount(cpuInfo->threadCount2);
24543c6a1daSCheng C Yang     }
24643c6a1daSCheng C Yang 
24718a5ab91SZhikui Ren     characteristics(cpuInfo->characteristics); // offset 26h
248e7cf3195SJie Yang 
249e7cf3195SJie Yang     if (!motherboardPath.empty())
250e7cf3195SJie Yang     {
251e7cf3195SJie Yang         std::vector<std::tuple<std::string, std::string, std::string>> assocs;
252e7cf3195SJie Yang         assocs.emplace_back("chassis", "processors", motherboardPath);
253e7cf3195SJie Yang         association::associations(assocs);
254e7cf3195SJie Yang     }
25543c6a1daSCheng C Yang }
25643c6a1daSCheng C Yang 
25743c6a1daSCheng C Yang } // namespace smbios
25843c6a1daSCheng C Yang } // namespace phosphor
259