diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index 160cf20..cffb882 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,7 +1,8 @@ use lib_ascii::println_log; use lib_serial::serial_println; use x86_64::instructions::port::Port; -use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; +use x86_64::registers::control::Cr2; +use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode}; use pic8259::ChainedPics; use spin::{Lazy, Mutex}; @@ -12,6 +13,7 @@ static IDT: Lazy = Lazy::new(|| { idt.double_fault.set_handler_fn(double_fault_handler); idt.general_protection_fault .set_handler_fn(general_protection_fault_handler); + idt.page_fault.set_handler_fn(page_fault_handler); idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler); idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler); @@ -85,3 +87,15 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFr .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); } } + +extern "x86-interrupt" fn page_fault_handler( + stack_frame: InterruptStackFrame, + error_code: PageFaultErrorCode, +) { + serial_println!("Exception: Page Fault"); + serial_println!("Accessed Address: {:?}", Cr2::read()); + serial_println!("Error Code: {:?}", error_code); + serial_println!("{:#?}", stack_frame); + + crate::hcf(); +} diff --git a/kernel/src/arch/x86_64/memmap.rs b/kernel/src/arch/x86_64/memmap.rs new file mode 100644 index 0000000..1b0cbbb --- /dev/null +++ b/kernel/src/arch/x86_64/memmap.rs @@ -0,0 +1,56 @@ +//! Sets up a memory map using Limine. + +use limine::{ + request::{HhdmRequest, KernelAddressRequest, MemoryMapRequest}, + response::MemoryMapResponse, +}; +use spin::Lazy; + +#[used] +#[link_section = ".requests"] +static MEMORY_MAP_REQUEST: MemoryMapRequest = MemoryMapRequest::new(); + +#[used] +#[link_section = ".requests"] +static HIGHER_HALF_DIRECT_MAP_REQUEST: HhdmRequest = HhdmRequest::new(); + +/// ```rs +/// let virt_addr = phys_addr + offset; +/// let phys_addr = virt_addr - offset; // (given VA is in the HHDM). Do not use for executable code. +/// ``` +pub static PHYSICAL_MEMORY_OFFSET: Lazy = Lazy::new(|| { + HIGHER_HALF_DIRECT_MAP_REQUEST + .get_response() + .unwrap() + .offset() +}); + +#[used] +#[link_section = ".requests"] +static KERNEL_ADDRESS_REQUEST: KernelAddressRequest = KernelAddressRequest::new(); + +/// Converts virtual addresses in the kernel to a physical address like this: +/// ```rs +/// let phys_addr = virt_addr - virtual_base + physical_base; +/// ``` +/// +/// Returns (virtual_base, physical_base) +pub static KERNEL_PHYSICAL_MEMORY_OFFSET: Lazy<(u64, u64)> = Lazy::new(|| { + let resp = KERNEL_ADDRESS_REQUEST.get_response().unwrap(); + + // These are base addresses, using Limine's built in page table. + (resp.virtual_base(), resp.physical_base()) +}); + +/// Fetches the memory map from Limine. +/// +/// # Panics +/// +/// Panics if the memory map was not found in MEMORY_MAP_REQUEST. +pub fn get_memory_map() -> &'static MemoryMapResponse { + if let Some(memory_map) = MEMORY_MAP_REQUEST.get_response() { + return memory_map; + } else { + unreachable!("Could not fetch memory map from Limine.") + } +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index c36854e..e667a18 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #![feature(abi_x86_interrupt)] -use arch::x86_64::interrupts; use core::arch::asm; use limine::request::{RequestsEndMarker, RequestsStartMarker}; use limine::BaseRevision; @@ -11,8 +10,6 @@ pub use lib_serial::{serial_print, serial_println, serial_read}; mod arch; -use lib_framebuffer; - /// Sets the base revision to the latest revision supported by the crate. /// See specification for further info. /// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.