Skip to main content

proka_kernel/interrupts/
handler.rs

1#[allow(unused)]
2use crate::interrupts::pic::{PICS, PIC_1_OFFSET};
3use crate::serial_println;
4use x86_64::{
5    registers::control::Cr2,
6    structures::idt::{InterruptStackFrame, PageFaultErrorCode},
7    VirtAddr,
8};
9
10macro_rules! exception_handler {
11    ($name:ident, $msg:expr) => {
12        pub extern "x86-interrupt" fn $name(stack_frame: InterruptStackFrame) {
13            serial_println!("EXCEPTION: {}\n{:#?}", $msg, stack_frame);
14            hlt_loop() // 需替换为恢复逻辑或panic处理
15        }
16    };
17}
18
19macro_rules! exception_handler_with_error_code {
20    ($name:ident, $msg:expr) => {
21        pub extern "x86-interrupt" fn $name(
22            stack_frame: InterruptStackFrame,
23            error_code: u64, // 统一使用u64接收错误码
24        ) {
25            serial_println!(
26                "EXCEPTION: {} [ERR: {:#x}]\n{:#?}",
27                $msg,
28                error_code,
29                stack_frame
30            );
31            hlt_loop()
32        }
33    };
34}
35
36// 无错误码异常 -------------------------------------------------
37exception_handler!(divide_error_handler, "DIVIDE ERROR");
38exception_handler!(debug_handler, "DEBUG");
39exception_handler!(nmi_handler, "NON-MASKABLE INTERRUPT");
40exception_handler!(overflow_handler, "OVERFLOW");
41exception_handler!(bound_range_handler, "BOUND RANGE EXCEEDED");
42exception_handler!(invalid_opcode_handler, "INVALID OPCODE");
43exception_handler!(device_not_available_handler, "DEVICE NOT AVAILABLE");
44exception_handler!(x87_floating_point_handler, "x87 FLOATING POINT ERROR");
45
46// 有错误码异常 -------------------------------------------------
47exception_handler_with_error_code!(invalid_tss_handler, "INVALID TSS");
48exception_handler_with_error_code!(segment_not_present_handler, "SEGMENT NOT PRESENT");
49exception_handler_with_error_code!(stack_segment_handler, "STACK-SEGMENT FAULT");
50exception_handler_with_error_code!(general_protection_handler, "GENERAL PROTECTION FAULT");
51exception_handler_with_error_code!(alignment_check_handler, "ALIGNMENT CHECK");
52exception_handler_with_error_code!(control_protection_handler, "CONTROL PROTECTION EXCEPTION");
53
54// 特殊处理异常 -------------------------------------------------
55pub extern "x86-interrupt" fn spurious_interrupt_handler(_stack_frame: InterruptStackFrame) {
56    // 伪中断不需要发送 EOI,仅作为占位符防止未处理中断引发异常
57    // 在调试模式下可以打印日志
58    // serial_println!("SPURIOUS INTERRUPT");
59}
60
61pub extern "x86-interrupt" fn double_fault_handler(
62    stack_frame: InterruptStackFrame,
63    error_code: u64,
64) -> ! {
65    // 必须标记为永不返回
66    serial_println!(
67        "CRITICAL: DOUBLE FAULT [ERR: {:#x}]\n{:#?}",
68        error_code,
69        stack_frame
70    );
71    panic!("SYSTEM HALT"); // 安全地停止系统
72}
73
74pub extern "x86-interrupt" fn pagefault_handler(
75    stack_frame: InterruptStackFrame,
76    error_code: PageFaultErrorCode,
77) {
78    let fault_address = match Cr2::read() {
79        Ok(addr) => addr,
80        Err(_) => VirtAddr::zero(),
81    };
82
83    serial_println!(
84        "EXCEPTION: PAGE FAULT at {:#x}\n \
85         Cause: {:?}\n \
86         Frame: {:#?}",
87        fault_address,
88        error_code,
89        stack_frame
90    );
91    // 实际应执行页面分配回收逻辑
92    hlt_loop()
93}
94
95pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
96    serial_println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
97}
98
99pub extern "x86-interrupt" fn machine_check_handler(stack_frame: InterruptStackFrame) -> ! {
100    serial_println!("CRITICAL: MACHINE CHECK\n{:#?}", stack_frame);
101    panic!("SYSTEM HALT: MACHINE CHECK");
102}
103
104#[inline(always)]
105fn hlt_loop() -> ! {
106    loop {
107        x86_64::instructions::hlt();
108    }
109}
110
111macro_rules! pic_interrupt_handler {
112    ($name:ident, $irq_number:expr) => {
113        #[allow(unused_variables)]
114        pub extern "x86-interrupt" fn $name(stack_frame: InterruptStackFrame) {
115            if $irq_number == 1 {
116                let mut port = x86_64::instructions::port::Port::<u8>::new(0x60);
117                let scancode = unsafe { port.read() };
118                crate::drivers::input::keyboard::KEYBOARD.handle_scancode(scancode);
119            } else {
120                serial_println!("IRQ {} received!", $irq_number);
121            }
122
123            unsafe {
124                PICS.lock()
125                    .notify_end_of_interrupt(PIC_1_OFFSET + $irq_number);
126            }
127        }
128    };
129}
130// 为所有 16 个 IRQ 定义处理函数
131pic_interrupt_handler!(pic_interrupt_handler_0, 0); // 时钟中断 Timer
132pic_interrupt_handler!(pic_interrupt_handler_1, 1); // 键盘中断 Keyboard
133pic_interrupt_handler!(pic_interrupt_handler_2, 2); // 级联到 PIC2
134pic_interrupt_handler!(pic_interrupt_handler_3, 3); // 串口 COM2
135pic_interrupt_handler!(pic_interrupt_handler_4, 4); // 串口 COM1
136pic_interrupt_handler!(pic_interrupt_handler_5, 5); // 并口 LPT2 / 声卡
137pic_interrupt_handler!(pic_interrupt_handler_6, 6); // 软盘控制器 Floppy Disk
138pic_interrupt_handler!(pic_interrupt_handler_7, 7); // 并口 LPT1 / 伪中断
139pic_interrupt_handler!(pic_interrupt_handler_8, 8); // RTC Real Time Clock
140pic_interrupt_handler!(pic_interrupt_handler_9, 9); // 重定向 IRQ2
141pic_interrupt_handler!(pic_interrupt_handler_10, 10); // 空闲 / SCSI / 网卡
142pic_interrupt_handler!(pic_interrupt_handler_11, 11); // 空闲 / SCSI / 网卡
143pic_interrupt_handler!(pic_interrupt_handler_12, 12); // PS/2 鼠标
144pic_interrupt_handler!(pic_interrupt_handler_13, 13); // FPU / 协处理器
145pic_interrupt_handler!(pic_interrupt_handler_14, 14); // 主 IDE Primary IDE
146pic_interrupt_handler!(pic_interrupt_handler_15, 15); // 次 IDE Secondary IDE