1- use atomic_refcell:: AtomicRefCell ;
21use x86_64:: {
32 registers:: control:: Cr3 ,
43 structures:: paging:: { PageSize , PageTable , PageTableFlags , PhysFrame , Size2MiB } ,
@@ -8,49 +7,45 @@ use x86_64::{
87// This is the number of GiB we will identity map.
98const ADDRESS_SPACE_GIB : usize = 4 ;
109
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+
24+ let pt_flags = PageTableFlags :: PRESENT | PageTableFlags :: WRITABLE ;
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 ;
2431 }
2532 }
2633
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+ }
4438
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) ;
4741
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 PML4
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 ) } ;
5347 }
48+ log ! ( "Page tables setup" ) ;
5449}
5550
5651// Map a virtual address to a PhysAddr (assumes identity mapping)
0 commit comments