// Copyright (c) 2025 shibedrill // SPDX-License-Identifier: MIT #![allow(dead_code)] use crate::constants::KERNEL_BUILD_PROFILE; use crate::{LOGGER, LogLevel, format, log_info, log_trace, memory::HHDM_RESPONSE}; use free_list::{PAGE_SIZE, PageLayout}; use x86_64::{ PhysAddr, VirtAddr, registers::control::*, structures::paging::{PageTable, PageTableFlags}, }; pub fn switch_ptable() { let allocated_region = crate::memory::FREELIST .lock() .allocate(PageLayout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) .expect("Could not allocate pages for new page table!"); log_info!("Got region for new PML4: 0x{:x}", allocated_region.start()); let pml4_start_vaddr = allocated_region.start() + HHDM_RESPONSE.offset() as usize; let pml4_ptr = pml4_start_vaddr as *mut PageTable; let mut pml4 = unsafe { crate::memory::alloc::boxed::Box::from_raw(pml4_ptr) }; *pml4 = PageTable::new(); log_info!("Initialized page table at 0x{:p}", pml4); } pub fn get_mappings() { log_info!("Paging: {}", Cr0::read().contains(Cr0Flags::PAGING)); log_info!( "Protection: {}", Cr0::read().contains(Cr0Flags::PROTECTED_MODE_ENABLE) ); log_info!( "Physical Address Extensions: {}", x86_64::registers::control::Cr4::read().contains(Cr4Flags::PHYSICAL_ADDRESS_EXTENSION) ); log_info!( "Page Size Extensions: {}", Cr4::read().contains(Cr4Flags::PAGE_SIZE_EXTENSION) ); log_info!( "Paging mode: {}", match crate::memory::PAGING_REQUEST.get_response().unwrap().mode() { limine::paging::Mode::FOUR_LEVEL => "Four-Level", limine::paging::Mode::FIVE_LEVEL => "Five-Level", _ => unreachable!(), } ); log_info!( "Page-Level Write-Through: {}", Cr3::read().1.contains(Cr3Flags::PAGE_LEVEL_WRITETHROUGH) ); log_info!( "Page-Level Cache Disable: {}", Cr3::read().1.contains(Cr3Flags::PAGE_LEVEL_CACHE_DISABLE) ); if KERNEL_BUILD_PROFILE == "debug" { let pml4_phys_addr = Cr3::read_raw().0.start_address(); log_info!("Page Map Level 4 Address: 0x{:x}", pml4_phys_addr.as_u64()); let pml4: &'static mut PageTable = table_from_phys_addr(pml4_phys_addr); iter_table(pml4, 4); } } fn table_from_phys_addr(address: PhysAddr) -> &'static mut PageTable { let virt_addr: VirtAddr = VirtAddr::new(address.as_u64() + HHDM_RESPONSE.offset()); let ptr: *mut PageTable = virt_addr.as_mut_ptr(); unsafe { &mut *ptr } } fn iter_table(table: &'static mut PageTable, level: usize) { if level == 1 { for page_entry in table.iter() { if page_entry.flags().contains(PageTableFlags::PRESENT) { log_trace!( "Page entry: 0x{:x}, flags: {:?}", page_entry.addr(), page_entry.flags() ); } } } else { for table_entry in table.iter() { if table_entry.flags().contains(PageTableFlags::PRESENT) { log_info!( "Table entry: 0x{:x}, flags: {:?}", table_entry.addr(), table_entry.flags() ); iter_table(table_from_phys_addr(table_entry.addr()), level - 1); } } } }