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