From fe04effa3d093f0db38533136de99ffb3bafaa4d Mon Sep 17 00:00:00 2001 From: ami-chuu Date: Mon, 30 Mar 2026 16:17:25 +0300 Subject: [PATCH] Added Double Fault Handler --- src/gdt.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++ src/interrupts.rs | 14 +++++++++++++ src/lib.rs | 2 ++ src/main.rs | 2 -- 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/gdt.rs diff --git a/src/gdt.rs b/src/gdt.rs new file mode 100644 index 0000000..05b074d --- /dev/null +++ b/src/gdt.rs @@ -0,0 +1,52 @@ +use lazy_static::lazy_static; +use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector}; +use x86_64::structures::tss::TaskStateSegment; +use x86_64::VirtAddr; + +pub const DOUBLE_FAULT_IST_INDEX: u16 = 0; + +lazy_static! { + static ref TSS: TaskStateSegment = { + let mut tss = TaskStateSegment::new(); + tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = { + const STACK_SIZE: usize = 4096 * 5; + static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; + + let stack_start = VirtAddr::from_ptr(&raw const STACK); + let stack_end = stack_start + STACK_SIZE; + stack_end + }; + tss + }; +} + +lazy_static! { + static ref GDT: (GlobalDescriptorTable, Selectors) = { + let mut gdt = GlobalDescriptorTable::new(); + let code_selector = gdt.add_entry(Descriptor::kernel_code_segment()); + let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS)); + ( + gdt, + Selectors { + code_selector, + tss_selector, + }, + ) + }; +} + +struct Selectors { + code_selector: SegmentSelector, + tss_selector: SegmentSelector, +} + +pub fn init() { + use x86_64::instructions::segmentation::{Segment, CS}; + use x86_64::instructions::tables::load_tss; + + GDT.0.load(); + unsafe { + CS::set_reg(GDT.1.code_selector); + load_tss(GDT.1.tss_selector); + } +} diff --git a/src/interrupts.rs b/src/interrupts.rs index 405c1e9..6f660c7 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -1,3 +1,4 @@ +use crate::gdt; use crate::println; use lazy_static::lazy_static; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; @@ -6,6 +7,12 @@ lazy_static! { static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); + unsafe { + idt.double_fault + .set_handler_fn(double_fault_handler) + .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); + } + idt }; } @@ -18,6 +25,13 @@ extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) { println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); } +extern "x86-interrupt" fn double_fault_handler( + stack_frame: InterruptStackFrame, + _error_code: u64, +) -> ! { + panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); +} + #[test_case] fn test_breakpoint_exception() { // invoke a breakpoint exception diff --git a/src/lib.rs b/src/lib.rs index ae4e3a3..6f6f9c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ use core::panic::PanicInfo; +pub mod gdt; pub mod interrupts; pub mod serial; pub mod vga_buffer; @@ -73,5 +74,6 @@ pub fn exit_qemu(exit_code: QemuExitCode) { } pub fn init() { + gdt::init(); interrupts::init_idt(); } diff --git a/src/main.rs b/src/main.rs index f153785..0b41888 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,8 +13,6 @@ pub extern "C" fn _start() -> ! { amix::init(); - x86_64::instructions::interrupts::int3(); - #[cfg(test)] test_main();