diff --git a/kernel-rs/src/interrupts/mod.rs b/kernel-rs/src/interrupts/mod.rs index 0a59bc83..dc5a3eef 100644 --- a/kernel-rs/src/interrupts/mod.rs +++ b/kernel-rs/src/interrupts/mod.rs @@ -4,16 +4,30 @@ lazy_static! { static ref IDT: Idt = { let mut idt = Idt::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); + idt.double_fault.set_handler_fn(double_fault_handler); + idt[0x21].set_handler_fn(::keyboard::kbd_callback); idt }; } -pub fn init() { +pub fn init(memory_controller: &mut ::memory::MemoryController) { + let double_fault_stack = memory_controller.alloc_stack(1) + .expect("could not allocate double fault stack"); + // println!("DF stack: {:#?}", double_fault_stack); + // flush!(); IDT.load(); } +extern "x86-interrupt" fn double_fault_handler( + stack_frame: &mut ExceptionStackFrame, _error_code: u32) +{ + println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); + flush!(); +} + extern "x86-interrupt" fn breakpoint_handler( stack_frame: &mut ExceptionStackFrame) { println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); + flush!(); } diff --git a/kernel-rs/src/keyboard.rs b/kernel-rs/src/keyboard.rs index c29217a8..de6859db 100644 --- a/kernel-rs/src/keyboard.rs +++ b/kernel-rs/src/keyboard.rs @@ -1,4 +1,5 @@ extern crate core; +use x86::structures::idt::*; use cpuio; use vga; @@ -76,7 +77,10 @@ fn check_key_state(key: u8) -> (bool, usize) { } } -pub fn kbd_callback() { +pub extern "x86-interrupt" fn kbd_callback( + stack_frame: &mut ExceptionStackFrame) { + println!("kbd callback called"); + flush!(); static mut SHIFT: bool = false; static mut CTRL: bool = false; static mut ALT: bool = false; diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 8b57dc33..cb08eff0 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -37,6 +37,7 @@ fn init_kernel(multiboot_info_addr: usize) -> Result <(), &'static str> { let boot_info = unsafe { multiboot2::load(multiboot_info_addr)}; + // ACPI must be intialized BEFORE paging (memory::init()) is active if let Some(rsdp) = boot_info.rsdp_v2_tag() { acpi::load(rsdp)?; } else if let Some(rsdp) = boot_info.rsdp_tag() { @@ -45,11 +46,8 @@ fn init_kernel(multiboot_info_addr: usize) -> Result <(), &'static str> { acpi::init()?; } - enable_paging(); - enable_write_protect_bit(); - - memory::init(&boot_info); - interrupts::init(); + let mut memory_controller = memory::init(&boot_info); + interrupts::init(&mut memory_controller); vga::init(); Ok(()) @@ -62,11 +60,16 @@ pub extern fn kmain(multiboot_info_addr: usize) -> ! { cpuio::halt(); } - x86::instructions::interrupts::int3(); + // x86::instructions::interrupts::int3(); - flush!(); + // fn stack_overflow() { stack_overflow(); } + // stack_overflow(); - loop { keyboard::kbd_callback(); } + // unsafe { + // *(0xdead as *mut u32) = 42; + // }; + + loop {} } #[lang = "eh_personality"] #[no_mangle] diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 7294cce2..aad7c4ca 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -1,11 +1,11 @@ -pub const PAGE_SIZE: usize = 4096; - mod area_allocator; mod heap_allocator; +mod stack_allocator; mod paging; pub use self::area_allocator::*; pub use self::heap_allocator::*; +pub use self::stack_allocator::*; pub use self::paging::remap_the_kernel; use multiboot2; use x86::*; @@ -16,8 +16,25 @@ pub trait FrameAllocator { fn deallocate_frame(&mut self, frame: PhysFrame); } +pub struct MemoryController { + active_table: paging::ActivePageTable, + frame_allocator: AreaFrameAllocator, + stack_allocator: StackAllocator, +} + +impl MemoryController { + pub fn alloc_stack(&mut self, size_in_pages: usize) -> Option { + let &mut MemoryController { ref mut active_table, + ref mut frame_allocator, + ref mut stack_allocator } = self; + + stack_allocator.alloc_stack(active_table, frame_allocator, + size_in_pages) + } +} + /// memory initialisation should only be called once -pub fn init(boot_info: &multiboot2::BootInformation) { +pub fn init(boot_info: &multiboot2::BootInformation) -> MemoryController { use x86::registers::control::{Cr0, Cr4, Cr0Flags, Cr4Flags}; Cr4::add(Cr4Flags::PSE); Cr0::add(Cr0Flags::PAGING | Cr0Flags::WRITE_PROTECT); @@ -52,4 +69,17 @@ pub fn init(boot_info: &multiboot2::BootInformation) { for page in heap_start_page..heap_end_page { active_table.map(page, PageTableFlags::WRITABLE, &mut frame_allocator); } + + let stack_allocator = { + let stack_alloc_start = heap_end_page + 1; + let stack_alloc_end = stack_alloc_start + 100; + let stack_alloc_range = stack_alloc_start..stack_alloc_end + 1; + StackAllocator::new(stack_alloc_range) + }; + + MemoryController { + active_table, + frame_allocator, + stack_allocator, + } } diff --git a/kernel-rs/src/memory/stack_allocator.rs b/kernel-rs/src/memory/stack_allocator.rs new file mode 100644 index 00000000..27fec344 --- /dev/null +++ b/kernel-rs/src/memory/stack_allocator.rs @@ -0,0 +1,81 @@ +use x86::*; +use x86::structures::paging::*; +use memory::paging::{self, ActivePageTable}; +use memory::*; +use core::ops::Range; + +#[derive(Debug)] +pub struct Stack { + top: usize, + bottom: usize, +} + +impl Stack { + fn new (top: usize, bottom: usize) -> Stack { + assert!(top > bottom); + Stack { + top, + bottom, + } + } + + pub fn top(&self) -> usize { + self.top + } + + pub fn bottom(&self) -> usize { + self.bottom + } +} + +#[derive(Debug)] +pub struct StackAllocator { + range: Range +} + +impl StackAllocator { + pub fn new(range: Range) -> StackAllocator { + StackAllocator { range } + } + + pub fn alloc_stack(&mut self, + active_table: &mut ActivePageTable, + frame_allocator: &mut FA, + size_in_pages: usize) -> Option { + if size_in_pages == 0 { + return None; /* a zero sized stack makes no sense */ + } + + // clone the range, since we only want to change it on success + let mut range = self.range.clone(); + + // try to allocate the stack pages and a guard page + let guard_page = range.next(); + let stack_start = range.next(); + let stack_end = if size_in_pages == 1 { + stack_start + } else { + // choose the (size_in_pages-2)th element, since index + // starts at 0 and we already allocated the start page + range.nth(size_in_pages - 2) + }; + + match (guard_page, stack_start, stack_end) { + (Some(_), Some(start), Some(end)) => { + // success! write back updated range + self.range = range.clone(); + + // map stack pages to physical frames + for page in range { + active_table.map(page, PageTableFlags::WRITABLE, frame_allocator); + } + + // create a new stack + let top_of_stack = end.start_address().as_u32() + PAGE_SIZE as u32; + Some(Stack::new(top_of_stack as usize, + start.start_address().as_u32() as usize)) + } + _ => None, /* not enough pages */ + } + } +}