Skip to content

Commit 14c4e62

Browse files
committed
Only copy first level 4 entry to bootloader page table
1 parent ec33e72 commit 14c4e62

File tree

1 file changed

+20
-8
lines changed

1 file changed

+20
-8
lines changed

src/bin/uefi.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,29 @@ fn create_page_tables(
8484
// copy the currently active level 4 page table, because it might be read-only
8585
log::trace!("switching to new level 4 table");
8686
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+
};
9092
let new_frame = frame_allocator
9193
.allocate_frame()
9294
.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
98110
unsafe {
99111
x86_64::registers::control::Cr3::write(
100112
new_frame,

0 commit comments

Comments
 (0)