ktest 0.1.6

A custom test framework for Rust-based operating system kernels
Documentation
use conquer_once::spin::OnceCell;
use spin::Mutex;
use x86_64::{structures::paging::{OffsetPageTable, PageTable}, VirtAddr};

static KERNEL_PAGE_TABLE: OnceCell<Mutex<OffsetPageTable<'static>>> = OnceCell::uninit();

pub fn get_kernel_page_table(physical_memory_offset: Option<u64>) -> &'static Mutex<OffsetPageTable<'static>> {
    KERNEL_PAGE_TABLE.get_or_init(|| Mutex::new(init_kernel_page_table(physical_memory_offset)))
}

fn init_kernel_page_table(physical_memory_offset: Option<u64>) -> OffsetPageTable<'static> {
    let physical_memory_offset = VirtAddr::new(physical_memory_offset
        .expect("BootInfo is missing physical_memory_offset"));

    unsafe {
        let level_4_table = find_level_4_table_from_bootloader(physical_memory_offset);
        OffsetPageTable::new(level_4_table, physical_memory_offset)
    }
}

fn find_level_4_table_from_bootloader(physical_memory_offset: VirtAddr) -> &'static mut PageTable {
    use x86_64::registers::control::Cr3;

    let (level_4_table_frame, _) = Cr3::read();

    let phys = level_4_table_frame.start_address();
    let virt = physical_memory_offset + phys.as_u64();
    let page_table_ptr: *mut PageTable = virt.as_mut_ptr();

    unsafe { &mut *page_table_ptr }
}