Add CPU feature checking.
Introduces the cpu_features.inc table to enumerate the CPU features that j6 cares about. Features in this table marked CPU_FEATURE_REQ are considered required, and the boot process will log an error and halt when any of these features are not supported. This should save me from banging my head against the wall like I did last night with the missing pdpe1gb feature.
This commit is contained in:
@@ -23,40 +23,69 @@ struct cpu_data
|
||||
|
||||
extern cpu_data bsp_cpu_data;
|
||||
|
||||
/// Enum of the cpu features jsix cares about
|
||||
enum class cpu_feature {
|
||||
#define CPU_FEATURE_REQ(name, ...) name,
|
||||
#define CPU_FEATURE_OPT(name, ...) name,
|
||||
#include "cpu_features.inc"
|
||||
#undef CPU_FEATURE_OPT
|
||||
#undef CPU_FEATURE_REQ
|
||||
max
|
||||
};
|
||||
|
||||
class cpu_id
|
||||
{
|
||||
public:
|
||||
/// CPUID result register values
|
||||
struct regs {
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
|
||||
regs() : eax(0), ebx(0), ecx(0), edx(0) {}
|
||||
regs(uint32_t a, uint32_t b, uint32_t c, uint32_t d) : eax(a), ebx(b), ecx(c), edx(d) {}
|
||||
regs(const regs &r) : eax(r.eax), ebx(r.ebx), ecx(r.ecx), edx(r.edx) {}
|
||||
union {
|
||||
uint32_t reg[4];
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
};
|
||||
|
||||
/// Return true if bit |bit| of EAX is set
|
||||
bool eax_bit(unsigned bit) { return (eax >> bit) & 0x1; }
|
||||
|
||||
/// Return true if bit |bit| of EBX is set
|
||||
bool ebx_bit(unsigned bit) { return (ebx >> bit) & 0x1; }
|
||||
|
||||
/// Return true if bit |bit| of ECX is set
|
||||
bool ecx_bit(unsigned bit) { return (ecx >> bit) & 0x1; }
|
||||
|
||||
/// Return true if bit |bit| of EDX is set
|
||||
bool edx_bit(unsigned bit) { return (edx >> bit) & 0x1; }
|
||||
};
|
||||
|
||||
cpu_id();
|
||||
|
||||
/// The the result of a given CPUID leaf/subleaf
|
||||
/// \arg leaf The leaf selector (initial EAX)
|
||||
/// \arg subleaf The subleaf selector (initial ECX)
|
||||
/// \returns A |regs| struct of the values retuned
|
||||
regs get(uint32_t leaf, uint32_t sub = 0) const;
|
||||
|
||||
/// Get the name of the cpu vendor (eg, "GenuineIntel")
|
||||
inline const char * vendor_id() const { return m_vendor_id; }
|
||||
inline uint8_t cpu_type() const { return m_cpu_type; }
|
||||
inline uint8_t stepping() const { return m_stepping; }
|
||||
inline uint16_t family() const { return m_family; }
|
||||
inline uint16_t model() const { return m_model; }
|
||||
|
||||
/// Get the brand name of this processor model
|
||||
inline const char * brand_name() const { return m_brand_name; }
|
||||
|
||||
/// Get the highest basic CPUID leaf supported
|
||||
inline uint32_t highest_basic() const { return m_high_basic; }
|
||||
|
||||
/// Get the highest extended CPUID leaf supported
|
||||
inline uint32_t highest_ext() const { return m_high_ext; }
|
||||
|
||||
/// Validate the CPU supports the necessary options for jsix
|
||||
void validate();
|
||||
|
||||
/// Return true if the CPU claims to support the given feature
|
||||
bool has_feature(cpu_feature feat);
|
||||
|
||||
private:
|
||||
void read();
|
||||
|
||||
uint32_t m_high_leaf;
|
||||
uint32_t m_high_basic;
|
||||
uint32_t m_high_ext;
|
||||
char m_vendor_id[13];
|
||||
|
||||
uint8_t m_cpu_type;
|
||||
uint8_t m_stepping;
|
||||
uint16_t m_family;
|
||||
uint16_t m_model;
|
||||
char m_brand_name[48];
|
||||
uint64_t m_features;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user