|
1 |
| -use atomic_refcell::AtomicRefCell; |
2 | 1 | use x86_64::{
|
3 | 2 | registers::control::Cr3,
|
4 | 3 | structures::paging::{PageSize, PageTable, PageTableFlags, PhysFrame, Size2MiB},
|
5 | 4 | PhysAddr,
|
6 | 5 | };
|
7 | 6 |
|
8 |
| -// This is the number of GiB we will identity map. |
| 7 | +// Amount of memory we identity map in setup(), max 512 GiB. |
9 | 8 | const ADDRESS_SPACE_GIB: usize = 4;
|
10 | 9 |
|
11 |
| -pub static MANAGER: AtomicRefCell<Manager> = AtomicRefCell::new(Manager::new()); |
12 |
| -pub struct Manager { |
13 |
| - l4: PageTable, |
14 |
| - l3: PageTable, |
15 |
| - l2s: [PageTable; ADDRESS_SPACE_GIB], |
16 |
| -} |
17 |
| - |
18 |
| -impl Manager { |
19 |
| - const fn new() -> Self { |
20 |
| - Manager { |
21 |
| - l4: PageTable::new(), |
22 |
| - l3: PageTable::new(), |
23 |
| - l2s: [PageTable::new(); ADDRESS_SPACE_GIB], |
| 10 | +// Put the Page Tables in static muts to make linking easier |
| 11 | +#[no_mangle] |
| 12 | +static mut L4_TABLE: PageTable = PageTable::new(); |
| 13 | +#[no_mangle] |
| 14 | +static mut L3_TABLE: PageTable = PageTable::new(); |
| 15 | +#[no_mangle] |
| 16 | +static mut L2_TABLES: [PageTable; ADDRESS_SPACE_GIB] = [PageTable::new(); ADDRESS_SPACE_GIB]; |
| 17 | + |
| 18 | +pub fn setup() { |
| 19 | + // SAFETY: This function is idempontent and only writes to static memory and |
| 20 | + // CR3. Thus, it is safe to run multiple times or on multiple threads. |
| 21 | + let (l4, l3, l2s) = unsafe { (&mut L4_TABLE, &mut L3_TABLE, &mut L2_TABLES) }; |
| 22 | + log!("Setting up {} GiB identity mapping", ADDRESS_SPACE_GIB); |
| 23 | + let pt_flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; |
| 24 | + |
| 25 | + // Setup Identity map using L2 huge pages |
| 26 | + let mut next_addr = PhysAddr::new(0); |
| 27 | + for l2 in l2s.iter_mut() { |
| 28 | + for l2e in l2.iter_mut() { |
| 29 | + l2e.set_addr(next_addr, pt_flags | PageTableFlags::HUGE_PAGE); |
| 30 | + next_addr += Size2MiB::SIZE; |
24 | 31 | }
|
25 | 32 | }
|
26 | 33 |
|
27 |
| - pub fn setup(&mut self) { |
28 |
| - log!("Setting up {} GiB identity mapping", ADDRESS_SPACE_GIB); |
29 |
| - |
30 |
| - let pt_flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; |
31 |
| - // Setup Identity map using L2 huge pages |
32 |
| - let mut next_addr = PhysAddr::new(0); |
33 |
| - for l2 in self.l2s.iter_mut() { |
34 |
| - for l2e in l2.iter_mut() { |
35 |
| - l2e.set_addr(next_addr, pt_flags | PageTableFlags::HUGE_PAGE); |
36 |
| - next_addr += Size2MiB::SIZE; |
37 |
| - } |
38 |
| - } |
39 |
| - |
40 |
| - // Point L3 at L2s |
41 |
| - for (i, l2) in self.l2s.iter().enumerate() { |
42 |
| - self.l3[i].set_addr(phys_addr(l2), pt_flags); |
43 |
| - } |
| 34 | + // Point L3 at L2s |
| 35 | + for (i, l2) in l2s.iter().enumerate() { |
| 36 | + l3[i].set_addr(phys_addr(l2), pt_flags); |
| 37 | + } |
44 | 38 |
|
45 |
| - // Point L4 at L3 |
46 |
| - self.l4[0].set_addr(phys_addr(&self.l3), pt_flags); |
| 39 | + // Point L4 at L3 |
| 40 | + l4[0].set_addr(phys_addr(l3), pt_flags); |
47 | 41 |
|
48 |
| - // Point Cr3 at PML4 |
49 |
| - let cr3_flags = Cr3::read().1; |
50 |
| - let pml4t_frame = PhysFrame::from_start_address(phys_addr(&self.l4)).unwrap(); |
51 |
| - unsafe { Cr3::write(pml4t_frame, cr3_flags) }; |
52 |
| - log!("Page tables setup"); |
| 42 | + // Point Cr3 at L4 |
| 43 | + let (cr3_frame, cr3_flags) = Cr3::read(); |
| 44 | + let l4_frame = PhysFrame::from_start_address(phys_addr(l4)).unwrap(); |
| 45 | + if cr3_frame != l4_frame { |
| 46 | + unsafe { Cr3::write(l4_frame, cr3_flags) }; |
53 | 47 | }
|
| 48 | + log!("Page tables setup"); |
54 | 49 | }
|
55 | 50 |
|
56 | 51 | // Map a virtual address to a PhysAddr (assumes identity mapping)
|
|
0 commit comments