blob: 3a586a2302895491b52f0ba6a0ddbab2d066374e [file] [log] [blame]
/*
// Copyright (c) 2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#include "cpu.hpp"
#include <bitset>
#include <map>
namespace phosphor
{
namespace smbios
{
void Cpu::socket(const uint8_t positionNum, const uint8_t structLen,
uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
processor::socket(result);
location::locationCode(result);
}
static constexpr uint8_t processorFamily2Indicator = 0xfe;
void Cpu::family(const uint8_t family, const uint16_t family2)
{
std::map<uint8_t, const char*>::const_iterator it =
familyTable.find(family);
if (it == familyTable.end())
{
processor::family("Unknown Processor Family");
}
else if (it->first == processorFamily2Indicator)
{
std::map<uint16_t, const char*>::const_iterator it2 =
family2Table.find(family2);
if (it2 == family2Table.end())
{
processor::family("Unknown Processor Family");
}
else
{
processor::family(it2->second);
processor::effectiveFamily(family2);
}
}
else
{
processor::family(it->second);
processor::effectiveFamily(family);
}
}
void Cpu::manufacturer(const uint8_t positionNum, const uint8_t structLen,
uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
asset::manufacturer(result);
}
void Cpu::partNumber(const uint8_t positionNum, const uint8_t structLen,
uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
asset::partNumber(result);
}
void Cpu::serialNumber(const uint8_t positionNum, const uint8_t structLen,
uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
asset::serialNumber(result);
}
void Cpu::version(const uint8_t positionNum, const uint8_t structLen,
uint8_t* dataIn)
{
std::string result;
result = positionToString(positionNum, structLen, dataIn);
rev::version(result);
}
void Cpu::characteristics(uint16_t value)
{
std::vector<processor::Capability> result;
std::optional<processor::Capability> cap;
std::bitset<16> charBits = value;
for (uint8_t index = 0; index < charBits.size(); index++)
{
if (charBits.test(index))
{
if ((cap = characteristicsTable[index]))
{
result.emplace_back(*cap);
}
}
}
processor::characteristics(result);
}
static constexpr uint8_t maxOldVersionCount = 0xff;
void Cpu::infoUpdate(uint8_t* smbiosTableStorage,
const std::string& motherboard)
{
storage = smbiosTableStorage;
motherboardPath = motherboard;
uint8_t* dataIn = storage;
dataIn = getSMBIOSTypePtr(dataIn, processorsType);
if (dataIn == nullptr)
{
return;
}
for (uint8_t index = 0; index < cpuNum; index++)
{
dataIn = smbiosNextPtr(dataIn);
if (dataIn == nullptr)
{
return;
}
dataIn = getSMBIOSTypePtr(dataIn, processorsType);
if (dataIn == nullptr)
{
return;
}
}
auto cpuInfo = reinterpret_cast<struct ProcessorInfo*>(dataIn);
socket(cpuInfo->socketDesignation, cpuInfo->length, dataIn); // offset 4h
constexpr uint32_t socketPopulatedMask = 1 << 6;
constexpr uint32_t statusMask = 0x07;
if ((cpuInfo->status & socketPopulatedMask) == 0)
{
// Don't attempt to fill in any other details if the CPU is not present.
present(false);
functional(false);
return;
}
present(true);
if ((cpuInfo->status & statusMask) == 1)
{
functional(true);
}
else
{
functional(false);
}
// this class is for type CPU //offset 5h
family(cpuInfo->family, cpuInfo->family2); // offset 6h and 28h
manufacturer(cpuInfo->manufacturer, cpuInfo->length,
dataIn); // offset 7h
id(cpuInfo->id); // offset 8h
// Step, EffectiveFamily, EffectiveModel computation for Intel processors.
std::map<uint8_t, const char*>::const_iterator it =
familyTable.find(cpuInfo->family);
if (it != familyTable.end())
{
std::string familyStr = it->second;
if ((familyStr.find(" Xeon ") != std::string::npos) ||
(familyStr.find(" Intel ") != std::string::npos))
{
// Processor ID field
// SteppinID: 4;
// Model: 4;
// Family: 4;
// Type: 2;
// Reserved1: 2;
// XModel: 4;
// XFamily: 8;
// Reserved2: 4;
uint16_t cpuStep = cpuInfo->id & 0xf;
uint16_t cpuModel = (cpuInfo->id & 0xf0) >> 4;
uint16_t cpuFamily = (cpuInfo->id & 0xf00) >> 8;
uint16_t cpuXModel = (cpuInfo->id & 0xf0000) >> 16;
uint16_t cpuXFamily = (cpuInfo->id & 0xff00000) >> 20;
step(cpuStep);
if (cpuFamily == 0xf)
{
effectiveFamily(cpuXFamily + cpuFamily);
}
else
{
effectiveFamily(cpuFamily);
}
if (cpuFamily == 0x6 || cpuFamily == 0xf)
{
effectiveModel((cpuXModel << 4) | cpuModel);
}
else
{
effectiveModel(cpuModel);
}
}
}
version(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h
maxSpeedInMhz(cpuInfo->maxSpeed); // offset 14h
serialNumber(cpuInfo->serialNum, cpuInfo->length,
dataIn); // offset 20h
partNumber(cpuInfo->partNum, cpuInfo->length,
dataIn); // offset 22h
if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah
{
coreCount(cpuInfo->coreCount);
}
else
{
coreCount(cpuInfo->coreCount2);
}
if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh)
{
threadCount(cpuInfo->threadCount);
}
else
{
threadCount(cpuInfo->threadCount2);
}
characteristics(cpuInfo->characteristics); // offset 26h
if (!motherboardPath.empty())
{
std::vector<std::tuple<std::string, std::string, std::string>> assocs;
assocs.emplace_back("chassis", "processors", motherboardPath);
association::associations(assocs);
}
}
} // namespace smbios
} // namespace phosphor