diff --git a/blog/post/exceptions.md b/blog/post/exceptions.md new file mode 100644 index 00000000..8f4bac82 --- /dev/null +++ b/blog/post/exceptions.md @@ -0,0 +1,19 @@ ++++ +title = "CPU Exceptions" +date = "2016-05-10" ++++ + +## Interrupts +Whenever a device (e.g. the keyboard contoller) needs + +## Exceptions +An exception signals that something is wrong with the current instruction. For example, the CPU issues an exception when it should divide by 0. When an exception occurs, the CPU immediately calls a specific exception handler function, depending on the exception type. + +We've already seen several types of exceptions in our kernel: + +- **Illegal instruction**: TODO +- **Page Fault**: The CPU tried to perform an illegal read or write. +- **Double Fault**: TODO +- **Triple Fault**: + +The full list of diff --git a/src/interrupts/idt.rs b/src/interrupts/idt.rs new file mode 100644 index 00000000..b8c68197 --- /dev/null +++ b/src/interrupts/idt.rs @@ -0,0 +1,26 @@ +use x86::irq::IdtEntry; + +pub struct Idt([IdtEntry; 16]); + +impl Idt { + pub fn new() -> Idt { + Idt([IdtEntry::missing(); 16]) + } + + pub fn set_handler(&mut self, entry: usize, handler: extern fn()->!) { + let ptr = handler as usize; + self.0[entry] = IdtEntry::interrupt_gate(0x8, ptr as *const _); + } + + pub unsafe fn load(&self) { + use x86::dtables::{DescriptorTablePointer, lidt}; + use core::mem::size_of; + + let ptr = DescriptorTablePointer{ + base: self as *const _ as u64, + limit: (size_of::() - 1) as u16, + }; + + lidt(&ptr); + } +} diff --git a/src/interrupts/mod.rs b/src/interrupts/mod.rs new file mode 100644 index 00000000..95b8711d --- /dev/null +++ b/src/interrupts/mod.rs @@ -0,0 +1,41 @@ +mod idt; + +lazy_static! { + static ref IDT: idt::Idt = { + let mut idt = idt::Idt::new(); + + idt.set_handler(0, divide_by_zero_handler); + idt.set_handler(8, double_fault_handler); + idt.set_handler(13, general_protection_fault_handler); + idt.set_handler(14, page_fault_handler); + + idt + }; +} + +pub fn init() { + assert_has_not_been_called!(); + + unsafe { IDT.load() } +} + + +pub extern fn divide_by_zero_handler() -> ! { + println!("EXCEPTION: DIVIDE BY ZERO"); + loop {} +} + +pub extern fn double_fault_handler() -> ! { + println!("EXCEPTION: DOUBLE FAULT"); + loop {} +} + +pub extern fn general_protection_fault_handler() -> ! { + println!("EXCEPTION: GENERAL PROTECTION FAULT"); + loop {} +} + +pub extern fn page_fault_handler() -> ! { + println!("EXCEPTION: PAGE FAULT"); + loop {} +} diff --git a/src/lib.rs b/src/lib.rs index 9b131ead..a0c75964 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ #![feature(lang_items)] #![feature(const_fn, unique)] #![feature(alloc, collections)] +#![feature(asm)] #![no_std] extern crate rlibc; @@ -29,6 +30,7 @@ extern crate collections; #[macro_use] mod vga_buffer; mod memory; +mod interrupts; #[no_mangle] pub extern "C" fn rust_main(multiboot_information_address: usize) { @@ -50,6 +52,14 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) { format!("Some String"); } + interrupts::init(); + + unsafe { *(0xdeadbeaf as *mut u32) = 42}; + + unsafe { + asm!("xor eax, eax; idiv eax" :::: "intel"); + } + println!("It did not crash!"); loop {}