[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:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user