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