feat: major overhaul and cleanup of paging and mm related code
This commit is contained in:
@@ -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),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user