proka_kernel/interrupts/
handler.rs1#[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() }
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, ) {
25 serial_println!(
26 "EXCEPTION: {} [ERR: {:#x}]\n{:#?}",
27 $msg,
28 error_code,
29 stack_frame
30 );
31 hlt_loop()
32 }
33 };
34}
35
36exception_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
46exception_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
54pub extern "x86-interrupt" fn spurious_interrupt_handler(_stack_frame: InterruptStackFrame) {
56 }
60
61pub extern "x86-interrupt" fn double_fault_handler(
62 stack_frame: InterruptStackFrame,
63 error_code: u64,
64) -> ! {
65 serial_println!(
67 "CRITICAL: DOUBLE FAULT [ERR: {:#x}]\n{:#?}",
68 error_code,
69 stack_frame
70 );
71 panic!("SYSTEM HALT"); }
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 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}
130pic_interrupt_handler!(pic_interrupt_handler_0, 0); pic_interrupt_handler!(pic_interrupt_handler_1, 1); pic_interrupt_handler!(pic_interrupt_handler_2, 2); pic_interrupt_handler!(pic_interrupt_handler_3, 3); pic_interrupt_handler!(pic_interrupt_handler_4, 4); pic_interrupt_handler!(pic_interrupt_handler_5, 5); pic_interrupt_handler!(pic_interrupt_handler_6, 6); pic_interrupt_handler!(pic_interrupt_handler_7, 7); pic_interrupt_handler!(pic_interrupt_handler_8, 8); pic_interrupt_handler!(pic_interrupt_handler_9, 9); pic_interrupt_handler!(pic_interrupt_handler_10, 10); pic_interrupt_handler!(pic_interrupt_handler_11, 11); pic_interrupt_handler!(pic_interrupt_handler_12, 12); pic_interrupt_handler!(pic_interrupt_handler_13, 13); pic_interrupt_handler!(pic_interrupt_handler_14, 14); pic_interrupt_handler!(pic_interrupt_handler_15, 15);