set pagetable, doesn't work

This commit is contained in:
Artemis Tosini 2024-08-04 19:23:43 +00:00
parent 08291808c7
commit a5da22da18
Signed by: artemist
GPG key ID: EE5227935FE3FF18
3 changed files with 88 additions and 12 deletions

25
Cargo.lock generated
View file

@ -27,6 +27,7 @@ dependencies = [
"goblin",
"log",
"uefi",
"x86_64",
]
[[package]]
@ -90,6 +91,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rustversion"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "scroll"
version = "0.12.0"
@ -190,3 +197,21 @@ name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "volatile"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793"
[[package]]
name = "x86_64"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
dependencies = [
"bit_field",
"bitflags",
"rustversion",
"volatile",
]

View file

@ -7,3 +7,4 @@ edition = "2021"
uefi = { version = "0.29.0", default-features = false, features = [ "alloc", "global_allocator", "panic_handler", "logger" ] }
log = { version = "0.4.22", default-features = false }
goblin = { version = "0.8.2", default-features = false, features = [ "elf64", "elf32", "endian_fd" ] }
x86_64 = { version = "0.15.1", default-features = false }

View file

@ -3,10 +3,13 @@ pub use x86_64::boot_kernel;
#[cfg(target_arch = "x86_64")]
mod x86_64 {
use core::{arch::global_asm, ptr::null, slice};
use core::{arch::global_asm, slice};
use uefi::table::{Boot, SystemTable};
use uefi::table::{boot::PAGE_SIZE, Boot, SystemTable};
use x86_64::{
structures::paging::{PageTable, PageTableFlags},
PhysAddr,
};
use crate::{object::Kernel, staging::allocate_code};
@ -38,7 +41,7 @@ trampoline_size:
fn trampoline_code(
stack: *const u8,
pagetable: *const u8,
pagetable: *const PageTable,
modinfo_base: *const u8,
free_ptr: *const u8,
entry: *const u8,
@ -46,7 +49,17 @@ trampoline_size:
}
type TrampolineFunction =
extern "sysv64" fn(*const u8, *const u8, *const u8, *const u8, *const u8);
extern "sysv64" fn(*const u8, *const PageTable, *const u8, *const u8, *const u8);
#[repr(C, align(4096))]
struct MiscBuf {
stack: [u8; PAGE_SIZE],
trampoline: [u8; PAGE_SIZE],
pt4: PageTable,
pt3_lower: PageTable,
pt3_upper: PageTable,
pt2_upper: PageTable,
}
pub fn boot_kernel(
system_table: SystemTable<Boot>,
@ -55,19 +68,56 @@ trampoline_size:
modinfo_base: *const u8,
free_ptr: *const u8,
) {
let trampoline_code_size = unsafe { trampoline_size } as usize;
let misc_buf = allocate_code(system_table.boot_services(), trampoline_code_size + 64);
let misc_alloc = allocate_code(
system_table.boot_services(),
core::mem::size_of::<MiscBuf>(),
);
// allocate_code is always page aligned, so we'll always meet 4096 alignment for MiscBuf
let misc_buf = unsafe { (misc_alloc.as_mut_ptr() as *mut MiscBuf).as_mut().unwrap() };
let (stack_buf, trampoline_buf) = misc_buf.split_at_mut(64);
trampoline_buf[..trampoline_code_size].copy_from_slice(unsafe {
let trampoline_code_size = unsafe { trampoline_size } as usize;
misc_buf.trampoline[..trampoline_code_size].copy_from_slice(unsafe {
slice::from_raw_parts(trampoline_code as *const u8, trampoline_code_size)
});
// Map the lower 512G of RAM identity-mapped with 1GiB pages
for (idx, pte) in misc_buf.pt3_lower.iter_mut().enumerate() {
pte.set_addr(
PhysAddr::new((idx as u64) << 30),
PageTableFlags::PRESENT | PageTableFlags::HUGE_PAGE | PageTableFlags::WRITABLE,
);
}
misc_buf.pt4[0].set_addr(
PhysAddr::new(&misc_buf.pt3_lower as *const PageTable as usize as u64),
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
);
// Map the kernel to 2GiB from the top of RAM with 2MiB pages
for (idx, pte) in misc_buf.pt2_upper.iter_mut().enumerate() {
let addr = kernel_base as usize + (idx << 21);
pte.set_addr(
PhysAddr::new(addr as u64),
PageTableFlags::PRESENT | PageTableFlags::HUGE_PAGE | PageTableFlags::WRITABLE,
);
}
// 512 entries, each pt3 entry represents 1GiB
misc_buf.pt3_upper[510].set_addr(
PhysAddr::new(&misc_buf.pt2_upper as *const PageTable as usize as u64),
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
);
// 512 entries, each pt4 entry represents 512GiB
misc_buf.pt4[511].set_addr(
PhysAddr::new(&misc_buf.pt3_upper as *const PageTable as usize as u64),
PageTableFlags::PRESENT | PageTableFlags::WRITABLE,
);
unsafe {
let trampoline_func: TrampolineFunction = core::mem::transmute(trampoline_buf.as_ptr());
let trampoline_func: TrampolineFunction =
core::mem::transmute(misc_buf.trampoline.as_ptr());
trampoline_func(
stack_buf.as_ptr(),
null(),
&misc_buf.stack[PAGE_SIZE - 8] as *const u8,
&misc_buf.pt4 as *const PageTable,
modinfo_base,
free_ptr,
kernel.entry_addr(kernel_base),