feat: major overhaul and cleanup of paging and mm related code

This commit is contained in:
Zoe
2026-08-21 11:18:40 -05:00
parent af24a5a783
commit afcef918a3
15 changed files with 1040 additions and 628 deletions
+3
View File
@@ -3,3 +3,6 @@ mod x86_64;
#[cfg(target_arch = "x86_64")]
pub use x86_64::*;
#[cfg(target_arch = "x86_64")]
pub(crate) use x86_64::{PageTableCreateError, PageTableMapError, PageTableUnmapError};
+92
View File
@@ -0,0 +1,92 @@
use core::arch::asm;
#[derive(Debug)]
pub enum CpuFeaturesError {
CpuidFeaturesNotSupported,
InvalidPhysicalAddressWidth,
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct CpuFeatures {
pub nx_supported: bool,
pub nx_enabled: bool,
pub physical_address_bits: u8,
pub virtual_address_bits: u8,
}
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,
};
let cpuid_result = core::arch::x86_64::__cpuid_count(0x80000000, 0);
if cpuid_result.eax < 0x80000008 {
return Err(CpuFeaturesError::CpuidFeaturesNotSupported);
}
let cpuid_result = core::arch::x86_64::__cpuid_count(0x80000001, 0);
features.nx_supported = cpuid_result.edx & (1 << 20) != 0;
let cpuid_result = core::arch::x86_64::__cpuid_count(0x80000008, 0);
features.physical_address_bits = (cpuid_result.eax & 0xFF) as u8;
if !(12..=52).contains(&features.physical_address_bits) {
return Err(CpuFeaturesError::InvalidPhysicalAddressWidth);
}
features.virtual_address_bits = (cpuid_result.eax >> 8 & 0xFF) as u8;
if features.nx_supported {
let cpuid_result = core::arch::x86_64::__cpuid_count(0x1, 0);
let msr_supported = cpuid_result.edx & (1 << 5) != 0;
if !msr_supported {
return Err(CpuFeaturesError::CpuidFeaturesNotSupported);
}
// mother efer
let efer = unsafe { read_msr(0xC0000080) };
unsafe {
write_msr(0xC0000080, efer | (1 << 11));
}
features.nx_enabled = unsafe { read_msr(0xC0000080) } & (1 << 11) != 0;
}
Ok(features)
}
unsafe fn read_msr(msr: u32) -> u64 {
let low: u32;
let high: u32;
unsafe {
asm!(
"rdmsr",
in("ecx") msr,
out("eax") low,
out("edx") high,
options(nomem, nostack, preserves_flags),
);
}
((high as u64) << 32) | low as u64
}
unsafe fn write_msr(msr: u32, value: u64) {
unsafe {
asm!(
"wrmsr",
in("ecx") msr,
in("eax") value as u32,
in("edx") (value >> 32) as u32,
options(nomem, nostack, preserves_flags),
);
}
}
+17 -2
View File
@@ -25,7 +25,10 @@ SECTIONS
/* that is the beginning of the region. */
/* Additionally, leave space for the ELF headers by adding SIZEOF_HEADERS to the */
/* base load address. */
. = 0xffffffff80000000 + SIZEOF_HEADERS;
. = 0xffffffff80000000;
__text_start = .;
. += SIZEOF_HEADERS;
.text : {
*(.text .text.*)
@@ -33,6 +36,8 @@ SECTIONS
/* Move to the next memory page for .rodata */
. = ALIGN(CONSTANT(MAXPAGESIZE));
__text_end = .;
__rodata_start = .;
.rodata : {
*(.rodata .rodata.*)
@@ -40,7 +45,9 @@ SECTIONS
/* Move to the next memory page for .data */
. = ALIGN(CONSTANT(MAXPAGESIZE));
__rodata_end = .;
__data_start = .;
.data : {
*(.data .data.*)
@@ -56,6 +63,11 @@ SECTIONS
*(.dynamic)
} :data :dynamic
.got : {
*(.got .got.*)
*(.got.plt .got.plt.*)
} :data
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
/* unnecessary zeros will be written to the binary. */
/* If you need, for example, .init_array and .fini_array, those should be placed */
@@ -65,6 +77,9 @@ SECTIONS
*(COMMON)
} :data
. = ALIGN(CONSTANT(MAXPAGESIZE));
__data_end = .;
/* Discard .note.* and .eh_frame* since they may cause issues on some hosts. */
/* Also discard the program interpreter section since we do not need one. This is */
/* more or less equivalent to the --no-dynamic-linker linker flag, except that it */
+16 -2
View File
@@ -1,20 +1,34 @@
mod cpu;
mod gdt;
mod interrupts;
pub mod paging;
mod paging;
pub mod port;
use core::arch::asm;
pub use interrupts::disable_interrupts;
pub(crate) use paging::{
MapError as PageTableMapError, PageTableCreateError, UnmapError as PageTableUnmapError,
};
pub use paging::{PageTable, PagingConfig};
pub struct ArchState {
pub paging: PagingConfig,
}
use crate::println;
pub fn init() {
pub fn init() -> ArchState {
disable_interrupts();
println!("Loading GDT...");
gdt::init();
println!("Loading IDT...");
interrupts::init();
println!("Detecting CPU features...");
let cpu_features = cpu::detect_features_and_enable();
let paging =
PagingConfig::from_features(cpu_features.expect("required CPU features are not supported"));
ArchState { paging }
}
pub fn halt() {
+484 -529
View File
File diff suppressed because it is too large Load Diff
+21 -19
View File
@@ -1,20 +1,22 @@
{
"arch": "x86_64",
"cpu": "x86-64",
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
"llvm-target": "x86_64-unknown-none",
"target-endian": "little",
"target-pointer-width": 64,
"target-c-int-width": 32,
"features": "-mmx,-sse,+soft-float",
"rustc-abi": "softfloat",
"os": "DawnOS",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"pre-link-args": {
"ld.lld": ["-melf_x86_64", "--script=./src/arch/x86_64/linker.ld"]
},
"panic-strategy": "abort",
"exe-suffix": ".elf",
"disable-redzone": true
}
"arch": "x86_64",
"cpu": "x86-64",
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
"llvm-target": "x86_64-unknown-none",
"target-endian": "little",
"target-pointer-width": 64,
"target-c-int-width": 32,
"features": "-mmx,-sse,+soft-float",
"rustc-abi": "softfloat",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"pre-link-args": {
"ld.lld": [
"-melf_x86_64",
"--script=./src/arch/x86_64/linker.ld"
]
},
"panic-strategy": "abort",
"exe-suffix": ".elf",
"disable-redzone": true
}