mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
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.
107 lines
2.6 KiB
C++
107 lines
2.6 KiB
C++
#include <cpu/cpu_id.h>
|
|
|
|
#include "console.h"
|
|
#include "error.h"
|
|
#include "hardware.h"
|
|
#include "status.h"
|
|
|
|
namespace boot {
|
|
namespace hw {
|
|
|
|
void *
|
|
find_acpi_table(uefi::system_table *st)
|
|
{
|
|
status_line status(L"Searching for ACPI table");
|
|
|
|
// Find ACPI tables. Ignore ACPI 1.0 if a 2.0 table is found.
|
|
uintptr_t acpi1_table = 0;
|
|
|
|
for (size_t i = 0; i < st->number_of_table_entries; ++i) {
|
|
uefi::configuration_table *table = &st->configuration_table[i];
|
|
|
|
// If we find an ACPI 2.0 table, return it immediately
|
|
if (table->vendor_guid == uefi::vendor_guids::acpi2)
|
|
return table->vendor_table;
|
|
|
|
if (table->vendor_guid == uefi::vendor_guids::acpi1) {
|
|
// Mark a v1 table with the LSB high
|
|
acpi1_table = reinterpret_cast<uintptr_t>(table->vendor_table);
|
|
acpi1_table |= 1;
|
|
}
|
|
}
|
|
|
|
if (!acpi1_table) {
|
|
error::raise(uefi::status::not_found, L"Could not find ACPI table");
|
|
} else if (acpi1_table & 1) {
|
|
status_line::warn(L"Only found ACPI 1.0 table");
|
|
}
|
|
|
|
return reinterpret_cast<void*>(acpi1_table);
|
|
}
|
|
|
|
static uint64_t
|
|
rdmsr(uint32_t addr)
|
|
{
|
|
uint32_t low, high;
|
|
__asm__ __volatile__ ("rdmsr" : "=a"(low), "=d"(high) : "c"(addr));
|
|
return (static_cast<uint64_t>(high) << 32) | low;
|
|
}
|
|
|
|
static void
|
|
wrmsr(uint32_t addr, uint64_t value)
|
|
{
|
|
uint32_t low = value & 0xffffffff;
|
|
uint32_t high = value >> 32;
|
|
__asm__ __volatile__ ("wrmsr" :: "c"(addr), "a"(low), "d"(high));
|
|
}
|
|
|
|
void
|
|
setup_control_regs()
|
|
{
|
|
uint64_t cr4 = 0;
|
|
asm volatile ( "mov %%cr4, %0" : "=r" (cr4) );
|
|
cr4 |=
|
|
0x000080 | // Enable global pages
|
|
0x000200 | // Enable FXSAVE/FXRSTOR
|
|
0x010000 | // Enable FSGSBASE
|
|
0x020000 | // Enable PCIDs
|
|
0;
|
|
asm volatile ( "mov %0, %%cr4" :: "r" (cr4) );
|
|
|
|
// Set up IA32_EFER
|
|
constexpr uint32_t IA32_EFER = 0xC0000080;
|
|
uint64_t efer = rdmsr(IA32_EFER);
|
|
efer |=
|
|
0x0001 | // Enable SYSCALL
|
|
0x0800 | // Enable NX bit
|
|
0;
|
|
wrmsr(IA32_EFER, efer);
|
|
}
|
|
|
|
void
|
|
check_cpu_supported()
|
|
{
|
|
status_line status {L"Checking CPU features"};
|
|
|
|
cpu::cpu_id cpu;
|
|
cpu::cpu_id::features features = cpu.validate();
|
|
bool supported = true;
|
|
|
|
#define CPU_FEATURE_OPT(...)
|
|
#define CPU_FEATURE_REQ(name, ...) \
|
|
if (!features[cpu::feature::name]) { \
|
|
status::fail(L"CPU required feature " L ## #name, uefi::status::unsupported); \
|
|
supported = false; \
|
|
}
|
|
#include "cpu/features.inc"
|
|
#undef CPU_FEATURE_REQ
|
|
#undef CPU_FEATURE_OPT
|
|
|
|
if (!supported)
|
|
error::raise(uefi::status::unsupported, L"CPU not supported");
|
|
}
|
|
|
|
|
|
} // namespace hw
|
|
} // namespace boot
|