1
- use atomic_refcell:: AtomicRefCell ;
2
1
use x86_64:: {
3
2
registers:: control:: Cr3 ,
4
3
structures:: paging:: { PageSize , PageTable , PageTableFlags , PhysFrame , Size2MiB } ,
@@ -8,49 +7,45 @@ use x86_64::{
8
7
// This is the number of GiB we will identity map.
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
+
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 ;
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 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 ) } ;
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