diff options
Diffstat (limited to 'kernel/src')
-rw-r--r-- | kernel/src/boot.asm | 33 | ||||
-rw-r--r-- | kernel/src/interrupts/exceptions.rs | 40 | ||||
-rw-r--r-- | kernel/src/interrupts/mod.rs | 2 | ||||
-rw-r--r-- | kernel/src/interrupts/table.rs | 20 | ||||
-rw-r--r-- | kernel/src/lib.rs | 14 | ||||
-rw-r--r-- | kernel/src/linker.ld | 8 |
6 files changed, 103 insertions, 14 deletions
diff --git a/kernel/src/boot.asm b/kernel/src/boot.asm index 451e455..1c0b3da 100644 --- a/kernel/src/boot.asm +++ b/kernel/src/boot.asm @@ -5,14 +5,16 @@ section .text bits 32 start: mov esp, stack_top - + call check_multiboot call check_cpuid call check_long_mode call setup_page_tables call enable_paging - ; load the 64-bit GDT + + + ; load the 64-bit GDT lgdt [gdt64.pointer] jmp gdt64.code:long_mode_start @@ -96,21 +98,27 @@ setup_page_tables: .map_p2_table: ; map ecx-th P2 entry to a huge page that starts at address 2MiB*ecx + mov ebx, eax + cmp eax, stack_bottom + 0b10000011 - 0x400000 + jne .hit_stack + and ebx, ~1 mov [p2_table + ecx ], eax ; map ecx-th entry - add eax, 0x200000 ; 2MiB - mov [p2_table + ecx + 8 ], eax ; map ecx-th entry - add eax, 0x200000 ; 2MiB - mov [p2_table + ecx + 16], eax ; map ecx-th entry - add eax, 0x200000 ; 2MiB - mov [p2_table + ecx + 24], eax ; map ecx-th entry + add ecx, 8 + +.hit_stack: + mov [p2_table + ecx ], ebx ; map ecx-th entry add eax, 0x200000 ; 2MiB - add ecx, 32 + add ecx, 8 + ;add ecx, 32 cmp ecx, 4096 ; if counter == 512, the whole P2 table is mapped jne .map_p2_table ; else map the next entry ret + + + enable_paging: mov eax, p4_table mov cr3, eax @@ -131,6 +139,10 @@ enable_paging: or eax, 1 << 31 mov cr0, eax + ; move stack pointer to accommodate for the guard page + add esp, 0x200000 + + ret section .rodata @@ -159,6 +171,7 @@ p3_table: resb 4096 p2_table: resb 4096 +alignb 4096 * 512 stack_bottom: - resb 4096 + resb 4096 * 4 stack_top: diff --git a/kernel/src/interrupts/exceptions.rs b/kernel/src/interrupts/exceptions.rs new file mode 100644 index 0000000..08555c4 --- /dev/null +++ b/kernel/src/interrupts/exceptions.rs @@ -0,0 +1,40 @@ +use crate::io::vga_text::OStream; +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"); +} + +pub extern "x86-interrupt" fn page_fault_handler( + stack_frame: &mut InterruptStackFrame, + error_code: PageFaultErrorCode, +) { + 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); + //println!("{:#?}", stack_frame); +} + +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"); +} + +extern "x86-interrupt" fn double_fault_handler( + stack_frame: &mut InterruptStackFrame, + _error_code: u64, +) { + let mut stdout = OStream::new(); + stdout.print(b"EXCEPTION: DOUBLE FAULT"); + loop {} +} diff --git a/kernel/src/interrupts/mod.rs b/kernel/src/interrupts/mod.rs new file mode 100644 index 0000000..ae21761 --- /dev/null +++ b/kernel/src/interrupts/mod.rs @@ -0,0 +1,2 @@ +mod exceptions; +pub mod table; diff --git a/kernel/src/interrupts/table.rs b/kernel/src/interrupts/table.rs new file mode 100644 index 0000000..6472014 --- /dev/null +++ b/kernel/src/interrupts/table.rs @@ -0,0 +1,20 @@ +use crate::io::vga_text::OStream; +use lazy_static::lazy_static; +use x86_64::structures::idt::InterruptDescriptorTable; + +lazy_static! { + static ref IDT: InterruptDescriptorTable = { + 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); + idt + }; +} + +pub fn init() { + IDT.load() +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index cbc9915..8ec68e5 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,13 +1,13 @@ #![no_main] #![feature(compiler_builtins_lib)] #![feature(custom_test_frameworks)] +#![feature(abi_x86_interrupt)] #![feature(panic_info_message)] #![test_runner(crate::test_runner)] #![reexport_test_harness_main = "test_main"] #![no_std] -extern crate compiler_builtins; - +mod interrupts; mod io; use core::fmt::Write; @@ -26,6 +26,7 @@ pub fn test_runner(tests: &[&dyn Fn(&mut OStream)]) { #[no_mangle] pub extern "C" fn _start() -> ! { + interrupts::table::init(); if cfg!(test) { #[cfg(test)] test_main(); @@ -39,6 +40,7 @@ pub extern "C" fn _start() -> ! { core::iter::successors(Some(0), |n| Some(n + 1)) .for_each(|n| write!(&mut stdout, "hello world {}!", n).unwrap()); + x86_64::instructions::interrupts::int3(); loop {} } @@ -64,8 +66,12 @@ pub extern "C" fn panic_handler(info: &core::panic::PanicInfo) -> ! { vga_text::Color::Red, )); stderr.set_centered(true); - write!(&mut stderr, "{:?}", info.message() - .unwrap_or(&format_args!("no panic information obtainable"))); + write!( + &mut stderr, + "{:?}", + info.message() + .unwrap_or(&format_args!("no panic information obtainable")) + ); //loop{} stderr.set_centered(false); if cfg!(test) { diff --git a/kernel/src/linker.ld b/kernel/src/linker.ld index 9b5355c..d187fd2 100644 --- a/kernel/src/linker.ld +++ b/kernel/src/linker.ld @@ -13,4 +13,12 @@ SECTIONS { { *(.text) } + rodata : + { + *(.rodata) + } + .bss : + { + *(.bss) + } } |