From f9fd19b6d0dba4a3c74addbbefe98018fc1768fb Mon Sep 17 00:00:00 2001 From: August Date: Sun, 5 Jul 2026 15:01:51 +0000 Subject: [PATCH] fixing GPFs --- src/kernel/arch/x86_64/gdt.rs | 3 +-- src/kernel/arch/x86_64/interrupts.rs | 15 +++++++++------ src/kernel/arch/x86_64/startup.rs | 6 +++++- src/kernel/interrupt/mod.rs | 4 ++-- src/kernel/main.rs | 1 + 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/kernel/arch/x86_64/gdt.rs b/src/kernel/arch/x86_64/gdt.rs index e34aa31..6e997df 100644 --- a/src/kernel/arch/x86_64/gdt.rs +++ b/src/kernel/arch/x86_64/gdt.rs @@ -54,7 +54,6 @@ pub struct Selectors { pub sel_kernel_stack: SegmentSelector, pub sel_user_code: SegmentSelector, pub sel_user_stack: SegmentSelector, - #[allow(unused)] pub sel_tss: SegmentSelector, pub gdt: GlobalDescriptorTable<48>, } @@ -79,7 +78,7 @@ lazy_static! { // DO NOT REORDER let sel_tss = gdt.append( Descriptor::tss_segment(&TSS).set_flags(DescriptorFlags::from_bits_retain(0b1010)) - //.set_access(0b10001011), // This would set the TSS to Busy, but it causes a GPF. + .set_access(0b10001011), // This would set the TSS to Busy, but it causes a GPF. ); Selectors { sel_kernel_code: sel_k_cs, diff --git a/src/kernel/arch/x86_64/interrupts.rs b/src/kernel/arch/x86_64/interrupts.rs index 8ca8b9c..e7bfd87 100644 --- a/src/kernel/arch/x86_64/interrupts.rs +++ b/src/kernel/arch/x86_64/interrupts.rs @@ -23,9 +23,9 @@ lazy_static! { // code. The x86_interrupt ABI is always breaking, and this // approach will fall apart once multiarch support is re-added. unsafe { - idt.double_fault.set_handler_fn(double_fault).set_code_selector(SELECTORS.sel_kernel_code).set_privilege_level(x86_64::PrivilegeLevel::Ring0); - idt.page_fault.set_handler_fn(page_fault).set_code_selector(SELECTORS.sel_kernel_code).set_privilege_level(x86_64::PrivilegeLevel::Ring0); - idt.general_protection_fault.set_handler_fn(gen_prot_fault).set_code_selector(SELECTORS.sel_kernel_code).set_privilege_level(x86_64::PrivilegeLevel::Ring0); + idt.double_fault.set_handler_fn(double_fault).set_code_selector(SELECTORS.sel_kernel_code); + idt.page_fault.set_handler_fn(page_fault).set_code_selector(SELECTORS.sel_kernel_code); + idt.general_protection_fault.set_handler_fn(gen_prot_fault).set_code_selector(SELECTORS.sel_kernel_code); } idt }; @@ -35,6 +35,7 @@ lazy_static! { #[allow(dead_code)] extern "x86-interrupt" fn double_fault(info: InterruptStackFrame, _: u64) -> ! { crate::interrupt::double_fault(format!("{info:#?}")); + unsafe { info.iretq() } } #[allow(dead_code)] @@ -68,11 +69,13 @@ extern "x86-interrupt" fn page_fault(info: InterruptStackFrame, errcode: PageFau } #[allow(dead_code)] -extern "x86-interrupt" fn gen_prot_fault(info: InterruptStackFrame, _: u64) { +extern "x86-interrupt" fn gen_prot_fault(info: InterruptStackFrame, error: u64) { crate::interrupt::gen_prot_fault(format!( - "RIP 0x{:x}, CS {} ({:?})", + "RIP 0x{:x}, CS {} ({:?}), error: 0x{:x}", info.instruction_pointer, info.code_segment.index(), - info.code_segment.rpl() + info.code_segment.rpl(), + error )); + unsafe { info.iretq() } } diff --git a/src/kernel/arch/x86_64/startup.rs b/src/kernel/arch/x86_64/startup.rs index c5ee808..5fb080c 100644 --- a/src/kernel/arch/x86_64/startup.rs +++ b/src/kernel/arch/x86_64/startup.rs @@ -3,7 +3,10 @@ use x86_64::{VirtAddr, registers::rflags::RFlags, structures::idt::InterruptStac use crate::{ arch::{ asm::ltr, - x86_64::{gdt::SELECTORS, interrupts::IDT}, + x86_64::{ + gdt::{SELECTORS, dump_gdt}, + interrupts::IDT, + }, }, log::{LOGGER, LogLevel}, log_info, @@ -24,6 +27,7 @@ pub fn init() -> Result<(), ()> { SELECTORS.sel_kernel_stack, ) .expect("Segment order in GDT is bad"); + dump_gdt(); ltr(SELECTORS.sel_tss.index()); Ok(()) } diff --git a/src/kernel/interrupt/mod.rs b/src/kernel/interrupt/mod.rs index 7581a18..e69f982 100644 --- a/src/kernel/interrupt/mod.rs +++ b/src/kernel/interrupt/mod.rs @@ -4,8 +4,8 @@ use crate::log::*; use crate::{format, log_error, memory::alloc::string::String}; -pub fn double_fault(info: String) -> ! { - panic!("Double fault: {}", info); +pub fn double_fault(info: String) { + log_error!("Double fault: {}", info); } pub fn page_fault_fatal(addr: usize, info: String) -> ! { diff --git a/src/kernel/main.rs b/src/kernel/main.rs index cca2b6e..a36b0d4 100644 --- a/src/kernel/main.rs +++ b/src/kernel/main.rs @@ -177,6 +177,7 @@ unsafe extern "C" fn main() -> ! { { let ub = modules_list.modules()[0]; log_info!("Found userboot: {} {}", ub.path(), ub.cmdline()); + // TODO: remap userboot as user pages let start_addr = VirtAddr::from_ptr(ub.data() as *const [u8]); arch::startup::jump_to_usermode(VirtAddr::new(0xfffffff800000000), start_addr)