Skip to content

Commit

Permalink
paging: Make PageTable Memory be owned by Rust
Browse files Browse the repository at this point in the history
This allows for less complex linking and less `unsafe` code. It also
frees up Rust to place the page tables wherever it wants.
  • Loading branch information
josephlr committed Feb 29, 2020
1 parent 3c6fad4 commit 48e46d1
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 36 deletions.
10 changes: 0 additions & 10 deletions layout.ld
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down
41 changes: 16 additions & 25 deletions src/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,49 @@ 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<Manager> = 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<Manager> = 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;
}
}

// 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");
}
Expand Down

0 comments on commit 48e46d1

Please sign in to comment.