@@ -84,17 +84,29 @@ fn create_page_tables(
84
84
// copy the currently active level 4 page table, because it might be read-only
85
85
log:: trace!( "switching to new level 4 table" ) ;
86
86
let bootloader_page_table = {
87
- let old_frame = x86_64:: registers:: control:: Cr3 :: read ( ) . 0 ;
88
- let old_table: * const PageTable =
89
- ( phys_offset + old_frame. start_address ( ) . as_u64 ( ) ) . as_ptr ( ) ;
87
+ let old_table = {
88
+ let frame = x86_64:: registers:: control:: Cr3 :: read ( ) . 0 ;
89
+ let ptr: * const PageTable = ( phys_offset + frame. start_address ( ) . as_u64 ( ) ) . as_ptr ( ) ;
90
+ unsafe { & * ptr }
91
+ } ;
90
92
let new_frame = frame_allocator
91
93
. allocate_frame ( )
92
94
. expect ( "Failed to allocate frame for new level 4 table" ) ;
93
- let new_table: * mut PageTable =
94
- ( phys_offset + new_frame. start_address ( ) . as_u64 ( ) ) . as_mut_ptr ( ) ;
95
- // copy the table to the new frame
96
- unsafe { core:: ptr:: copy_nonoverlapping ( old_table, new_table, 1 ) } ;
97
- // the tables are now identical, so we can just load the new one
95
+ let new_table: & mut PageTable = {
96
+ let ptr: * mut PageTable =
97
+ ( phys_offset + new_frame. start_address ( ) . as_u64 ( ) ) . as_mut_ptr ( ) ;
98
+ // create a new, empty page table
99
+ unsafe {
100
+ ptr. write ( PageTable :: new ( ) ) ;
101
+ & mut * ptr
102
+ }
103
+ } ;
104
+
105
+ // copy the first entry (we don't need to access more than 512 GiB; also, some UEFI
106
+ // implementations seem to create an level 4 table entry 0 in all slots)
107
+ new_table[ 0 ] = old_table[ 0 ] . clone ( ) ;
108
+
109
+ // the first level 4 table entry is now identical, so we can just load the new one
98
110
unsafe {
99
111
x86_64:: registers:: control:: Cr3 :: write (
100
112
new_frame,
0 commit comments