|
| 1 | +use core::panic; |
| 2 | + |
| 3 | +use x86_64::{PhysAddr, VirtAddr, structures::paging::PageTable}; |
| 4 | + |
| 5 | +pub unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable { |
| 6 | + use x86_64::registers::control::Cr3; |
| 7 | + |
| 8 | + let (level_4_table_frame, _) = Cr3::read(); |
| 9 | + |
| 10 | + let phys = level_4_table_frame.start_address(); |
| 11 | + let virt = physical_memory_offset + phys.as_u64(); |
| 12 | + let page_table_ptr: *mut PageTable = virt.as_mut_ptr(); |
| 13 | + |
| 14 | + unsafe { &mut *page_table_ptr } |
| 15 | +} |
| 16 | + |
| 17 | +pub unsafe fn translate_addr(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option<PhysAddr> { |
| 18 | + translate_addr_inner(addr, physical_memory_offset); |
| 19 | +} |
| 20 | + |
| 21 | +fn translate_addr_inner(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option<PhysAddr> { |
| 22 | + use x86_64::registers::control::Cr3; |
| 23 | + use x86_64::structures::paging::page_table::FrameError; |
| 24 | + |
| 25 | + let (level_4_table_frame, _) = Cr3::read(); |
| 26 | + |
| 27 | + let table_indexes = [ |
| 28 | + addr.p4_index(), |
| 29 | + addr.p3_index(), |
| 30 | + addr.p2_index(), |
| 31 | + addr.p1_index(), |
| 32 | + ]; |
| 33 | + let mut frame = level_4_table_frame; |
| 34 | + |
| 35 | + for &index in &table_indexes { |
| 36 | + let virt = physical_memory_offset + frame.start_address().as_u64(); |
| 37 | + let table_ptr: *const PageTable = virt.as_ptr(); |
| 38 | + let table = unsafe { &*table_ptr }; |
| 39 | + |
| 40 | + let entry = &table[index]; |
| 41 | + |
| 42 | + frame = match entry.frame() { |
| 43 | + Ok(frame) => frame, |
| 44 | + Err(FrameError::FrameNotPresent) => return None, |
| 45 | + Err(FrameError::HugeFrame) => panic!("Huge frames not supported"), |
| 46 | + }; |
| 47 | + } |
| 48 | + |
| 49 | + Some(frame.start_address() + u64::from(addr.page_offset())) |
| 50 | +} |
0 commit comments