feat: Handling interrupts

This commit is contained in:
ParrotXray 2025-05-12 20:33:45 +08:00
parent 24b03ece89
commit 582c789632
7 changed files with 269 additions and 68 deletions

View File

@ -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

View File

@ -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]

View File

@ -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);

View File

@ -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<u32>, fault_addr: Option<u32>) {
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 {}
}

View File

@ -1,3 +1,4 @@
pub mod gdt;
pub mod idt;
pub mod interrupt;
pub mod interrupt;
pub mod segment;

View File

@ -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();

View File

@ -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();