[cpu] Reimplement CPUID features as util::bitset

The cpu::cpu_id class no longer looks up all known features in the
constructor, but instead provides access to the map of supported
features as a bitset from the verify() method. It also exposes the
brand_name() method instead of loading the brand name string in the
constructor and storing it as part of the object.
This commit is contained in:
Justin C. Miller
2022-03-13 17:33:16 -07:00
parent e2eaf43b4a
commit 54aef00913
6 changed files with 69 additions and 59 deletions

View File

@@ -23,9 +23,7 @@ __cpuid(
if (edx) *edx = d;
}
cpu_id::cpu_id() :
m_features {0},
m_missing {0}
cpu_id::cpu_id()
{
__cpuid(0, 0,
&m_high_basic,
@@ -34,46 +32,31 @@ cpu_id::cpu_id() :
reinterpret_cast<uint32_t *>(&m_vendor_id[4]));
__cpuid(cpuid_extended, 0, &m_high_ext);
}
if (m_high_ext >= cpuid_extended + 4) {
__cpuid(cpuid_extended + 2, 0,
reinterpret_cast<uint32_t *>(&m_brand_name[0]),
reinterpret_cast<uint32_t *>(&m_brand_name[4]),
reinterpret_cast<uint32_t *>(&m_brand_name[8]),
reinterpret_cast<uint32_t *>(&m_brand_name[12]));
__cpuid(cpuid_extended + 3, 0,
reinterpret_cast<uint32_t *>(&m_brand_name[16]),
reinterpret_cast<uint32_t *>(&m_brand_name[20]),
reinterpret_cast<uint32_t *>(&m_brand_name[24]),
reinterpret_cast<uint32_t *>(&m_brand_name[28]));
__cpuid(cpuid_extended + 4, 0,
reinterpret_cast<uint32_t *>(&m_brand_name[32]),
reinterpret_cast<uint32_t *>(&m_brand_name[36]),
reinterpret_cast<uint32_t *>(&m_brand_name[40]),
reinterpret_cast<uint32_t *>(&m_brand_name[44]));
} else {
m_brand_name[0] = 0;
}
cpu_id::features
cpu_id::validate() const
{
cpu_id::features feats;
uint32_t leaf = -1u;
uint32_t sub = -1u;
regs r;
#define CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit) \
if (leaf != feat_leaf || sub != feat_sub) { \
leaf = feat_leaf; sub = feat_sub; r = get(leaf, sub); \
} \
if (r.regname & (1ull << bit)) \
m_features |= (1ull << static_cast<uint64_t>(feature::name)); \
feats.set(feature::name);
#define CPU_FEATURE_REQ(name, feat_leaf, feat_sub, regname, bit) \
CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit); \
if ((r.regname & (1ull << bit)) == 0) { \
m_missing |= (1ull << static_cast<uint64_t>(feature::name)); \
}
CPU_FEATURE_OPT(name, feat_leaf, feat_sub, regname, bit);
#include "cpu/features.inc"
#undef CPU_FEATURE_OPT
#undef CPU_FEATURE_REQ
return feats;
}
cpu_id::regs
@@ -88,12 +71,6 @@ cpu_id::get(uint32_t leaf, uint32_t sub) const
return ret;
}
bool
cpu_id::has_feature(feature feat)
{
return (m_features & (1 << static_cast<uint64_t>(feat))) != 0;
}
uint8_t
cpu_id::local_apic_id() const
{
@@ -103,4 +80,29 @@ cpu_id::local_apic_id() const
return static_cast<uint8_t>(ebx >> 24);
}
bool
cpu_id::brand_name(char *buffer) const
{
if (m_high_ext < cpuid_extended + 4)
return false;
__cpuid(cpuid_extended + 2, 0,
reinterpret_cast<uint32_t *>(&buffer[0]),
reinterpret_cast<uint32_t *>(&buffer[4]),
reinterpret_cast<uint32_t *>(&buffer[8]),
reinterpret_cast<uint32_t *>(&buffer[12]));
__cpuid(cpuid_extended + 3, 0,
reinterpret_cast<uint32_t *>(&buffer[16]),
reinterpret_cast<uint32_t *>(&buffer[20]),
reinterpret_cast<uint32_t *>(&buffer[24]),
reinterpret_cast<uint32_t *>(&buffer[28]));
__cpuid(cpuid_extended + 4, 0,
reinterpret_cast<uint32_t *>(&buffer[32]),
reinterpret_cast<uint32_t *>(&buffer[36]),
reinterpret_cast<uint32_t *>(&buffer[40]),
reinterpret_cast<uint32_t *>(&buffer[44]));
return true;
}
}