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
121*b1094b2cSManojkiran Eda void Cpu::assetTagString(const uint8_t positionNum, const uint8_t structLen,
infoUpdate(uint8_t * smbiosTableStorage,const std::string & motherboard)122*b1094b2cSManojkiran Eda uint8_t* dataIn)
123*b1094b2cSManojkiran Eda {
124*b1094b2cSManojkiran Eda std::string result = positionToString(positionNum, structLen, dataIn);
125*b1094b2cSManojkiran Eda assetTagType::assetTag(result);
126*b1094b2cSManojkiran Eda }
127*b1094b2cSManojkiran Eda
12843c6a1daSCheng C Yang static constexpr uint8_t maxOldVersionCount = 0xff;
1295a122a6eSBrandon Kim void Cpu::infoUpdate(uint8_t* smbiosTableStorage,
1305a122a6eSBrandon Kim const std::string& motherboard)
13143c6a1daSCheng C Yang {
1325a122a6eSBrandon Kim storage = smbiosTableStorage;
1335a122a6eSBrandon Kim motherboardPath = motherboard;
1345a122a6eSBrandon Kim
13543c6a1daSCheng C Yang uint8_t* dataIn = storage;
13643c6a1daSCheng C Yang
13743c6a1daSCheng C Yang dataIn = getSMBIOSTypePtr(dataIn, processorsType);
13843c6a1daSCheng C Yang if (dataIn == nullptr)
13943c6a1daSCheng C Yang {
14043c6a1daSCheng C Yang return;
14143c6a1daSCheng C Yang }
14243c6a1daSCheng C Yang
14343c6a1daSCheng C Yang for (uint8_t index = 0; index < cpuNum; index++)
14443c6a1daSCheng C Yang {
14543c6a1daSCheng C Yang dataIn = smbiosNextPtr(dataIn);
14643c6a1daSCheng C Yang if (dataIn == nullptr)
14743c6a1daSCheng C Yang {
14843c6a1daSCheng C Yang return;
14943c6a1daSCheng C Yang }
15043c6a1daSCheng C Yang dataIn = getSMBIOSTypePtr(dataIn, processorsType);
15143c6a1daSCheng C Yang if (dataIn == nullptr)
15243c6a1daSCheng C Yang {
15343c6a1daSCheng C Yang return;
15443c6a1daSCheng C Yang }
15543c6a1daSCheng C Yang }
15643c6a1daSCheng C Yang
15743c6a1daSCheng C Yang auto cpuInfo = reinterpret_cast<struct ProcessorInfo*>(dataIn);
15843c6a1daSCheng C Yang
159563570dfSJonathan Doman socket(cpuInfo->socketDesignation, cpuInfo->length, dataIn); // offset 4h
160563570dfSJonathan Doman
161563570dfSJonathan Doman constexpr uint32_t socketPopulatedMask = 1 << 6;
162e05a5423SDavid Wang constexpr uint32_t statusMask = 0x07;
163563570dfSJonathan Doman if ((cpuInfo->status & socketPopulatedMask) == 0)
164563570dfSJonathan Doman {
165563570dfSJonathan Doman // Don't attempt to fill in any other details if the CPU is not present.
166563570dfSJonathan Doman present(false);
167e05a5423SDavid Wang functional(false);
168563570dfSJonathan Doman return;
169563570dfSJonathan Doman }
170563570dfSJonathan Doman present(true);
171e05a5423SDavid Wang if ((cpuInfo->status & statusMask) == 1)
172e05a5423SDavid Wang {
173e05a5423SDavid Wang functional(true);
174e05a5423SDavid Wang }
175e05a5423SDavid Wang else
176e05a5423SDavid Wang {
177e05a5423SDavid Wang functional(false);
178e05a5423SDavid Wang }
179563570dfSJonathan Doman
18018a5ab91SZhikui Ren // this class is for type CPU //offset 5h
181800bb700SCharles Boyer family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h
18218a5ab91SZhikui Ren manufacturer(cpuInfo->manufacturer, cpuInfo->length,
18343c6a1daSCheng C Yang dataIn); // offset 7h
18418a5ab91SZhikui Ren id(cpuInfo->id); // offset 8h
18559616938SZhikui Ren
18659616938SZhikui Ren // Step, EffectiveFamily, EffectiveModel computation for Intel processors.
18759616938SZhikui Ren std::map<uint8_t, const char*>::const_iterator it =
18859616938SZhikui Ren familyTable.find(cpuInfo->family);
18959616938SZhikui Ren if (it != familyTable.end())
19059616938SZhikui Ren {
19159616938SZhikui Ren std::string familyStr = it->second;
19259616938SZhikui Ren if ((familyStr.find(" Xeon ") != std::string::npos) ||
1930f7704a3SKonda Reddy Kachana (familyStr.find(" Intel ") != std::string::npos) ||
1940f7704a3SKonda Reddy Kachana (familyStr.find(" Zen ") != std::string::npos))
19559616938SZhikui Ren {
19659616938SZhikui Ren // Processor ID field
19759616938SZhikui Ren // SteppinID: 4;
19859616938SZhikui Ren // Model: 4;
19959616938SZhikui Ren // Family: 4;
20059616938SZhikui Ren // Type: 2;
20159616938SZhikui Ren // Reserved1: 2;
20259616938SZhikui Ren // XModel: 4;
20359616938SZhikui Ren // XFamily: 8;
20459616938SZhikui Ren // Reserved2: 4;
20559616938SZhikui Ren uint16_t cpuStep = cpuInfo->id & 0xf;
20659616938SZhikui Ren uint16_t cpuModel = (cpuInfo->id & 0xf0) >> 4;
20759616938SZhikui Ren uint16_t cpuFamily = (cpuInfo->id & 0xf00) >> 8;
20859616938SZhikui Ren uint16_t cpuXModel = (cpuInfo->id & 0xf0000) >> 16;
20959616938SZhikui Ren uint16_t cpuXFamily = (cpuInfo->id & 0xff00000) >> 20;
21059616938SZhikui Ren step(cpuStep);
21159616938SZhikui Ren if (cpuFamily == 0xf)
21259616938SZhikui Ren {
21359616938SZhikui Ren effectiveFamily(cpuXFamily + cpuFamily);
21459616938SZhikui Ren }
21559616938SZhikui Ren else
21659616938SZhikui Ren {
21759616938SZhikui Ren effectiveFamily(cpuFamily);
21859616938SZhikui Ren }
21959616938SZhikui Ren if (cpuFamily == 0x6 || cpuFamily == 0xf)
22059616938SZhikui Ren {
22159616938SZhikui Ren effectiveModel((cpuXModel << 4) | cpuModel);
22259616938SZhikui Ren }
22359616938SZhikui Ren else
22459616938SZhikui Ren {
22559616938SZhikui Ren effectiveModel(cpuModel);
22659616938SZhikui Ren }
22759616938SZhikui Ren }
22859616938SZhikui Ren }
22959616938SZhikui Ren
23018a5ab91SZhikui Ren version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h
23118a5ab91SZhikui Ren maxSpeedInMhz(cpuInfo->maxSpeed); // offset 14h
232e643169dSCharles Boyer serialNumber(cpuInfo->serialNum, cpuInfo->length,
233e643169dSCharles Boyer dataIn); // offset 20h
234*b1094b2cSManojkiran Eda assetTagString(cpuInfo->assetTag, cpuInfo->length,
235*b1094b2cSManojkiran Eda dataIn); // offset 21h
236e643169dSCharles Boyer partNumber(cpuInfo->partNum, cpuInfo->length,
237e643169dSCharles Boyer dataIn); // offset 22h
23843c6a1daSCheng C Yang if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah
23943c6a1daSCheng C Yang {
24018a5ab91SZhikui Ren coreCount(cpuInfo->coreCount);
24143c6a1daSCheng C Yang }
24243c6a1daSCheng C Yang else
24343c6a1daSCheng C Yang {
24418a5ab91SZhikui Ren coreCount(cpuInfo->coreCount2);
24543c6a1daSCheng C Yang }
24643c6a1daSCheng C Yang
24743c6a1daSCheng C Yang if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh)
24843c6a1daSCheng C Yang {
24918a5ab91SZhikui Ren threadCount(cpuInfo->threadCount);
25043c6a1daSCheng C Yang }
25143c6a1daSCheng C Yang else
25243c6a1daSCheng C Yang {
25318a5ab91SZhikui Ren threadCount(cpuInfo->threadCount2);
25443c6a1daSCheng C Yang }
25543c6a1daSCheng C Yang
25618a5ab91SZhikui Ren characteristics(cpuInfo->characteristics); // offset 26h
257e7cf3195SJie Yang
258e7cf3195SJie Yang if (!motherboardPath.empty())
259e7cf3195SJie Yang {
260e7cf3195SJie Yang std::vector<std::tuple<std::string, std::string, std::string>> assocs;
261e7cf3195SJie Yang assocs.emplace_back("chassis", "processors", motherboardPath);
262e7cf3195SJie Yang association::associations(assocs);
263e7cf3195SJie Yang }
26443c6a1daSCheng C Yang }
26543c6a1daSCheng C Yang
26643c6a1daSCheng C Yang } // namespace smbios
26743c6a1daSCheng C Yang } // namespace phosphor
268