diff --git a/src/arch/x86_64/boot.asm b/src/arch/x86_64/boot.asm index b4ff26f1..a9d7a6bb 100644 --- a/src/arch/x86_64/boot.asm +++ b/src/arch/x86_64/boot.asm @@ -29,6 +29,12 @@ start: ; load the 64-bit GDT lgdt [gdt64.pointer] + ; update selectors + mov ax, gdt64.data + mov ss, ax + mov ds, ax + mov es, ax + jmp gdt64.code:long_mode_start set_up_page_tables: @@ -196,7 +202,9 @@ section .rodata gdt64: dq 0 ; zero entry .code: equ $ - gdt64 ; new - dq (1<<44) | (1<<47) | (1<<43) | (1<<53) ; code segment + dq (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53) ; code segment +.data: equ $ - gdt64 ; new + dq (1<<44) | (1<<47) | (1<<41) ; data segment .pointer: dw $ - gdt64 - 1 dq gdt64 diff --git a/src/interrupts/gdt.rs b/src/interrupts/gdt.rs deleted file mode 100644 index e67956f3..00000000 --- a/src/interrupts/gdt.rs +++ /dev/null @@ -1,91 +0,0 @@ -use bit_field::BitField; -use x86::bits64::task::TaskStateSegment; -use x86::shared::segmentation::SegmentSelector; -use x86::shared::PrivilegeLevel; - -pub struct Gdt { - table: [u64; 8], - current_offset: usize, -} - -impl Gdt { - pub fn new() -> Gdt { - Gdt { - table: [0; 8], - current_offset: 1, - } - } - - fn push(&mut self, value: u64) -> usize { - if self.current_offset < self.table.len() { - let offset = self.current_offset; - self.table[offset] = value; - self.current_offset += 1; - offset - } else { - panic!("GDT full"); - } - } - - pub fn add_entry(&mut self, entry: Descriptor) -> SegmentSelector { - let index = match entry { - Descriptor::UserSegment(value) => self.push(value), - Descriptor::SystemSegment(value_low, value_high) => { - let index = self.push(value_low); - self.push(value_high); - index - } - }; - SegmentSelector::new(index as u16, PrivilegeLevel::Ring0) - } - - pub fn load(&'static self) { - use x86::shared::dtables::{DescriptorTablePointer, lgdt}; - use core::mem::size_of; - - let ptr = DescriptorTablePointer { - base: self.table.as_ptr() as *const ::x86::shared::segmentation::SegmentDescriptor, - limit: (self.table.len() * size_of::() - 1) as u16, - }; - - unsafe { lgdt(&ptr) }; - } -} - -pub enum Descriptor { - UserSegment(u64), - SystemSegment(u64, u64), -} - -impl Descriptor { - pub fn kernel_code_segment() -> Descriptor { - let flags = USER_SEGMENT | PRESENT | EXECUTABLE | LONG_MODE; - Descriptor::UserSegment(flags.bits()) - } - - pub fn tss_segment(tss: &'static TaskStateSegment) -> Descriptor { - use core::mem::size_of; - - let ptr = tss as *const _ as u64; - - let mut low = PRESENT.bits(); - low.set_range(0..16, (size_of::() - 1) as u64); - low.set_range(16..40, ptr.get_range(0..24)); - low.set_range(40..44, 0b1001); // type: available 64-bit tss - - let mut high = 0; - high.set_range(0..32, ptr.get_range(32..64)); - - Descriptor::SystemSegment(low, high) - } -} - -bitflags! { - flags DescriptorFlags: u64 { - const CONFORMING = 1 << 42, - const EXECUTABLE = 1 << 43, - const USER_SEGMENT = 1 << 44, - const PRESENT = 1 << 47, - const LONG_MODE = 1 << 53, - } -} diff --git a/src/interrupts/idt.rs b/src/interrupts/idt.rs index 63f81410..9c191cbb 100644 --- a/src/interrupts/idt.rs +++ b/src/interrupts/idt.rs @@ -102,14 +102,14 @@ impl EntryOptions { } #[allow(dead_code)] - pub fn set_privilege_level(&mut self, dpl: u8) -> &mut Self { - self.0.set_range(13..15, dpl.into()); + pub fn set_privilege_level(&mut self, dpl: u16) -> &mut Self { + self.0.set_range(13..15, dpl); self } #[allow(dead_code)] - pub fn set_stack_index(&mut self, index: u8) -> &mut Self { - self.0.set_range(0..3, (index + 1).into()); + pub fn set_stack_index(&mut self, index: u16) -> &mut Self { + self.0.set_range(0..3, index); self } } diff --git a/src/interrupts/mod.rs b/src/interrupts/mod.rs index 15dde3ed..6556236e 100644 --- a/src/interrupts/mod.rs +++ b/src/interrupts/mod.rs @@ -7,12 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use spin::Once; -use memory::MemoryController; -use x86::bits64::task::TaskStateSegment; - mod idt; -mod gdt; macro_rules! save_scratch_registers { () => { @@ -98,46 +93,13 @@ lazy_static! { idt.set_handler(0, handler!(divide_by_zero_handler)); idt.set_handler(3, handler!(breakpoint_handler)); idt.set_handler(6, handler!(invalid_opcode_handler)); - idt.set_handler(8, handler_with_error_code!(double_fault_handler)) - .set_stack_index(DOUBLE_FAULT_IST_INDEX as u8); idt.set_handler(14, handler_with_error_code!(page_fault_handler)); idt }; } -static TSS: Once = Once::new(); -static GDT: Once = Once::new(); -const DOUBLE_FAULT_IST_INDEX: usize = 0; - -pub fn init(memory_controller: &mut MemoryController) { - use x86::shared::segmentation::{SegmentSelector, set_cs}; - use x86::shared::task::load_tr; - - let double_fault_stack = memory_controller.alloc_stack(1) - .expect("could not allocate double fault stack"); - - let tss = TSS.call_once(|| { - let mut tss = TaskStateSegment::new(); - tss.ist[DOUBLE_FAULT_IST_INDEX] = double_fault_stack.top() as u64; - tss - }); - - let mut code_selector = SegmentSelector::empty(); - let mut tss_selector = SegmentSelector::empty(); - let gdt = GDT.call_once(|| { - let mut gdt = gdt::Gdt::new(); - tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss)); - code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); - gdt - }); - gdt.load(); - - unsafe { - set_cs(code_selector); - load_tr(tss_selector); - } - +pub fn init() { IDT.load(); } @@ -188,8 +150,3 @@ extern "C" fn page_fault_handler(stack_frame: &ExceptionStackFrame, error_code: stack_frame); loop {} } - -extern "C" fn double_fault_handler(stack_frame: &ExceptionStackFrame, _error_code: u64) { - println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); - loop {} -} diff --git a/src/lib.rs b/src/lib.rs index c2149d2b..441b2e5f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,6 @@ #![feature(asm)] #![feature(naked_functions)] #![feature(core_intrinsics)] -#![feature(drop_types_in_const)] #![no_std] extern crate rlibc; @@ -52,31 +51,14 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) { enable_write_protect_bit(); // set up guard page and map the heap pages - let mut memory_controller = memory::init(boot_info); + memory::init(boot_info); // initialize our IDT - interrupts::init(&mut memory_controller); + interrupts::init(); + // trigger a breakpoint exception unsafe { int!(3) }; - stack_overflow(); - // trigger a debug exception - unsafe { int!(1) }; - - fn divide_by_zero() { - unsafe { asm!("mov dx, 0; div dx" ::: "ax", "dx" : "volatile", "intel") } - } - - fn int_overflow() { - unsafe { asm!("mov al, 0xf0; add al, 0x10; into" ::: "ax", "dx" : "volatile", "intel") } - } - - fn stack_overflow() { - stack_overflow(); - } - - int_overflow(); - println!("It did not crash!"); loop {} } diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 22693792..266aa5a2 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -9,17 +9,15 @@ pub use self::area_frame_allocator::AreaFrameAllocator; pub use self::paging::remap_the_kernel; -pub use self::stack_allocator::Stack; use self::paging::PhysicalAddress; use multiboot2::BootInformation; mod area_frame_allocator; mod paging; -mod stack_allocator; pub const PAGE_SIZE: usize = 4096; -pub fn init(boot_info: &BootInformation) -> MemoryController { +pub fn init(boot_info: &BootInformation) { assert_has_not_been_called!("memory::init must be called only once"); let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required"); @@ -60,34 +58,6 @@ pub fn init(boot_info: &BootInformation) -> MemoryController { for page in Page::range_inclusive(heap_start_page, heap_end_page) { active_table.map(page, paging::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 = Page::range_inclusive(stack_alloc_start, stack_alloc_end); - stack_allocator::new_stack_allocator(stack_alloc_range) - }; - - MemoryController { - active_table: active_table, - frame_allocator: frame_allocator, - stack_allocator: stack_allocator, - } -} - -pub struct MemoryController { - active_table: paging::ActivePageTable, - frame_allocator: AreaFrameAllocator, - stack_allocator: 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) - } } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] diff --git a/src/memory/paging/mod.rs b/src/memory/paging/mod.rs index 2d7b48d7..6c80fbcd 100644 --- a/src/memory/paging/mod.rs +++ b/src/memory/paging/mod.rs @@ -11,7 +11,7 @@ pub use self::entry::*; use memory::{PAGE_SIZE, Frame, FrameAllocator}; use self::temporary_page::TemporaryPage; pub use self::mapper::Mapper; -use core::ops::{Deref, DerefMut, Add}; +use core::ops::{Deref, DerefMut}; use multiboot2::BootInformation; mod entry; @@ -37,7 +37,7 @@ impl Page { Page { number: address / PAGE_SIZE } } - pub fn start_address(&self) -> usize { + fn start_address(&self) -> usize { self.number * PAGE_SIZE } @@ -62,15 +62,6 @@ impl Page { } } -impl Add for Page { - type Output = Page; - - fn add(self, rhs: usize) -> Page { - Page { number: self.number + rhs } - } -} - -#[derive(Debug, Clone)] pub struct PageIter { start: Page, end: Page, diff --git a/src/memory/stack_allocator.rs b/src/memory/stack_allocator.rs deleted file mode 100644 index 47e8b5c3..00000000 --- a/src/memory/stack_allocator.rs +++ /dev/null @@ -1,75 +0,0 @@ -use memory::paging::{self, Page, PageIter, ActivePageTable}; -use memory::{PAGE_SIZE, FrameAllocator}; - -pub fn new_stack_allocator(page_range: PageIter) -> StackAllocator { - StackAllocator { range: page_range } -} - -pub struct StackAllocator { - range: PageIter, -} - -impl StackAllocator { - 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; - } - - 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 { - 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; - - // map stack pages to physical frames - for page in Page::range_inclusive(start, end) { - active_table.map(page, paging::WRITABLE, frame_allocator); - } - - // create a new stack - let top_of_stack = end.start_address() + PAGE_SIZE; - Some(Stack::new(top_of_stack, start.start_address())) - } - _ => None, /* not enough pages */ - } - } -} - -#[derive(Debug)] -pub struct Stack { - top: usize, - bottom: usize, -} - -impl Stack { - fn new(top: usize, bottom: usize) -> Stack { - assert!(top > bottom); - Stack { - top: top, - bottom: bottom, - } - } - - pub fn top(&self) -> usize { - self.top - } - - #[allow(dead_code)] - pub fn bottom(&self) -> usize { - self.bottom - } -}