interrupts.rs
1 use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; 2 use crate::println; 3 use lazy_static::lazy_static; 4 use crate::gdt; 5 use pic8259::ChainedPics; 6 use spin; 7 use crate::print; 8 use x86_64::structures::idt::PageFaultErrorCode; 9 use crate::hlt_loop; 10 11 lazy_static! { 12 static ref IDT: InterruptDescriptorTable = { 13 let mut idt = InterruptDescriptorTable::new(); 14 idt.breakpoint.set_handler_fn(breakpoint_handler); 15 unsafe { 16 idt.double_fault.set_handler_fn(double_fault_handler) 17 .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); 18 } 19 idt[InterruptIndex::Timer.as_usize()] 20 .set_handler_fn(timer_interrupt_handler); 21 idt[InterruptIndex::Keyboard.as_usize()] 22 .set_handler_fn(keyboard_interrupt_handler); 23 idt.page_fault.set_handler_fn(page_fault_handler); 24 25 idt 26 }; 27 } 28 29 pub fn init_idt() { 30 IDT.load(); 31 } 32 33 extern "x86-interrupt" fn breakpoint_handler( 34 stack_frame: InterruptStackFrame) 35 { 36 println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); 37 } 38 39 extern "x86-interrupt" fn double_fault_handler( 40 stack_frame: InterruptStackFrame, _error_code: u64) -> ! 41 { 42 panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); 43 } 44 45 extern "x86-interrupt" fn timer_interrupt_handler( 46 _stack_frame: InterruptStackFrame) 47 { 48 print!("."); 49 50 unsafe { 51 PICS.lock() 52 .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); 53 } 54 } 55 56 extern "x86-interrupt" fn keyboard_interrupt_handler( 57 _stack_frame: InterruptStackFrame) 58 { 59 use x86_64::instructions::port::Port; 60 61 let mut port = Port::new(0x60); 62 let scancode: u8 = unsafe { port.read() }; 63 crate::task::keyboard::add_scancode(scancode); 64 65 unsafe { 66 PICS.lock() 67 .notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8()); 68 } 69 } 70 71 extern "x86-interrupt" fn page_fault_handler( 72 stack_frame: InterruptStackFrame, 73 error_code: PageFaultErrorCode, 74 ) { 75 use x86_64::registers::control::Cr2; 76 77 println!("EXCEPTION: PAGE FAULT"); 78 println!("Accessed Address: {:?}", Cr2::read()); 79 println!("Error Code: {:?}", error_code); 80 println!("{:#?}", stack_frame); 81 hlt_loop(); 82 } 83 84 pub const PIC_1_OFFSET: u8 = 32; 85 pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; 86 87 pub static PICS: spin::Mutex<ChainedPics> = 88 spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); 89 90 #[derive(Debug, Clone, Copy)] 91 #[repr(u8)] 92 pub enum InterruptIndex { 93 Timer = PIC_1_OFFSET, 94 Keyboard, 95 } 96 97 impl InterruptIndex { 98 fn as_u8(self) -> u8 { 99 self as u8 100 } 101 102 fn as_usize(self) -> usize { 103 usize::from(self.as_u8()) 104 } 105 } 106 107 #[test_case] 108 fn test_breakpoint_exeception() { 109 x86_64::instructions::interrupts::int3(); 110 }