From 933abe8bc6f9480bcdea39c6bdd1a4e937402a06 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Fri, 8 Nov 2019 22:50:13 +0100 Subject: Add InterruptStackTable --- kernel/src/boot.asm | 35 +++++++++++---------- kernel/src/interrupts/exceptions.rs | 15 ++++----- kernel/src/interrupts/gdt.rs | 61 +++++++++++++++++++++++++++++++++++++ kernel/src/interrupts/mod.rs | 1 + kernel/src/interrupts/table.rs | 11 +++++-- kernel/src/lib.rs | 19 +++++++++--- kernel/src/linker.ld | 4 ++- 7 files changed, 113 insertions(+), 33 deletions(-) create mode 100644 kernel/src/interrupts/gdt.rs diff --git a/kernel/src/boot.asm b/kernel/src/boot.asm index 96a1fc1..36b1ef9 100644 --- a/kernel/src/boot.asm +++ b/kernel/src/boot.asm @@ -94,27 +94,26 @@ setup_page_tables: ; map each P2 entry to a huge 2MiB page mov ecx, 0 ; counter variable - mov eax, 0b10000011 ; present + writable + huge - mov edx, stack_bottom - shr edx, 18 + mov eax, 0b10000011 ; huge + writable + present .map_p2_table: - mov ebx, eax - ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx - cmp ecx, edx - jne .valid_memory - add ebx, ~1 - sub eax, 0x200000 ; 2MiB - -.valid_memory: - mov [p2_table + ecx ], ebx ; map ecx-th entry + cmp eax, 0b10000011 + stack_bottom + jne .valid_mem + mov ebx, 0b10000010 + mov [p2_table + ecx], ebx + add ecx, 8 + cmp ecx, 4096 + jne .valid_mem + ret +.valid_mem: + mov [p2_table + ecx], eax add eax, 0x200000 ; 2MiB - add ecx, 8 - cmp ecx, 4096 ; if counter == 512, the whole P2 table is mapped - jne .map_p2_table ; else map the next entry - - ret + add ecx, 8 + cmp ecx, 4096 + jne .map_p2_table + + ret enable_paging: mov eax, p4_table @@ -167,7 +166,7 @@ p3_table: resb 4096 p2_table: resb 4096 -alignb 4096 * 512 +alignb 4096 * 512 ; align memory into huge memory page stack_bottom: resb 4096 * 42 stack_top: 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 }; } diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 8ec68e5..15f027b 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -26,6 +26,7 @@ pub fn test_runner(tests: &[&dyn Fn(&mut OStream)]) { #[no_mangle] pub extern "C" fn _start() -> ! { + interrupts::gdt::init(); interrupts::table::init(); if cfg!(test) { #[cfg(test)] @@ -37,10 +38,19 @@ pub extern "C" fn _start() -> ! { stdout.clear(); panic!("panic! at the disco"); - core::iter::successors(Some(0), |n| Some(n + 1)) - .for_each(|n| write!(&mut stdout, "hello world {}!", n).unwrap()); - - x86_64::instructions::interrupts::int3(); + /// TODO: write test + ///fn _loop(i: u64) -> u64 { + /// if i > 0b1010101001101101 { + /// return i; + /// } + /// let n = i; + /// let mut stdout = OStream::new(); + /// write!(&mut stdout, "{:x}", &n as *const u64 as u64).unwrap(); + /// _loop(i + 1) + ///} + ///_loop(0); + /// TODO: write test + ///x86_64::instructions::interrupts::int3(); loop {} } @@ -72,7 +82,6 @@ pub extern "C" fn panic_handler(info: &core::panic::PanicInfo) -> ! { info.message() .unwrap_or(&format_args!("no panic information obtainable")) ); - //loop{} stderr.set_centered(false); if cfg!(test) { write!(serial::SerialStream::new(), "Testing failed\n").unwrap(); diff --git a/kernel/src/linker.ld b/kernel/src/linker.ld index d187fd2..cca621e 100644 --- a/kernel/src/linker.ld +++ b/kernel/src/linker.ld @@ -13,7 +13,7 @@ SECTIONS { { *(.text) } - rodata : + .rodata : { *(.rodata) } @@ -21,4 +21,6 @@ SECTIONS { { *(.bss) } + /*[Guard page]*/ + . += 2M; } -- cgit v1.2.3-54-g00ecf