diff --git a/Cargo.toml b/Cargo.toml index a5503538..d0cb6f3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,10 @@ name = "blog_os" version = "0.1.0" [dependencies] -bit_field = "0.1.0" -bitflags = "0.7.0" once = "0.2.1" rlibc = "0.1.4" spin = "0.3.4" +bitflags = "0.7.0" [dependencies.hole_list_allocator] path = "libs/hole_list_allocator" @@ -18,7 +17,7 @@ git = "https://github.com/phil-opp/multiboot2-elf64" [dependencies.x86] default-features = false -version = "0.7.0" +version = "0.6.0" [lib] crate-type = ["staticlib"] diff --git a/src/interrupts/gdt.rs b/src/interrupts/gdt.rs deleted file mode 100644 index 930b1caf..00000000 --- a/src/interrupts/gdt.rs +++ /dev/null @@ -1,115 +0,0 @@ -use bit_field::BitField; -use collections::vec::Vec; -use core::ops::Range; -use x86::task::TaskStateSegment; - -pub struct Gdt(Vec>); - -impl Gdt { - pub fn new() -> Gdt { - let zero_entry = BitField::new(0); - Gdt(vec![zero_entry]) - } - - pub fn add_entry(&mut self, entry: Entry) -> Selector { - use core::mem::size_of; - let index = self.0.len() * size_of::>(); - - match entry { - Entry::UserSegment(entry) => self.0.push(entry), - Entry::SystemSegment(entry_low, entry_high) => { - self.0.push(entry_low); - self.0.push(entry_high); - } - } - - Selector(index as u16) - } - - pub unsafe fn load(&'static self) { - use x86::dtables::{DescriptorTablePointer, lgdt}; - use core::mem::{self, size_of}; - - let ptr = DescriptorTablePointer { - base: self.0.as_ptr() as u64, - limit: (self.0.len() * size_of::() - 1) as u16, - }; - - lgdt(&ptr); - } -} - -pub enum Entry { - UserSegment(BitField), - SystemSegment(BitField, BitField), -} - -impl Entry { - pub fn code_segment() -> Entry { - let flags = DESCRIPTOR_TYPE | PRESENT | READ_WRITE | EXECUTABLE | LONG_MODE; - Entry::UserSegment(BitField::new(flags.bits())) - } - - pub fn data_segment() -> Entry { - let flags = DESCRIPTOR_TYPE | PRESENT | READ_WRITE; - Entry::UserSegment(BitField::new(flags.bits())) - } - - pub fn tss_segment(tss: &'static TaskStateSegment) -> Entry { - use core::mem::size_of; - - let ptr = BitField::new(tss as *const _ as u64); - - let mut low = BitField::new(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 = BitField::new(0); - high.set_range(0..32, ptr.get_range(32..64)); - - Entry::SystemSegment(low, high) - } -} - -bitflags! { - flags EntryFlags: u64 { - const READ_WRITE = 1 << 41, - const CONFORMING = 1 << 42, - const EXECUTABLE = 1 << 43, - const DESCRIPTOR_TYPE = 1 << 44, - const PRESENT = 1 << 47, - const LONG_MODE = 1 << 53, - } -} - -#[derive(Debug, Clone, Copy)] -pub struct Selector(u16); - -pub fn reload_segment_registers(code_selector: Selector, data_selector: Selector) { - - let current_code_selector: u16; - let current_data_selector: u16; - - unsafe { - asm!("mov $0, cs" : "=r" (current_code_selector) ::: "intel"); - asm!("mov $0, ds" : "=r" (current_data_selector) ::: "intel"); - } - assert_eq!(code_selector.0, current_code_selector); - assert_eq!(data_selector.0, current_data_selector); - - // jmp ax:.new_code_segment // TODO - // .new_code_segment: - // unsafe { asm!(" - // mov ax, $1 - // mov ss, ax - // mov ds, ax - // mov es, ax - // ":: "r" (code_selector.0), "r" (data_selector.0) :: "intel")}; - // -} - -/// Load the task state register. -pub unsafe fn load_ltr(selector: Selector) { - asm!("ltr $0" :: "r" (selector)); -} diff --git a/src/interrupts/idt.rs b/src/interrupts/idt.rs deleted file mode 100644 index 43ecb467..00000000 --- a/src/interrupts/idt.rs +++ /dev/null @@ -1,101 +0,0 @@ -use x86::segmentation::{self, SegmentSelector}; - -pub struct Idt([Entry; 16]); - -impl Idt { - pub fn new() -> Idt { - Idt([Entry::missing(); 16]) - } - - pub fn set_handler(&mut self, entry: u8, handler: extern "C" fn() -> !) -> &mut EntryOptions { - self.0[entry as usize] = Entry::new(segmentation::cs(), handler); - &mut self.0[entry as usize].options - } - - pub fn load(&'static self) { - use x86::dtables::{DescriptorTablePointer, lidt}; - use core::mem::size_of; - - let ptr = DescriptorTablePointer { - base: self as *const _ as u64, - limit: (size_of::() - 1) as u16, - }; - - unsafe { lidt(&ptr) }; - } -} - -use bit_field::BitField; - -#[derive(Debug, Clone, Copy)] -#[repr(C, packed)] -pub struct Entry { - pointer_low: u16, - gdt_selector: SegmentSelector, - options: EntryOptions, - pointer_middle: u16, - pointer_high: u32, - reserved: u32, -} - -impl Entry { - fn missing() -> Self { - Entry { - gdt_selector: SegmentSelector::new(0), - pointer_low: 0, - pointer_middle: 0, - pointer_high: 0, - options: EntryOptions::minimal(), - reserved: 0, - } - } - - fn new(gdt_selector: SegmentSelector, handler: extern "C" fn() -> !) -> Self { - let pointer = handler as u64; - Entry { - gdt_selector: gdt_selector, - pointer_low: pointer as u16, - pointer_middle: (pointer >> 16) as u16, - pointer_high: (pointer >> 32) as u32, - options: EntryOptions::new(), - reserved: 0, - } - } -} - -#[derive(Debug, Clone, Copy)] -pub struct EntryOptions(BitField); - -impl EntryOptions { - fn minimal() -> Self { - let mut options = BitField::new(0); - options.set_range(9..12, 0b111); // required 'one' bits - EntryOptions(options) - } - - fn new() -> Self { - let mut options = Self::minimal(); - options.set_present(true); - options - } - - pub fn set_present(&mut self, present: bool) -> &mut Self { - self.0.set_bit(15, present); - self - } - - pub fn disable_interrupts(&mut self, disable: bool) -> &mut Self { - self.0.set_bit(8, !disable); - self - } - - pub fn set_privilege_level(&mut self, dpl: u16) -> &mut Self { - self.0.set_range(13..15, dpl); - self - } - - 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 deleted file mode 100644 index e628d1b9..00000000 --- a/src/interrupts/mod.rs +++ /dev/null @@ -1,90 +0,0 @@ -use x86::task::{load_ltr, TaskStateSegment}; -use vga_buffer::print_error; - -mod idt; -mod gdt; - -lazy_static! { - static ref IDT: idt::Idt = { - let mut idt = idt::Idt::new(); - - idt.set_handler(0, divide_by_zero_handler); - idt.set_handler(8, double_fault_handler).set_stack_index(1); - idt.set_handler(13, general_protection_fault_handler); - idt.set_handler(14, page_fault_handler); - - idt - }; - - static ref TSS: TaskStateSegment = { - let mut tss = TaskStateSegment::new(); - - let stack_size = 1024 * 3; // 3KiB - let stack_bottom = unsafe { - ::alloc::heap::allocate(stack_size, 16) as usize // TODO - }; - let stack_top = stack_bottom + stack_size; - - tss.ist[0] = stack_top as u64; - - tss - }; - - static ref GDT: Gdt = { - let mut table = gdt::Gdt::new(); - - let selectors = GdtSelectors { - code: table.add_entry(gdt::Entry::code_segment()), - data: table.add_entry(gdt::Entry::data_segment()), - tss: table.add_entry(gdt::Entry::tss_segment(&TSS)), - }; - - Gdt { - table: table, - selectors: selectors, - } - }; -} - -struct Gdt { - table: gdt::Gdt, - selectors: GdtSelectors, -} - -struct GdtSelectors { - code: gdt::Selector, - data: gdt::Selector, - tss: gdt::Selector, -} - -pub fn init() { - assert_has_not_been_called!(); - - unsafe { - GDT.table.load(); - gdt::reload_segment_registers(GDT.selectors.code, GDT.selectors.data); - gdt::load_ltr(GDT.selectors.tss); - } - IDT.load(); -} - -extern "C" fn divide_by_zero_handler() -> ! { - unsafe { print_error(format_args!("EXCEPTION: DIVIDE BY ZERO")) }; - loop {} -} - -extern "C" fn double_fault_handler() -> ! { - unsafe { print_error(format_args!("EXCEPTION: DOUBLE FAULT")) }; - unsafe { asm!("iretq")}; - loop {} -} - -extern "C" fn general_protection_fault_handler() -> ! { - unsafe { print_error(format_args!("EXCEPTION: GENERAL PROTECTION FAULT")) }; - loop {} -} - -extern "C" fn page_fault_handler() -> ! { - unsafe { print_error(format_args!("EXCEPTION: PAGE FAULT")) }; - loop {} -} diff --git a/src/lib.rs b/src/lib.rs index 89fc5a86..9b131ead 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,9 +10,6 @@ #![feature(lang_items)] #![feature(const_fn, unique)] #![feature(alloc, collections)] -#![feature(asm)] -#![feature(drop_types_in_const)] -#![feature(heap_api)] #![no_std] extern crate rlibc; @@ -29,12 +26,9 @@ extern crate alloc; #[macro_use] extern crate collections; -extern crate bit_field; - #[macro_use] mod vga_buffer; mod memory; -mod interrupts; #[no_mangle] pub extern "C" fn rust_main(multiboot_information_address: usize) { @@ -49,20 +43,11 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) { // set up guard page and map the heap pages memory::init(boot_info); - interrupts::init(); + use alloc::boxed::Box; + let heap_test = Box::new(42); - //println!("{:?}", unsafe { *(0xdeadbeaf as *mut u32) }); - //unsafe { *(0xdeadbeaf as *mut u32) = 42 }; - - fn recursive() { - recursive(); - } - recursive(); - - unsafe { *(0xdeadbeaf as *mut u32) = 42 }; - - unsafe { - asm!("xor eax, eax; idiv eax" :::: "intel"); + for i in 0..10000 { + format!("Some String"); } println!("It did not crash!"); @@ -94,11 +79,8 @@ extern "C" fn eh_personality() {} #[cfg(not(test))] #[lang = "panic_fmt"] extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &str, line: u32) -> ! { - use vga_buffer::print_error; - unsafe { - print_error(format_args!("\n\nPANIC in {} at line {}:", file, line)); - print_error(format_args!(" {}", fmt)); - } + println!("\n\nPANIC in {} at line {}:", file, line); + println!(" {}", fmt); loop {} } diff --git a/src/vga_buffer.rs b/src/vga_buffer.rs index 7f319cdf..2546fdd5 100644 --- a/src/vga_buffer.rs +++ b/src/vga_buffer.rs @@ -135,15 +135,3 @@ struct ScreenChar { struct Buffer { chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT], } - -pub unsafe fn print_error(fmt: fmt::Arguments) { - use core::fmt::Write; - - let mut writer = Writer { - column_position: 0, - color_code: ColorCode::new(Color::Red, Color::Black), - buffer: Unique::new(0xb8000 as *mut _), - }; - writer.new_line(); - writer.write_fmt(fmt); -}