feat: acpi, apic, apic timer
This commit is contained in:
+35
-5
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user