[cpu] Rename cpu_id::validate() to cpu_id::features()

Validate wasn't a correct name anymore. Also move the features enum out
of the cpu_id class scope and into the `cpu` namespace directly.
This commit is contained in:
Justin C. Miller
2023-03-16 19:41:07 -07:00
parent 201e7191ef
commit bfab4f085e
6 changed files with 51 additions and 22 deletions

View File

@@ -79,7 +79,7 @@ check_cpu_supported()
status_line status {L"Checking CPU features"}; status_line status {L"Checking CPU features"};
cpu::cpu_id cpu; cpu::cpu_id cpu;
cpu::cpu_id::features features = cpu.validate(); cpu::features features = cpu.features();
bool supported = true; bool supported = true;
#define CPU_FEATURE_OPT(...) #define CPU_FEATURE_OPT(...)

View File

@@ -2,10 +2,10 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <util/bitset.h> #include <util/bitset.h>
#include <util/no_construct.h>
#include "assert.h" #include "assert.h"
#include "cpu.h" #include "cpu.h"
#include "cpu/cpu_id.h"
#include "device_manager.h" #include "device_manager.h"
#include "gdt.h" #include "gdt.h"
#include "idt.h" #include "idt.h"
@@ -20,38 +20,49 @@ unsigned g_num_cpus = 1;
panic_data g_panic_data; panic_data g_panic_data;
panic_data *g_panic_data_p = &g_panic_data; panic_data *g_panic_data_p = &g_panic_data;
cpu_data g_bsp_cpu_data; static util::no_construct<cpu_data> __g_bsp_cpu_storage;
cpu_data &g_bsp_cpu_data = __g_bsp_cpu_storage.value;
cpu_data **g_cpu_data = nullptr; cpu_data **g_cpu_data = nullptr;
static cpu::features
get_features()
{
cpu::cpu_id cpuid;
return cpuid.features();
}
// Validate the required CPU features are present. Really, the bootloader already // Validate the required CPU features are present. Really, the bootloader already
// validated the required features, but still iterate the options and log about them. // validated the required features, but still iterate the options and log about them.
void static cpu::features
cpu_validate() cpu_validate(cpu_data *c)
{ {
cpu::cpu_id cpu; cpu::cpu_id cpuid;
char brand_name[50]; char brand_name[50];
cpu.brand_name(brand_name); cpuid.brand_name(brand_name);
cpu::cpu_id::features features = cpu.validate(); cpu::features &features = c->features;
log::info(logs::boot, "CPU: %s", brand_name); log::info(logs::boot, "CPU %2d: %s", c->index, brand_name);
log::info(logs::boot, " Vendor is %s", cpu.vendor_id()); log::info(logs::boot, " Vendor is %s", cpuid.vendor_id());
log::spam(logs::boot, " Higest basic CPUID: 0x%02x", cpu.highest_basic()); log::spam(logs::boot, " Higest basic CPUID: 0x%02x", cpuid.highest_basic());
log::spam(logs::boot, " Higest ext CPUID: 0x%02x", cpu.highest_ext() & ~cpu::cpu_id::cpuid_extended); log::spam(logs::boot, " Higest ext CPUID: 0x%02x", cpuid.highest_ext() & ~cpu::cpu_id::cpuid_extended);
#define CPU_FEATURE_OPT(name, ...) \ #define CPU_FEATURE_OPT(name, ...) \
log::verbose(logs::boot, " Supports %9s: %s", #name, features[cpu::feature::name] ? "yes" : "no"); log::verbose(logs::boot, " Flag %11s: %s", #name, features[cpu::feature::name] ? "yes" : "no");
#define CPU_FEATURE_REQ(name, feat_leaf, feat_sub, regname, bit) \ #define CPU_FEATURE_REQ(name, feat_leaf, feat_sub, regname, bit) \
log::verbose(logs::boot, " Supports %9s: %s", #name, features[cpu::feature::name] ? "yes" : "no"); \ log::verbose(logs::boot, " Flag %11s: %s", #name, features[cpu::feature::name] ? "yes" : "no"); \
kassert(features[cpu::feature::name], "Missing required CPU feature " #name ); kassert(features[cpu::feature::name], "Missing required CPU feature " #name );
#include "cpu/features.inc" #include "cpu/features.inc"
#undef CPU_FEATURE_OPT #undef CPU_FEATURE_OPT
#undef CPU_FEATURE_REQ #undef CPU_FEATURE_REQ
return features;
} }
@@ -70,13 +81,24 @@ cpu_early_init(cpu_data *cpu)
.clear(cr0::CD); .clear(cr0::CD);
asm volatile ( "mov %0, %%cr0" :: "r" (cr0_val) ); asm volatile ( "mov %0, %%cr0" :: "r" (cr0_val) );
cpu->features = get_features();
uintptr_t cr3_val;
asm ("mov %%cr3, %0" : "=r"(cr3_val));
util::bitset64 cr4_val = 0; util::bitset64 cr4_val = 0;
asm ("mov %%cr4, %0" : "=r"(cr4_val)); asm ("mov %%cr4, %0" : "=r"(cr4_val));
cr4_val cr4_val
.set(cr4::OSXFSR) .set(cr4::OSXFSR)
.set(cr4::OSXMMEXCPT) .set(cr4::OSXMMEXCPT)
.set(cr4::PCIDE)
.set(cr4::OSXSAVE); .set(cr4::OSXSAVE);
// TODO: On KVM setting PCIDE generates a #GP even though
// the feature is listed as available in CPUID.
/*
if (cpu->features[cpu::feature::pcid])
cr4_val.set(cr4::PCIDE);
*/
asm volatile ( "mov %0, %%cr4" :: "r" (cr4_val) ); asm volatile ( "mov %0, %%cr4" :: "r" (cr4_val) );
// Enable SYSCALL and NX bit // Enable SYSCALL and NX bit
@@ -98,7 +120,6 @@ cpu_early_init(cpu_data *cpu)
cpu_data * cpu_data *
bsp_early_init() bsp_early_init()
{ {
cpu_validate();
memset(&g_panic_data, 0, sizeof(g_panic_data)); memset(&g_panic_data, 0, sizeof(g_panic_data));
extern IDT &g_bsp_idt; extern IDT &g_bsp_idt;
@@ -135,7 +156,12 @@ bsp_late_init()
uint64_t xcr0v = get_xcr0(); uint64_t xcr0v = get_xcr0();
uint64_t efer = rdmsr(msr::ia32_efer); uint64_t efer = rdmsr(msr::ia32_efer);
<<<<<<< HEAD
log::spam(logs::boot, "Control regs: cr0:%lx cr4:%lx efer:%lx mxcsr:%x xcr0:%x", cr0v, cr4v, efer, mxcsrv, xcr0v); log::spam(logs::boot, "Control regs: cr0:%lx cr4:%lx efer:%lx mxcsr:%x xcr0:%x", cr0v, cr4v, efer, mxcsrv, xcr0v);
=======
log::spam(logs::boot, "Control regs: cr0:%lx cr4:%lx efer:%lx", cr0v, cr4v, efer);
cpu_validate(&g_bsp_cpu_data);
>>>>>>> 66a5273 ([cpu] Rename cpu_id::validate() to cpu_id::features())
} }
cpu_data * cpu_data *

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <cpu/cpu_id.h>
class GDT; class GDT;
class IDT; class IDT;
@@ -128,6 +129,7 @@ struct cpu_data
// the assembly version // the assembly version
lapic *apic; lapic *apic;
panic_data *panic; panic_data *panic;
cpu::features features;
}; };
extern "C" { extern "C" {

View File

@@ -16,10 +16,11 @@ enum class feature {
max max
}; };
using features = util::bitset<(unsigned)feature::max>;
class cpu_id class cpu_id
{ {
public: public:
using features = util::bitset<(unsigned)feature::max>;
static constexpr uint32_t cpuid_extended = 0x80000000; static constexpr uint32_t cpuid_extended = 0x80000000;
/// CPUID result register values /// CPUID result register values
@@ -46,7 +47,7 @@ public:
/// Check which of the cpu::feature flags this CPU supports. /// Check which of the cpu::feature flags this CPU supports.
/// \returns A util::bitset mapping to cpu::feature values /// \returns A util::bitset mapping to cpu::feature values
features validate() const; features features() const;
/// The the result of a given CPUID leaf/subleaf /// The the result of a given CPUID leaf/subleaf
/// \arg leaf The leaf selector (initial EAX) /// \arg leaf The leaf selector (initial EAX)

View File

@@ -2,7 +2,7 @@
CPU_FEATURE_OPT(pcid, 0x00000001, 0, ecx, 17) CPU_FEATURE_OPT(pcid, 0x00000001, 0, ecx, 17)
CPU_FEATURE_OPT(x2apic, 0x00000001, 0, ecx, 21) CPU_FEATURE_OPT(x2apic, 0x00000001, 0, ecx, 21)
CPU_FEATURE_REQ(xsave, 0x00000001, 0, ecx, 26) CPU_FEATURE_REQ(xsave, 0x00000001, 0, ecx, 26)
CPU_FEATURE_OPT(in_hv, 0x00000001, 0, ecx, 31) CPU_FEATURE_OPT(hypervisor, 0x00000001, 0, ecx, 31)
CPU_FEATURE_REQ(fpu, 0x00000001, 0, edx, 0) CPU_FEATURE_REQ(fpu, 0x00000001, 0, edx, 0)
CPU_FEATURE_REQ(pse, 0x00000001, 0, edx, 3) CPU_FEATURE_REQ(pse, 0x00000001, 0, edx, 3)

View File

@@ -34,10 +34,10 @@ cpu_id::cpu_id()
__cpuid(cpuid_extended, 0, &m_high_ext); __cpuid(cpuid_extended, 0, &m_high_ext);
} }
cpu_id::features features
cpu_id::validate() const cpu_id::features() const
{ {
cpu_id::features feats; ::cpu::features feats;
uint32_t leaf = -1u; uint32_t leaf = -1u;
uint32_t sub = -1u; uint32_t sub = -1u;
regs r; regs r;