feat: acpi, apic, apic timer

This commit is contained in:
Zoe
2026-08-27 13:09:11 -05:00
parent afcef918a3
commit 7dcf244ee6
22 changed files with 2394 additions and 382 deletions
+35 -5
View File
@@ -4,6 +4,7 @@ use core::arch::asm;
pub enum CpuFeaturesError {
CpuidFeaturesNotSupported,
InvalidPhysicalAddressWidth,
InvalidVirtualAddressWidth,
}
#[derive(Clone, Copy, Debug)]
@@ -12,14 +13,19 @@ pub(crate) struct CpuFeatures {
pub nx_enabled: bool,
pub physical_address_bits: u8,
pub virtual_address_bits: u8,
pub five_level_paging_active: bool,
}
// Extended features
const IA32_EFER: u32 = 0xC0000080;
pub fn detect_features_and_enable() -> Result<CpuFeatures, CpuFeaturesError> {
let mut features = CpuFeatures {
nx_supported: false,
nx_enabled: false,
physical_address_bits: 0,
virtual_address_bits: 0,
five_level_paging_active: false,
};
let cpuid_result = core::arch::x86_64::__cpuid_count(0x80000000, 0);
@@ -40,6 +46,16 @@ pub fn detect_features_and_enable() -> Result<CpuFeatures, CpuFeaturesError> {
}
features.virtual_address_bits = (cpuid_result.eax >> 8 & 0xFF) as u8;
features.five_level_paging_active = read_cr4() & (1 << 12) != 0;
let required_virtual_address_bits = if features.five_level_paging_active {
57
} else {
48
};
if features.virtual_address_bits < required_virtual_address_bits {
return Err(CpuFeaturesError::InvalidVirtualAddressWidth);
}
if features.nx_supported {
let cpuid_result = core::arch::x86_64::__cpuid_count(0x1, 0);
@@ -50,19 +66,33 @@ pub fn detect_features_and_enable() -> Result<CpuFeatures, CpuFeaturesError> {
}
// mother efer
let efer = unsafe { read_msr(0xC0000080) };
let efer = unsafe { read_msr(IA32_EFER) };
unsafe {
write_msr(0xC0000080, efer | (1 << 11));
write_msr(IA32_EFER, efer | (1 << 11));
}
features.nx_enabled = unsafe { read_msr(0xC0000080) } & (1 << 11) != 0;
features.nx_enabled = unsafe { read_msr(IA32_EFER) } & (1 << 11) != 0;
}
Ok(features)
}
unsafe fn read_msr(msr: u32) -> u64 {
fn read_cr4() -> usize {
let value: usize;
unsafe {
asm!(
"mov {}, cr4",
out(reg) value,
options(nomem, nostack, preserves_flags),
);
}
value
}
pub(super) unsafe fn read_msr(msr: u32) -> u64 {
let low: u32;
let high: u32;
@@ -79,7 +109,7 @@ unsafe fn read_msr(msr: u32) -> u64 {
((high as u64) << 32) | low as u64
}
unsafe fn write_msr(msr: u32, value: u64) {
pub(super) unsafe fn write_msr(msr: u32, value: u64) {
unsafe {
asm!(
"wrmsr",