From c373d23ee0c08a338dfa5dae37886ca7f404e4bc Mon Sep 17 00:00:00 2001 From: juls0730 <62722391+juls0730@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:13:14 -0500 Subject: [PATCH] add limine.conf (oops) and make exceptions more helpful --- limine.conf | 10 +++ src/arch/x86_64/interrupts/exceptions.rs | 94 +++++++++++++++++++----- src/arch/x86_64/mod.rs | 75 +++++++++++++++++++ src/arch/x86_64/stack_trace.rs | 41 +++++++---- src/main.rs | 4 + 5 files changed, 191 insertions(+), 33 deletions(-) create mode 100644 limine.conf diff --git a/limine.conf b/limine.conf new file mode 100644 index 0000000..3825a14 --- /dev/null +++ b/limine.conf @@ -0,0 +1,10 @@ +# Timeout in seconds that Limine will use before automatically booting. +timeout: 3 + +/CappuccinOS + protocol: limine + + kernel_path: boot():/boot/CappuccinOS.elf + cmdline: fat_in_mem=false big_fat_phony + + module_path: boot():/boot/initramfs.img diff --git a/src/arch/x86_64/interrupts/exceptions.rs b/src/arch/x86_64/interrupts/exceptions.rs index 6398e60..9c3f4d2 100644 --- a/src/arch/x86_64/interrupts/exceptions.rs +++ b/src/arch/x86_64/interrupts/exceptions.rs @@ -1,3 +1,5 @@ +use core::sync::atomic::{AtomicU8, Ordering}; + use super::idt_set_gate; use crate::hcf; use crate::{log_error, log_info}; @@ -33,46 +35,97 @@ struct Registers { ss: usize, } +static FAULTED: AtomicU8 = AtomicU8::new(0); + extern "C" fn exception_handler(registers: u64) { let registers = unsafe { *(registers as *const Registers) }; - // crate::println!("{:X?}", registers); + match FAULTED.fetch_add(1, Ordering::SeqCst) { + 0 => {} + 1 => { + log_error!("Exception Loop detected, stopping here"); + print_registers(®isters); + hcf(); + } + // We have faulted multiple times, this could indicate an issue with the allocator, stop everything without further logging since it will likely cause more issues + _ => hcf(), + } let int = registers.int; match int { 0x00 => { - crate::drivers::serial::write_string("DIVISION ERROR!"); + log_error!("DIVISION ERROR!"); } 0x06 => { - crate::drivers::serial::write_string("INVALID OPCODE!"); + log_error!("INVALID OPCODE!"); } 0x08 => { - crate::drivers::serial::write_string("DOUBLE FAULT!"); + log_error!("DOUBLE FAULT!"); } 0x0D => { - crate::drivers::serial::write_string("GENERAL PROTECTION FAULT!"); + log_error!("GENERAL PROTECTION FAULT!"); } 0x0E => { - crate::drivers::serial::write_string("PAGE FAULT!"); + log_error!("PAGE FAULT!"); } 0xFF => { - crate::drivers::serial::write_string("EXCEPTION!"); + log_error!("EXCEPTION!"); } _ => { - crate::drivers::serial::write_string("EXCEPTION!"); + log_error!("EXCEPTION!"); } } - // log_info!( - // "INT: {:x} RIP: {:X}, CS: {:X}, EFLAGS: {:b}", - // int, - // registers.rip, - // registers.cs, - // registers.rflags - // ); + print_registers(®isters); - // crate::arch::stack_trace::print_stack_trace(6, registers.rbp as u64); + crate::arch::stack_trace::print_stack_trace(6, registers.rbp as u64); +} + +fn print_registers(registers: &Registers) { + log_info!("{:-^width$}", " REGISTERS ", width = 98); + + log_info!( + "INT: {:#018X}, RIP: {:#018X}, CS: {:#018X}, FLG: {:#018X}", + registers.int, + registers.rip, + registers.cs, + registers.rflags + ); + + log_info!( + "RSP: {:#018X}, SS: {:#018X}, RAX: {:#018X}, RBX: {:#018X}", + registers.rsp, + registers.ss, + registers.rax, + registers.rbx + ); + + log_info!( + "RCX: {:#018X}, RDX: {:#018X}, RSI: {:#018X}, RDI: {:#018X}", + registers.rcx, + registers.rdx, + registers.rsi, + registers.rdi + ); + + log_info!( + "RBP: {:#018X}, R8: {:#018X}, R9: {:#018X}, R10: {:#018X}", + registers.rbp, + registers.r8, + registers.r9, + registers.r10 + ); + + log_info!( + "R11: {:#018X}, R12: {:#018X}, R13: {:#018X}, R14: {:#018X}", + registers.r11, + registers.r12, + registers.r13, + registers.r14 + ); + + log_info!("R15: {:#018X}", registers.r15); } // *macro intensifies* @@ -80,20 +133,25 @@ macro_rules! exception_function { ($code:expr, $handler:ident) => { #[inline(always)] extern "C" fn $handler() { + crate::arch::push_gprs(); + unsafe { core::arch::asm!( - "pushfq", "push {0:r}", "mov rdi, rsp", "call {1}", "pop {0:r}", "mov rsp, rdi", - "popfq", in(reg) $code, sym exception_handler, + options(nostack) ); }; + crate::arch::pop_gprs(); + + super::signal_end_of_interrupt(); + hcf(); } }; diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index c60039c..1799afd 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -34,3 +34,78 @@ pub unsafe fn cpu_set_msr(msr: u32, lo: &u32, hi: &u32) { in("edx") *hi, ); } + +// struct Registers { +// // Pushed by wrapper +// int: usize, + +// // Pushed by push_gprs in crate::arch::x86_64 +// r15: usize, +// r14: usize, +// r13: usize, +// r12: usize, +// r11: usize, +// r10: usize, +// r9: usize, +// r8: usize, +// rbp: usize, +// rdi: usize, +// rsi: usize, +// rdx: usize, +// rcx: usize, +// rbx: usize, +// rax: usize, + +// // Pushed by interrupt +// rip: usize, +// cs: usize, +// rflags: usize, +// rsp: usize, +// ss: usize, +// } + +pub fn push_gprs() { + unsafe { + core::arch::asm!( + "push rax", + "push rbx", + "push rcx", + "push rdx", + "push rsi", + "push rdi", + "push rbp", + "push r8", + "push r9", + "push r10", + "push r11", + "push r12", + "push r13", + "push r14", + "push r15", + options(nostack) + ) + } +} + +pub fn pop_gprs() { + unsafe { + core::arch::asm!( + "pop r15", + "pop r14", + "pop r13", + "pop r12", + "pop r11", + "pop r10", + "pop r9", + "pop r8", + "pop rbp", + "pop rdi", + "pop rsi", + "pop rdx", + "pop rcx", + "pop rbx", + "pop rax", + options(nostack) + ) + } +} diff --git a/src/arch/x86_64/stack_trace.rs b/src/arch/x86_64/stack_trace.rs index c21a2a1..f822fca 100644 --- a/src/arch/x86_64/stack_trace.rs +++ b/src/arch/x86_64/stack_trace.rs @@ -1,6 +1,10 @@ use alloc::{borrow::ToOwned, string::String, vec::Vec}; -use crate::drivers::fs::vfs::{vfs_open, UserCred}; +use crate::{ + drivers::fs::vfs::{vfs_open, UserCred}, + log_info, + mem::HHDM_OFFSET, +}; // use crate::drivers::fs::vfs::VfsFileSystem; @@ -8,41 +12,48 @@ use crate::drivers::fs::vfs::{vfs_open, UserCred}; #[derive(Clone, Copy, Debug)] struct StackFrame { back: *const StackFrame, - rip: u64, + rip: usize, } pub fn print_stack_trace(max_frames: usize, rbp: u64) { let mut stackframe = rbp as *const StackFrame; + let mut frames_processed = 0; - crate::println!("Stack Trace:"); - for _frame in 0..max_frames { - if stackframe.is_null() || unsafe { core::ptr::read_unaligned(stackframe).back.is_null() } { + log_info!("{:-^width$}", " Stack Trace ", width = 98); + for _ in 0..max_frames { + frames_processed += 1; + + if stackframe.is_null() { break; } - let instruction_pointer = unsafe { (*stackframe).rip }; + let instruction_ptr = unsafe { (*stackframe).rip }; - if instruction_pointer == 0x0 { + if instruction_ptr < *HHDM_OFFSET { unsafe { stackframe = (*stackframe).back; }; continue; } - crate::print!(" {:#X} ", instruction_pointer); + let instruction_info = get_function_name(instruction_ptr as u64); - let instrcution_info = get_function_name(instruction_pointer); - - if let Ok((function_name, function_offset)) = instrcution_info { - crate::println!("<{}+{:#X}>", function_name, function_offset); + let address_info = if let Ok((function_name, function_offset)) = instruction_info { + &alloc::format!("<{}+{:#X}>", function_name, function_offset) } else { - crate::println!(); - } + "" + }; + + log_info!("{:#X} {address_info}", instruction_ptr); unsafe { stackframe = (*stackframe).back; }; } + + if frames_processed == max_frames && !stackframe.is_null() { + log_info!("... "); + } } fn get_function_name(function_address: u64) -> Result<(String, u64), ()> { @@ -97,5 +108,5 @@ fn get_function_name(function_address: u64) -> Result<(String, u64), ()> { previous_symbol = Some((function_name, address)); } - unreachable!(); + return Err(()); } diff --git a/src/main.rs b/src/main.rs index 8020b4d..6dc28a6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -102,6 +102,10 @@ pub fn kmain() -> ! { .read(0, 0, 0) ); + unsafe { + *(0xDEADBEEF as *mut u32) = 0xBAADF00D; + }; + // let file = vfs_open("/example.txt").unwrap(); // as a sign that we didnt panic