From 48e46d13719c0ced708d1f9c03fd10cbac0c7efb Mon Sep 17 00:00:00 2001 From: Joe Richey Date: Fri, 28 Feb 2020 20:06:53 -0800 Subject: [PATCH] paging: Make PageTable Memory be owned by Rust This allows for less complex linking and less `unsafe` code. It also frees up Rust to place the page tables wherever it wants. --- layout.ld | 10 ---------- src/main.rs | 2 +- src/paging.rs | 41 ++++++++++++++++------------------------- 3 files changed, 17 insertions(+), 36 deletions(-) diff --git a/layout.ld b/layout.ld index af87cf45..4a6bda51 100644 --- a/layout.ld +++ b/layout.ld @@ -13,10 +13,6 @@ ram_max = 2M; /* Our stack grows down from ram_max. TODO: Add a guard for stack overflows. */ stack_size = 64K; -/* Pagetable locations loaded by Firecracker/cloud-hypervisor */ -pml4t = 0x9000; -pml3t = 0xa000; - SECTIONS { /* Mapping in the program headers makes it easier to mmap the whole file. */ @@ -32,12 +28,6 @@ SECTIONS firmware_ram_size = . - ram_min; - /* Memory for identity mapping, keep synced with ADDRESS_SPACE_GIB */ - address_space_gib = 4; - . = ALIGN(4K); - pml2ts = .; - . += 4K * address_space_gib; - ASSERT((. <= ram_max - stack_size), "firmware size too big for RAM region") /* Match edk2's GccBase.lds DISCARD section */ diff --git a/src/main.rs b/src/main.rs index 2c6b3766..61c343ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![feature(global_asm)] +#![feature(global_asm, const_in_array_repeat_expressions)] #![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_main)] #![cfg_attr(test, allow(unused_imports, dead_code))] diff --git a/src/paging.rs b/src/paging.rs index b10a5fda..3b3124fa 100644 --- a/src/paging.rs +++ b/src/paging.rs @@ -5,41 +5,32 @@ use x86_64::{ PhysAddr, }; -// Keep in sync with address_space_gib in layout.ld +// This is the number of GiB we will identity map. const ADDRESS_SPACE_GIB: usize = 4; -pub static MANAGER: AtomicRefCell = AtomicRefCell::new(Manager); -pub struct Manager; - -extern "C" { - static mut pml4t: PageTable; - static mut pml3t: PageTable; - static mut pml2ts: [PageTable; ADDRESS_SPACE_GIB]; -} - -struct Tables<'a> { - l4: &'a mut PageTable, - l3: &'a mut PageTable, - l2s: &'a mut [PageTable], +pub static MANAGER: AtomicRefCell = AtomicRefCell::new(Manager::new()); +pub struct Manager { + l4: PageTable, + l3: PageTable, + l2s: [PageTable; ADDRESS_SPACE_GIB], } impl Manager { - fn tables(&mut self) -> Tables { - Tables { - l4: unsafe { &mut pml4t }, - l3: unsafe { &mut pml3t }, - l2s: unsafe { &mut pml2ts }, + const fn new() -> Self { + Manager { + l4: PageTable::new(), + l3: PageTable::new(), + l2s: [PageTable::new(); ADDRESS_SPACE_GIB], } } pub fn setup(&mut self) { log!("Setting up {} GiB identity mapping", ADDRESS_SPACE_GIB); - let Tables { l4, l3, l2s } = self.tables(); let pt_flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; // Setup Identity map using L2 huge pages let mut next_addr = PhysAddr::new(0); - for l2 in l2s.iter_mut() { + for l2 in self.l2s.iter_mut() { for l2e in l2.iter_mut() { l2e.set_addr(next_addr, pt_flags | PageTableFlags::HUGE_PAGE); next_addr += Size2MiB::SIZE; @@ -47,16 +38,16 @@ impl Manager { } // Point L3 at L2s - for (i, l2) in l2s.iter().enumerate() { - l3[i].set_addr(phys_addr(l2), pt_flags); + for (i, l2) in self.l2s.iter().enumerate() { + self.l3[i].set_addr(phys_addr(l2), pt_flags); } // Point L4 at L3 - l4[0].set_addr(phys_addr(l3), pt_flags); + self.l4[0].set_addr(phys_addr(&self.l3), pt_flags); // Point Cr3 at PML4 let cr3_flags = Cr3::read().1; - let pml4t_frame = PhysFrame::from_start_address(phys_addr(l4)).unwrap(); + let pml4t_frame = PhysFrame::from_start_address(phys_addr(&self.l4)).unwrap(); unsafe { Cr3::write(pml4t_frame, cr3_flags) }; log!("Page tables setup"); }