page table
This commit is contained in:
@@ -3,12 +3,15 @@
|
||||
|
||||
pub mod constant;
|
||||
pub mod logging;
|
||||
pub mod paging;
|
||||
pub mod serial;
|
||||
|
||||
use core::arch::asm;
|
||||
use core::panic::PanicInfo;
|
||||
use core::ptr::addr_of;
|
||||
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
use crate::constant::{BANNER, KERNEL_STACK_SIZE, PKG_VERSION};
|
||||
|
||||
#[repr(C, align(16))]
|
||||
@@ -39,7 +42,8 @@ pub extern "sysv64" fn asm_main() -> ! {
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &PanicInfo) -> ! {
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
println!("{}", info);
|
||||
hlt_loop();
|
||||
}
|
||||
|
||||
@@ -55,5 +59,11 @@ fn hlt_loop() -> ! {
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "sysv64" fn main() {
|
||||
println!("{} v{}", BANNER, PKG_VERSION);
|
||||
|
||||
info!("Page table test:");
|
||||
let virt = VirtAddr::new(0xb8000);
|
||||
let phys = paging::translate_addr(virt);
|
||||
info!(" {:?} -> {:?}", virt, phys);
|
||||
|
||||
hlt_loop();
|
||||
}
|
||||
|
||||
77
nel_os_kernel/src/paging.rs
Normal file
77
nel_os_kernel/src/paging.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use x86_64::{
|
||||
registers::control::Cr3,
|
||||
structures::paging::{page_table::FrameError, PageTable, PhysFrame},
|
||||
PhysAddr, VirtAddr,
|
||||
};
|
||||
|
||||
pub fn get_active_level_4_table() -> &'static mut PageTable {
|
||||
let (level_4_table_frame, _) = Cr3::read();
|
||||
|
||||
frame_to_page_table(level_4_table_frame)
|
||||
}
|
||||
|
||||
pub fn frame_to_page_table(frame: PhysFrame) -> &'static mut PageTable {
|
||||
let page_table_addr = frame.start_address().as_u64();
|
||||
let page_table_ptr: *mut PageTable = VirtAddr::new(page_table_addr).as_mut_ptr();
|
||||
|
||||
unsafe { &mut *page_table_ptr }
|
||||
}
|
||||
|
||||
pub fn translate_addr(addr: VirtAddr) -> Option<PhysAddr> {
|
||||
let (level_4_table_frame, _) = Cr3::read();
|
||||
|
||||
let table_indexes = [
|
||||
addr.p4_index(),
|
||||
addr.p3_index(),
|
||||
addr.p2_index(),
|
||||
addr.p1_index(),
|
||||
];
|
||||
|
||||
let mut frame = level_4_table_frame;
|
||||
|
||||
let table = frame_to_page_table(frame);
|
||||
let entry = &table[table_indexes[0]];
|
||||
frame = match entry.frame() {
|
||||
Ok(frame) => frame,
|
||||
Err(FrameError::FrameNotPresent) => return None,
|
||||
Err(FrameError::HugeFrame) => panic!("1GiB pages at level 4 are not supported"),
|
||||
};
|
||||
|
||||
let table = frame_to_page_table(frame);
|
||||
let entry = &table[table_indexes[1]];
|
||||
match entry.frame() {
|
||||
Ok(frame_4k) => {
|
||||
frame = frame_4k;
|
||||
}
|
||||
Err(FrameError::FrameNotPresent) => return None,
|
||||
Err(FrameError::HugeFrame) => {
|
||||
let huge_frame_addr = entry.addr();
|
||||
let offset_1gib = addr.as_u64() & 0x3FFF_FFFF;
|
||||
return Some(huge_frame_addr + offset_1gib);
|
||||
}
|
||||
};
|
||||
|
||||
let table = frame_to_page_table(frame);
|
||||
let entry = &table[table_indexes[2]];
|
||||
match entry.frame() {
|
||||
Ok(frame_4k) => {
|
||||
frame = frame_4k;
|
||||
}
|
||||
Err(FrameError::FrameNotPresent) => return None,
|
||||
Err(FrameError::HugeFrame) => {
|
||||
let huge_frame_addr = entry.addr();
|
||||
let offset_2mib = addr.as_u64() & 0x1F_FFFF;
|
||||
return Some(huge_frame_addr + offset_2mib);
|
||||
}
|
||||
};
|
||||
|
||||
let table = frame_to_page_table(frame);
|
||||
let entry = &table[table_indexes[3]];
|
||||
frame = match entry.frame() {
|
||||
Ok(frame) => frame,
|
||||
Err(FrameError::FrameNotPresent) => return None,
|
||||
Err(FrameError::HugeFrame) => panic!("Huge pages at level 1 are not supported"),
|
||||
};
|
||||
|
||||
Some(frame.start_address() + u64::from(addr.page_offset()))
|
||||
}
|
||||
Reference in New Issue
Block a user