diff options
Diffstat (limited to 'kernel/src/interrupts')
-rw-r--r-- | kernel/src/interrupts/exceptions.rs | 15 | ||||
-rw-r--r-- | kernel/src/interrupts/gdt.rs | 61 | ||||
-rw-r--r-- | kernel/src/interrupts/mod.rs | 1 | ||||
-rw-r--r-- | kernel/src/interrupts/table.rs | 11 |
4 files changed, 79 insertions, 9 deletions
diff --git a/kernel/src/interrupts/exceptions.rs b/kernel/src/interrupts/exceptions.rs index 08555c4..782dd16 100644 --- a/kernel/src/interrupts/exceptions.rs +++ b/kernel/src/interrupts/exceptions.rs @@ -4,6 +4,7 @@ use x86_64::structures::idt::{InterruptStackFrame, PageFaultErrorCode}; pub extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut InterruptStackFrame) { let mut stdout = OStream::new(); stdout.print(b"EXCEPTION: BREAKPOINT\n"); + loop {} } pub extern "x86-interrupt" fn page_fault_handler( @@ -13,11 +14,11 @@ pub extern "x86-interrupt" fn page_fault_handler( use x86_64::registers::control::Cr2; let mut stdout = OStream::new(); - stdout.print(b"EXCEPTION: PAGEFAULT\n"); - loop {} - panic!("PAGE FAULT"); - //println!("Accessed Address: {:?}", Cr2::read()); - //println!("Error Code: {:?}", error_code); + panic!( + "PAGE FAULT while accessing address: {:?}{:?}", + Cr2::read(), + error_code + ); //println!("{:#?}", stack_frame); } @@ -25,12 +26,12 @@ pub extern "x86-interrupt" fn segment_not_present_handler( stack_frame: &mut InterruptStackFrame, error_code: u64, ) { - loop {} let mut stdout = OStream::new(); stdout.print(b"EXCEPTION: SEGMENT NOT PRESENT\n"); + loop {} } -extern "x86-interrupt" fn double_fault_handler( +pub extern "x86-interrupt" fn double_fault_handler( stack_frame: &mut InterruptStackFrame, _error_code: u64, ) { diff --git a/kernel/src/interrupts/gdt.rs b/kernel/src/interrupts/gdt.rs new file mode 100644 index 0000000..8f20092 --- /dev/null +++ b/kernel/src/interrupts/gdt.rs @@ -0,0 +1,61 @@ +use lazy_static::lazy_static; +use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector}; +use x86_64::structures::tss::TaskStateSegment; +use x86_64::VirtAddr; + +pub const DOUBLE_FAULT_IST_INDEX: u16 = 0; +pub const PAGE_FAULT_IST_INDEX: u16 = 1; + +lazy_static! { + static ref TSS: TaskStateSegment = { + let mut tss = TaskStateSegment::new(); + tss.interrupt_stack_table[DOUBLE_FAULT_IST_INDEX as usize] = { + const STACK_SIZE: usize = 4096; + static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; + + let stack_start = VirtAddr::from_ptr(unsafe { &STACK }); + let stack_end = stack_start + STACK_SIZE; + stack_end + }; + tss.interrupt_stack_table[PAGE_FAULT_IST_INDEX as usize] = { + const STACK_SIZE: usize = 4096; + static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; + + let stack_start = VirtAddr::from_ptr(unsafe { &STACK }); + let stack_end = stack_start + STACK_SIZE; + stack_end + }; + tss + }; +} + +lazy_static! { + static ref GDT: (GlobalDescriptorTable, Selectors) = { + let mut gdt = GlobalDescriptorTable::new(); + let code_selector = gdt.add_entry(Descriptor::kernel_code_segment()); + let tss_selector = gdt.add_entry(Descriptor::tss_segment(&TSS)); + ( + gdt, + Selectors { + code_selector, + tss_selector, + }, + ) + }; +} + +struct Selectors { + code_selector: SegmentSelector, + tss_selector: SegmentSelector, +} + +pub fn init() { + use x86_64::instructions::segmentation::set_cs; + use x86_64::instructions::tables::load_tss; + + GDT.0.load(); + unsafe { + set_cs(GDT.1.code_selector); + load_tss(GDT.1.tss_selector); + } +} diff --git a/kernel/src/interrupts/mod.rs b/kernel/src/interrupts/mod.rs index ae21761..14de3f2 100644 --- a/kernel/src/interrupts/mod.rs +++ b/kernel/src/interrupts/mod.rs @@ -1,2 +1,3 @@ mod exceptions; +pub mod gdt; pub mod table; diff --git a/kernel/src/interrupts/table.rs b/kernel/src/interrupts/table.rs index 6472014..d417824 100644 --- a/kernel/src/interrupts/table.rs +++ b/kernel/src/interrupts/table.rs @@ -7,10 +7,17 @@ lazy_static! { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint .set_handler_fn(super::exceptions::breakpoint_handler); - idt.page_fault - .set_handler_fn(super::exceptions::page_fault_handler); idt.segment_not_present .set_handler_fn(super::exceptions::segment_not_present_handler); + unsafe { + idt.double_fault + .set_handler_fn(super::exceptions::double_fault_handler) + .set_stack_index(super::gdt::DOUBLE_FAULT_IST_INDEX); + idt.page_fault + .set_handler_fn(super::exceptions::page_fault_handler) + .set_stack_index(super::gdt::PAGE_FAULT_IST_INDEX); + } + idt }; } |