From 582c789632b0630fc184d7713e7202a241443a63 Mon Sep 17 00:00:00 2001 From: ParrotXray Date: Mon, 12 May 2025 20:33:45 +0800 Subject: [PATCH] feat: Handling interrupts --- src/arch/x86/boot.S | 4 +- src/kernel/asm/x86/gdt.rs | 17 --- src/kernel/asm/x86/idt.rs | 74 +++++++----- src/kernel/asm/x86/interrupt.rs | 204 ++++++++++++++++++++++++++++++-- src/kernel/asm/x86/mod.rs | 3 +- src/kernel/asm/x86/segment.rs | 19 +++ src/kernel/kernel.rs | 16 +-- 7 files changed, 269 insertions(+), 68 deletions(-) create mode 100644 src/kernel/asm/x86/segment.rs diff --git a/src/arch/x86/boot.S b/src/arch/x86/boot.S index 7f8cbd7..53e6074 100644 --- a/src/arch/x86/boot.S +++ b/src/arch/x86/boot.S @@ -42,7 +42,7 @@ call _load_idt /* processing register (CS, ES, SS, DS, FS, GS) */ - movw $0x10, %cx /* 0x10 in binary representation is 0001 0000. If you right-shift this number by 3 bits, you will get 0000 0010, so the index is 2. */ + movw KERNEL_DATA_SEL, %cx /* 0x10 in binary representation is 0001 0000. If you right-shift this number by 3 bits, you will get 0000 0010, so the index is 2. */ movw %cx, %es movw %cx, %ds movw %cx, %fs @@ -50,7 +50,7 @@ movw %cx, %ss /* Change CS:IP */ - pushw $0x08 /* 0x08 in binary representation is 0000 1000. If you right-shift this number by 3 bits, you will get 0000 0001, so the index is 1. */ + pushw KERNEL_CODE_SEL /* 0x08 in binary representation is 0000 1000. If you right-shift this number by 3 bits, you will get 0000 0001, so the index is 1. */ pushl $_after_gdt retf diff --git a/src/kernel/asm/x86/gdt.rs b/src/kernel/asm/x86/gdt.rs index 3c9a286..9faddd1 100644 --- a/src/kernel/asm/x86/gdt.rs +++ b/src/kernel/asm/x86/gdt.rs @@ -39,23 +39,6 @@ pub const SEG_CODE_EXRDC: u64 = 0x0E; // Execute/Read, conforming #[allow(dead_code)] pub const SEG_CODE_EXRDCA: u64 = 0x0F; // Execute/Read, conforming, accessed -pub const NULL_SELECTOR: SegmentSelector = SegmentSelector::new(0, Ring::Ring0); -pub const KERNEL_CODE_SELECTOR: SegmentSelector = SegmentSelector::new(1, Ring::Ring0); -pub const KERNEL_DATA_SELECTOR: SegmentSelector = SegmentSelector::new(2, Ring::Ring0); -pub const USER_CODE_SELECTOR: SegmentSelector = SegmentSelector::new(3, Ring::Ring3); -pub const USER_DATA_SELECTOR: SegmentSelector = SegmentSelector::new(4, Ring::Ring3); - -#[no_mangle] -pub static NULL_SEL: u16 = NULL_SELECTOR.bits(); -#[no_mangle] -pub static KERNEL_CODE_SEL: u16 = KERNEL_CODE_SELECTOR.bits(); -#[no_mangle] -pub static KERNEL_DATA_SEL: u16 = KERNEL_DATA_SELECTOR.bits(); -#[no_mangle] -pub static USER_CODE_SEL: u16 = USER_CODE_SELECTOR.bits(); -#[no_mangle] -pub static USER_DATA_SEL: u16 = USER_DATA_SELECTOR.bits(); - pub const GDT_ENTRY_COUNT: usize = 5; #[no_mangle] diff --git a/src/kernel/asm/x86/idt.rs b/src/kernel/asm/x86/idt.rs index a3dea68..ee07915 100644 --- a/src/kernel/asm/x86/idt.rs +++ b/src/kernel/asm/x86/idt.rs @@ -14,7 +14,7 @@ use x86::Ring; use x86::irq::{self, EXCEPTIONS}; use x86::segmentation::GateDescriptorBuilder; use x86::segmentation::TaskGateDescriptorBuilder; -use crate::kernel::asm::x86::interrupt; +use crate::kernel::asm::x86::{interrupt, segment}; pub const IDT_ENTRY_COUNT: usize = 256; @@ -24,17 +24,15 @@ pub static mut _IDT: [Descriptor; IDT_ENTRY_COUNT] = [Descriptor::NULL; IDT_ENTR #[no_mangle] pub static mut _IDT_LIMIT: u16 = (mem::size_of::<[Descriptor; IDT_ENTRY_COUNT]>() - 1) as u16; -pub const KERNEL_CS: SegmentSelector = SegmentSelector::new(1, Ring::Ring0); - -pub type InterruptHandler = extern "C" fn() -> (); -pub type ExceptionHandlerWithErrorCode = extern "C" fn(error_code: u32) -> (); +pub type InterruptHandler = fn() -> (); +pub type ExceptionHandlerWithErrorCode = fn(error_code: u32) -> (); #[no_mangle] -pub fn _set_interrupt_handler(vector: u8, handler: InterruptHandler) { +pub fn _set_interrupt_handler(vector: u8, selector: SegmentSelector, handler: InterruptHandler, dpl: Ring) { unsafe { - let desc = DescriptorBuilder::interrupt_descriptor(KERNEL_CS, handler as u32) + let desc = DescriptorBuilder::interrupt_descriptor(selector, handler as u32) .present() - .dpl(Ring::Ring0) + .dpl(dpl) .finish(); _IDT[vector as usize] = desc; @@ -42,11 +40,11 @@ pub fn _set_interrupt_handler(vector: u8, handler: InterruptHandler) { } #[no_mangle] -pub fn _set_trap_handler(vector: u8, handler: InterruptHandler) { +pub fn _set_interrupt_err_handler(vector: u8, selector: SegmentSelector, handler: ExceptionHandlerWithErrorCode, dpl: Ring) { unsafe { - let desc = DescriptorBuilder::trap_gate_descriptor(KERNEL_CS, handler as u32) + let desc = DescriptorBuilder::interrupt_descriptor(selector, handler as u32) .present() - .dpl(Ring::Ring0) + .dpl(dpl) .finish(); _IDT[vector as usize] = desc; @@ -54,11 +52,23 @@ pub fn _set_trap_handler(vector: u8, handler: InterruptHandler) { } #[no_mangle] -pub fn _set_task_gate(vector: u8, tss_selector: SegmentSelector) { +pub fn _set_trap_handler(vector: u8, selector: SegmentSelector, handler: InterruptHandler, dpl: Ring) { + unsafe { + let desc = DescriptorBuilder::trap_gate_descriptor(selector, handler as u32) + .present() + .dpl(dpl) + .finish(); + + _IDT[vector as usize] = desc; + } +} + +#[no_mangle] +pub fn _set_task_gate(vector: u8, tss_selector: SegmentSelector, dpl: Ring) { unsafe { let desc = DescriptorBuilder::task_gate_descriptor(tss_selector) .present() - .dpl(Ring::Ring0) + .dpl(dpl) .finish(); _IDT[vector as usize] = desc; @@ -91,24 +101,30 @@ pub fn _load_idt() { #[no_mangle] pub fn _setup_idt() { - _set_interrupt_handler(irq::DIVIDE_ERROR_VECTOR, interrupt::divide_error_handler); - _set_interrupt_handler(irq::DEBUG_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::NONMASKABLE_INTERRUPT_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::BREAKPOINT_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::OVERFLOW_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::BOUND_RANGE_EXCEEDED_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::INVALID_OPCODE_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::DEVICE_NOT_AVAILABLE_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::DOUBLE_FAULT_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::COPROCESSOR_SEGMENT_OVERRUN_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::INVALID_TSS_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::SEGMENT_NOT_PRESENT_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::STACK_SEGEMENT_FAULT_VECTOR, interrupt::default_interrupt_handler); - _set_interrupt_handler(irq::GENERAL_PROTECTION_FAULT_VECTOR, interrupt::general_protection_handler); - _set_interrupt_handler(irq::PAGE_FAULT_VECTOR, interrupt::page_fault_handler); + _set_interrupt_err_handler(irq::DIVIDE_ERROR_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::divide_error_handler, Ring::Ring0); + _set_interrupt_handler(irq::DEBUG_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::debug_error_handler, Ring::Ring0); + _set_interrupt_handler(irq::NONMASKABLE_INTERRUPT_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::nonmaskable_interrupt_handler, Ring::Ring0); + _set_interrupt_handler(irq::BREAKPOINT_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::breakpoint_handler, Ring::Ring0); + _set_interrupt_handler(irq::OVERFLOW_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::overflow_handler, Ring::Ring0); + _set_interrupt_handler(irq::BOUND_RANGE_EXCEEDED_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::bound_range_exceeded_handler, Ring::Ring0); + _set_interrupt_handler(irq::INVALID_OPCODE_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::invalid_opcode_handler, Ring::Ring0); + _set_interrupt_handler(irq::DEVICE_NOT_AVAILABLE_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::device_not_available_handler, Ring::Ring0); + _set_interrupt_handler(irq::DOUBLE_FAULT_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::double_fault_handler, Ring::Ring0); + _set_interrupt_handler(irq::COPROCESSOR_SEGMENT_OVERRUN_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::coprocessor_segment_overrun_handler, Ring::Ring0); + _set_interrupt_handler(irq::INVALID_TSS_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::invalid_tss_handler, Ring::Ring0); + _set_interrupt_handler(irq::SEGMENT_NOT_PRESENT_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::segment_not_present_handler, Ring::Ring0); + _set_interrupt_handler(irq::STACK_SEGEMENT_FAULT_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::stack_segment_fault_handler, Ring::Ring0); + _set_interrupt_err_handler(irq::GENERAL_PROTECTION_FAULT_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::general_protection_handler, Ring::Ring0); + _set_interrupt_err_handler(irq::PAGE_FAULT_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::page_fault_handler, Ring::Ring0); + _set_interrupt_handler(irq::X87_FPU_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::x87_fpu_floating_point_handler, Ring::Ring0); + _set_interrupt_handler(irq::ALIGNMENT_CHECK_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::alignment_check_handler, Ring::Ring0); + _set_interrupt_handler(irq::MACHINE_CHECK_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::machine_check_handler, Ring::Ring0); + _set_interrupt_handler(irq::SIMD_FLOATING_POINT_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::simd_floating_point_handler, Ring::Ring0); + _set_interrupt_handler(irq::VIRTUALIZATION_VECTOR, segment::KERNEL_CODE_SELECTOR, interrupt::virtualization_handler, Ring::Ring0); + for i in 32..IDT_ENTRY_COUNT as u8 { - _set_interrupt_handler(i, interrupt::default_interrupt_handler); + _set_interrupt_handler(i, segment::KERNEL_CODE_SELECTOR, interrupt::default_interrupt_handler, Ring::Ring0); } // crate::println!("IDT initialized with {} entries", IDT_ENTRY_COUNT); diff --git a/src/kernel/asm/x86/interrupt.rs b/src/kernel/asm/x86/interrupt.rs index 8a0c868..d855837 100644 --- a/src/kernel/asm/x86/interrupt.rs +++ b/src/kernel/asm/x86/interrupt.rs @@ -6,36 +6,218 @@ use x86::irq::{self, PageFaultError, EXCEPTIONS}; use crate::{print, println}; use crate::hal::cpu; +fn print_exception(vector: u8, error_code: Option, fault_addr: Option) { + if vector < 32 { + let ex = &EXCEPTIONS[vector as usize]; + crate::println!("CPU Exception: {}", ex); + + // 如果有錯誤碼 + if let Some(code) = error_code { + println!("Error code: 0x{:x}", code); + + // 如果是頁錯誤,解析錯誤碼 + if vector == irq::PAGE_FAULT_VECTOR { + let pf_error = PageFaultError::from_bits_truncate(code); + println!("Fault details:\n{}", pf_error); + } + } + + // 如果有故障地址(如頁錯誤) + if let Some(addr) = fault_addr { + println!("Fault address: 0x{:x}", addr); + } + } else { + crate::println!("Unhandled interrupt: Vector {}", vector); + } + + crate::println!("System halted"); +} + /// isr0 #[no_mangle] -pub extern "C" fn divide_error_handler() { +pub fn divide_error_handler(error_code: u32) { let ex = &EXCEPTIONS[irq::DIVIDE_ERROR_VECTOR as usize]; - println!("CPU Exception: {} ({})", ex.mnemonic, ex.description); - println!("Type: {}, Source: {}", ex.irqtype, ex.source); + println!("Error code: 0x{:x}", error_code); + println!("CPU Exception: {}", ex); + loop {} +} +/// isr1 +#[no_mangle] +pub fn debug_error_handler() { + let ex = &EXCEPTIONS[irq::DEBUG_VECTOR as usize]; + println!("CPU Exception: {}", ex); loop {} } +/// isr2 #[no_mangle] -pub extern "C" fn page_fault_handler() { +pub fn nonmaskable_interrupt_handler() { + let ex = &EXCEPTIONS[irq::NONMASKABLE_INTERRUPT_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr3 +#[no_mangle] +pub fn breakpoint_handler() { + let ex = &EXCEPTIONS[irq::BREAKPOINT_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr4 +#[no_mangle] +pub fn overflow_handler() { + let ex = &EXCEPTIONS[irq::OVERFLOW_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr5 +#[no_mangle] +pub fn bound_range_exceeded_handler() { + let ex = &EXCEPTIONS[irq::BOUND_RANGE_EXCEEDED_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr6 +#[no_mangle] +pub fn invalid_opcode_handler() { + let ex = &EXCEPTIONS[irq::INVALID_OPCODE_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr7 +#[no_mangle] +pub fn device_not_available_handler() { + let ex = &EXCEPTIONS[irq::DEVICE_NOT_AVAILABLE_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr8 +#[no_mangle] +pub fn double_fault_handler() { + let ex = &EXCEPTIONS[irq::DOUBLE_FAULT_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr9 +#[no_mangle] +pub fn coprocessor_segment_overrun_handler() { + let ex = &EXCEPTIONS[irq::COPROCESSOR_SEGMENT_OVERRUN_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr10 +#[no_mangle] +pub fn invalid_tss_handler() { + let ex = &EXCEPTIONS[irq::INVALID_TSS_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr11 +#[no_mangle] +pub fn segment_not_present_handler() { + let ex = &EXCEPTIONS[irq::SEGMENT_NOT_PRESENT_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr12 +#[no_mangle] +pub fn stack_segment_fault_handler() { + let ex = &EXCEPTIONS[irq::STACK_SEGEMENT_FAULT_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr13 +#[no_mangle] +pub fn general_protection_handler(error_code: u32) { + let ex = &EXCEPTIONS[irq::GENERAL_PROTECTION_FAULT_VECTOR as usize]; + let cr2: u32; + cr2 = cpu::cpu_r_cr2() as u32; + println!("CPU Exception: {}", ex); + println!("Error code: 0x{:x}", error_code); + println!("Fault address: 0x{:x}", cr2); + loop {} +} + +/// isr14 +#[no_mangle] +pub fn page_fault_handler(error_code: u32) { let cr2: u32; cr2 = cpu::cpu_r_cr2() as u32; let ex = &EXCEPTIONS[irq::PAGE_FAULT_VECTOR as usize]; - crate::println!("CPU Exception: {} ({})", ex.mnemonic, ex.description); - crate::println!("Fault address: 0x{:x}", cr2); + println!("CPU Exception: {} ({})", ex.mnemonic, ex.description); + println!("Error code: 0x{:x}", error_code); + println!("Fault address: 0x{:x}", cr2); + + // 使用錯誤碼 + let error_flags = PageFaultError::from_bits_truncate(error_code); + println!("Page fault details:\n{}", error_flags); loop {} } +/// isr16 #[no_mangle] -pub extern "C" fn general_protection_handler() { - let ex = &EXCEPTIONS[irq::GENERAL_PROTECTION_FAULT_VECTOR as usize]; - crate::println!("CPU Exception: {} ({})", ex.mnemonic, ex.description); +pub fn x87_fpu_floating_point_handler() { + let ex = &EXCEPTIONS[irq::X87_FPU_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr17 +#[no_mangle] +pub fn alignment_check_handler() { + let ex = &EXCEPTIONS[irq::ALIGNMENT_CHECK_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr18 +#[no_mangle] +pub fn machine_check_handler() { + let ex = &EXCEPTIONS[irq::MACHINE_CHECK_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr19 +#[no_mangle] +pub fn simd_floating_point_handler() { + let ex = &EXCEPTIONS[irq::SIMD_FLOATING_POINT_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + +/// isr20 +#[no_mangle] +pub fn virtualization_handler() { + let ex = &EXCEPTIONS[irq::VIRTUALIZATION_VECTOR as usize]; + println!("CPU Exception: {}", ex); + loop {} +} + + +/// isr15, 21-31 +#[no_mangle] +pub fn reserved_handler(vector: u8) { + let ex = &EXCEPTIONS[vector as usize]; + println!("CPU Exception: {}", ex); loop {} } #[no_mangle] -pub extern "C" fn default_interrupt_handler() { - crate::println!("Unhandled interrupt!"); +pub fn default_interrupt_handler() { + println!("Unhandled interrupt!"); loop {} } \ No newline at end of file diff --git a/src/kernel/asm/x86/mod.rs b/src/kernel/asm/x86/mod.rs index 7a16afe..ac7dbff 100644 --- a/src/kernel/asm/x86/mod.rs +++ b/src/kernel/asm/x86/mod.rs @@ -1,3 +1,4 @@ pub mod gdt; pub mod idt; -pub mod interrupt; \ No newline at end of file +pub mod interrupt; +pub mod segment; \ No newline at end of file diff --git a/src/kernel/asm/x86/segment.rs b/src/kernel/asm/x86/segment.rs new file mode 100644 index 0000000..ac9b388 --- /dev/null +++ b/src/kernel/asm/x86/segment.rs @@ -0,0 +1,19 @@ +use x86::segmentation::SegmentSelector; +use x86::Ring; + +pub const NULL_SELECTOR: SegmentSelector = SegmentSelector::new(0, Ring::Ring0); +pub const KERNEL_CODE_SELECTOR: SegmentSelector = SegmentSelector::new(1, Ring::Ring0); +pub const KERNEL_DATA_SELECTOR: SegmentSelector = SegmentSelector::new(2, Ring::Ring0); +pub const USER_CODE_SELECTOR: SegmentSelector = SegmentSelector::new(3, Ring::Ring3); +pub const USER_DATA_SELECTOR: SegmentSelector = SegmentSelector::new(4, Ring::Ring3); + +#[no_mangle] +pub static NULL_SEL: u16 = NULL_SELECTOR.bits(); +#[no_mangle] +pub static KERNEL_CODE_SEL: u16 = KERNEL_CODE_SELECTOR.bits(); +#[no_mangle] +pub static KERNEL_DATA_SEL: u16 = KERNEL_DATA_SELECTOR.bits(); +#[no_mangle] +pub static USER_CODE_SEL: u16 = USER_CODE_SELECTOR.bits(); +#[no_mangle] +pub static USER_DATA_SEL: u16 = USER_DATA_SELECTOR.bits(); \ No newline at end of file diff --git a/src/kernel/kernel.rs b/src/kernel/kernel.rs index 39c2191..1806404 100644 --- a/src/kernel/kernel.rs +++ b/src/kernel/kernel.rs @@ -40,14 +40,14 @@ pub extern "C" fn _kernel_main() { println!("{}", cpu::cpu_get_brand(&mut brand_buffer)); println!("{}", cpu::cpu_get_model(&mut brand_buffer)); - // unsafe { - // core::arch::asm!( - // "movl $0, %eax", - // "movl $0, %ebx", - // "divl %ebx", - // options(att_syntax) - // ); - // } + unsafe { + core::arch::asm!( + "movl $0, %eax", + "movl $0, %ebx", + "divl %ebx", + options(att_syntax) + ); + } // cpu::cpu_enable_interrupts();