From cd4fb562308b4e3cfa21bb82d453b2b57165c7f4 Mon Sep 17 00:00:00 2001 From: Eemeli Lehtonen <eemeli.o.lehtonen@utu.fi> Date: Mon, 30 Jan 2023 18:08:23 +0200 Subject: [PATCH] page fault handler --- src/arch/x86_64/idt.rs | 25 ++++++++++++++++++----- src/boot/limine/addr.rs | 20 +++++++++++++++++++ src/boot/limine/mem.rs | 2 +- src/boot/limine/mod.rs | 3 +++ src/main.rs | 44 +++++++++++++++++++++++++++++++++++++++++ src/mem/pfa.rs | 5 ++--- src/panic.rs | 2 +- src/testfw.rs | 19 ++++++++++++++---- 8 files changed, 106 insertions(+), 14 deletions(-) create mode 100644 src/boot/limine/addr.rs diff --git a/src/arch/x86_64/idt.rs b/src/arch/x86_64/idt.rs index 41943cd..ba81aa9 100644 --- a/src/arch/x86_64/idt.rs +++ b/src/arch/x86_64/idt.rs @@ -1,6 +1,9 @@ -use crate::{debug, info}; +use crate::{debug, error, info}; use spin::Lazy; -use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; +use x86_64::{ + registers::control::Cr2, + structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode}, +}; // @@ -67,16 +70,28 @@ extern "x86-interrupt" fn double_fault(stack: InterruptStackFrame, ec: u64) -> ! panic!(); } +extern "x86-interrupt" fn page_fault(stack: InterruptStackFrame, ec: PageFaultErrorCode) { + let addr = Cr2::read(); + + error!("INT: Page fault\nAddress: {addr:?}\nErrorCode: {ec:?}\n{stack:#?}"); + + panic!(); +} + // static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| { let mut idt = InterruptDescriptorTable::new(); + idt.breakpoint.set_handler_fn(breakpoint); + + let opt = idt.double_fault.set_handler_fn(double_fault); unsafe { - idt.double_fault - .set_handler_fn(double_fault) - .set_stack_index(DOUBLE_FAULT_IST); + opt.set_stack_index(DOUBLE_FAULT_IST); } + + idt.page_fault.set_handler_fn(page_fault); + idt }); diff --git a/src/boot/limine/addr.rs b/src/boot/limine/addr.rs new file mode 100644 index 0000000..bae296d --- /dev/null +++ b/src/boot/limine/addr.rs @@ -0,0 +1,20 @@ +use limine::{LimineKernelAddressRequest, LimineKernelAddressResponse}; +use spin::Lazy; +use x86_64::{PhysAddr, VirtAddr}; + +// + +pub fn phys_addr() -> PhysAddr { + PhysAddr::new(KERNEL_ADDR.physical_base) +} + +pub fn virt_addr() -> VirtAddr { + VirtAddr::new(KERNEL_ADDR.virtual_base) +} + +// + +static KERNEL_ADDR: Lazy<&'static LimineKernelAddressResponse> = Lazy::new(|| { + static REQ: LimineKernelAddressRequest = LimineKernelAddressRequest::new(0); + REQ.get_response().get().unwrap() +}); diff --git a/src/boot/limine/mem.rs b/src/boot/limine/mem.rs index 40c8350..ab4b1fe 100644 --- a/src/boot/limine/mem.rs +++ b/src/boot/limine/mem.rs @@ -1,4 +1,4 @@ -use crate::{debug, mem::map::Memmap}; +use crate::mem::map::Memmap; use limine::{LimineMemmapEntry, LimineMemmapRequest, LimineMemoryMapEntryType, NonNullPtr}; use spin::Lazy; diff --git a/src/boot/limine/mod.rs b/src/boot/limine/mod.rs index c5657a8..a028899 100644 --- a/src/boot/limine/mod.rs +++ b/src/boot/limine/mod.rs @@ -3,12 +3,15 @@ use crate::{arch, kernel_main}; // +pub use addr::phys_addr; +pub use addr::virt_addr; pub use mem::memmap; pub use mem::memtotal; pub use term::_print; // +mod addr; mod cmdline; mod framebuffer; mod mem; diff --git a/src/main.rs b/src/main.rs index 640553e..7deb831 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,6 +14,12 @@ // +use x86_64::{ + registers::control::Cr3, + structures::paging::{PageTable, PhysFrame}, + VirtAddr, +}; + extern crate alloc; // @@ -50,8 +56,46 @@ fn kernel_main() -> ! { debug!("Entering kernel_main"); debug!("Cmdline: {:?}", env::Arguments::get()); + debug!( + "Kernel addr: {:?} {:?}", + boot::virt_addr(), + boot::phys_addr() + ); + mem::init(); + /* let (l4, _) = Cr3::read(); + + let read_pt = |frame: PhysFrame| -> &mut PageTable { + let addr = VirtAddr::new(frame.start_address().as_u64()); + let table: *mut PageTable = addr.as_mut_ptr(); + unsafe { &mut *table } + }; + + for (i, e) in read_pt(l4).iter().enumerate() { + if !e.is_unused() { + println!("L4 entry {i}: {e:?}"); + + for (i, e) in read_pt(e.frame().unwrap()).iter().enumerate() { + if !e.is_unused() { + println!(" L3 entry {i}: {e:?}"); + + for (i, e) in read_pt(e.frame().unwrap()).iter().enumerate() { + if !e.is_unused() { + println!(" L2 entry {i}: {e:?}"); + + for (i, e) in read_pt(e.frame().unwrap()).iter().enumerate() { + if !e.is_unused() { + println!(" L1 entry {i}: {e:?}"); + } + } + } + } + } + } + } + } */ + // ofc. every kernel has to have this cringy ascii name splash info!("\n{}\n", include_str!("./splash")); diff --git a/src/mem/pfa.rs b/src/mem/pfa.rs index 442644a..b9241c9 100755 --- a/src/mem/pfa.rs +++ b/src/mem/pfa.rs @@ -1,7 +1,6 @@ use super::map::Memmap; use crate::{ boot, debug, - log::{test_log_level, LogLevel}, mem::bump, util::{bitmap::Bitmap, fmt::NumberPostfix}, }; @@ -79,7 +78,7 @@ pub fn init() { #[cfg(debug_assertions)] bitmap.set(page as _, false).unwrap(); #[cfg(not(debug_assertions))] - let _ = bitmap.set(page as _, false); + let res = bitmap.set(page as _, false); } } @@ -109,5 +108,5 @@ pub struct PageFrameAllocator { // impl PageFrameAllocator { - pub fn free_page(&mut self, addr: u64) {} + pub fn free_page(&mut self, _addr: u64) {} } diff --git a/src/panic.rs b/src/panic.rs index d69b799..1b47435 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -6,7 +6,7 @@ use core::panic::PanicInfo; #[cfg(not(feature = "tests"))] #[panic_handler] fn panic_handler(info: &PanicInfo) -> ! { - crate::println!("{info}"); + crate::println!("Kernel {info}"); done(); } diff --git a/src/testfw.rs b/src/testfw.rs index 5c28a89..a317928 100644 --- a/src/testfw.rs +++ b/src/testfw.rs @@ -63,6 +63,8 @@ pub fn test_panic_handler(info: &PanicInfo) { #[cfg(test)] mod tests { + /* use crate::{debug, println}; */ + #[allow(clippy::eq_op)] #[test_case] fn trivial() { @@ -73,10 +75,19 @@ mod tests { #[test_case] fn random_tests() { // error handling test - // stack_overflow(79999999); - // unsafe { - // *(0xFFFFFFFFDEADC0DE as *mut u8) = 42; - // } + + /* stack_overflow(79999999); */ + + /* unsafe { + *(0xFFFFFFFFDEADC0DE as *mut u8) = 42; + } */ + + /* unsafe { + let x = *(0xffffffffc18a8137 as *mut u8); + println!("Read worked: {x}"); + *(0xffffffffc18a8137 as *mut u8) = 42; + println!("Write worked"); + } */ #[allow(unused)] fn stack_overflow(n: usize) { -- GitLab