diff --git a/src/kernel/arch/x86_64/interrupts.rs b/src/kernel/arch/x86_64/interrupts.rs index 070f59f..149120f 100644 --- a/src/kernel/arch/x86_64/interrupts.rs +++ b/src/kernel/arch/x86_64/interrupts.rs @@ -3,31 +3,42 @@ use lazy_static::lazy_static; use x86_64::structures::idt::*; +use crate::format; lazy_static! { pub static ref IDT: InterruptDescriptorTable = { - InterruptDescriptorTable::new() + let mut idt = InterruptDescriptorTable::new(); // TODO: Re-implement this once the x86-interrupt ABI is fixed. // Alternatively: Write our own interrupt handler wrappers. + idt.double_fault.set_handler_fn(double_fault); + idt.page_fault.set_handler_fn(page_fault); + idt }; } -// For all these handlers, they will be called from a purely naked ASM -// function. That function will first push all registers to the stack. -// It is the responsibility of these functions to recover this info. +extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! { + crate::interrupt::double_fault(format!("{info:#?}")); +} -// Recoverable exception: Occurs on division failure. -#[unsafe(no_mangle)] -pub extern "C" fn x86_divide_error() {} - -// Recoverable exception: Occurs on failure in BOUND instruction. -#[unsafe(no_mangle)] -pub extern "C" fn x86_bound_range() {} - -// Recoverable exception: Invalid opcode. -#[unsafe(no_mangle)] -pub extern "C" fn x86_invalid_opcode() {} - -// Recoverable exception: FPU not available or enabled. -#[unsafe(no_mangle)] -pub extern "C" fn x86_device_unavailable() {} +#[allow(dead_code)] +extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFaultErrorCode) { + if errcode.contains(PageFaultErrorCode::USER_MODE) { + // Fault occurred in usermode. Non fatal. + todo!() + } else { + // Fault occurred in kernel mode. This is possibly fatal. + // This is recoverable if we simply hit an unavailable page, + // but unrecoverable if we hit a nonexistent or invalid page. + if errcode.contains(PageFaultErrorCode::PROTECTION_VIOLATION) + | errcode.contains(PageFaultErrorCode::MALFORMED_TABLE) + { + let addr = unsafe { + let a: usize; + core::arch::asm! {"mov {}, cr2", out(reg) a}; + a + }; + let info_formatted = format!("{info:#?}"); + crate::interrupt::page_fault(addr, info_formatted) + } + } +} diff --git a/src/kernel/interrupt/mod.rs b/src/kernel/interrupt/mod.rs index 4a632fe..52fda8b 100644 --- a/src/kernel/interrupt/mod.rs +++ b/src/kernel/interrupt/mod.rs @@ -1,16 +1,12 @@ // Copyright (c) 2025 shibedrill // SPDX-License-Identifier: GPL-3.0-or-later -use core::str; +use crate::memory::alloc::string::String; -#[unsafe(no_mangle)] -extern "C" fn double_fault(info: *const u8, info_len: usize) -> ! { - let info_slice = unsafe { &str::from_raw_parts(info, info_len) }; - panic!("Double fault: {}", info_slice); +pub fn double_fault(info: String) -> ! { + panic!("Double fault: {}", info); } -#[unsafe(no_mangle)] -pub extern "C" fn page_fault(addr: usize, info: *const u8, info_len: usize) -> ! { - let info_slice = unsafe { &str::from_raw_parts(info, info_len) }; - panic!("Page fault at 0x{:X}: {}", addr, info_slice); +pub fn page_fault(addr: usize, info: String) -> ! { + panic!("Page fault at 0x{:X}: {}", addr, info); } diff --git a/src/kernel/main.rs b/src/kernel/main.rs index d952e4a..bf26fc9 100644 --- a/src/kernel/main.rs +++ b/src/kernel/main.rs @@ -5,6 +5,7 @@ #![no_main] #![feature(allocator_api)] #![feature(str_from_raw_parts)] +#![feature(abi_x86_interrupt)] mod arch; mod boot;