diff --git a/src/interrupts/gdt.rs b/src/interrupts/gdt.rs index d016480..2e8c685 100644 --- a/src/interrupts/gdt.rs +++ b/src/interrupts/gdt.rs @@ -1,3 +1,5 @@ +use core::fmt; +use core::fmt::Debug; use x86_64::structures::tss::TaskStateSegment; use x86_64::structures::gdt::SegmentSelector; use x86_64::PrivilegeLevel; @@ -85,11 +87,27 @@ impl Descriptor { } bitflags! { + /// Reference: https://wiki.osdev.org/GDT flags DescriptorFlags: u64 { + const ACCESSED = 1 << 40, + const DATA_WRITABLE = 1 << 41, + const CODE_READABLE = 1 << 41, const CONFORMING = 1 << 42, const EXECUTABLE = 1 << 43, const USER_SEGMENT = 1 << 44, + const USER_MODE = 1 << 45 | 1 << 46, const PRESENT = 1 << 47, const LONG_MODE = 1 << 53, } } + +impl Debug for Descriptor { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match self { + Descriptor::UserSegment(flags) => + write!(f, "UserSegment( {:?} )", DescriptorFlags{bits: *flags}), + Descriptor::SystemSegment(low, high) => + write!(f, "SystemSegment{:?}", (low, high)), + } + } +} \ No newline at end of file diff --git a/src/interrupts/irq.rs b/src/interrupts/irq.rs new file mode 100644 index 0000000..0d246c4 --- /dev/null +++ b/src/interrupts/irq.rs @@ -0,0 +1,21 @@ +use x86_64::structures::idt::*; + +pub extern "x86-interrupt" fn breakpoint_handler( + stack_frame: &mut ExceptionStackFrame) +{ + println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); +} + +pub extern "x86-interrupt" fn double_fault_handler( + stack_frame: &mut ExceptionStackFrame, _error_code: u64) +{ + println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); + loop {} +} + +pub extern "x86-interrupt" fn page_fault_handler( + stack_frame: &mut ExceptionStackFrame, error_code: PageFaultErrorCode) +{ + println!("\nEXCEPTION: PAGE FAULT\n{:#?}\n{:#?}", stack_frame, error_code); + loop {} +} \ No newline at end of file diff --git a/src/interrupts/mod.rs b/src/interrupts/mod.rs index aedd2ce..8b20197 100644 --- a/src/interrupts/mod.rs +++ b/src/interrupts/mod.rs @@ -1,13 +1,15 @@ use x86_64::VirtualAddress; -use x86_64::structures::idt::*; +use x86_64::structures::idt::Idt; use x86_64::structures::tss::TaskStateSegment; use memory::MemoryController; use spin::Once; mod gdt; +mod irq; lazy_static! { static ref IDT: Idt = { + use self::irq::*; let mut idt = Idt::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); idt.page_fault.set_handler_fn(page_fault_handler); @@ -19,12 +21,22 @@ lazy_static! { }; } +// Copied from xv6 x86_64 +const GNULL: gdt::Descriptor = gdt::Descriptor::UserSegment(0); +const KCODE: gdt::Descriptor = gdt::Descriptor::UserSegment(0x0020980000000000); // EXECUTABLE | USER_SEGMENT | PRESENT | LONG_MODE +const UCODE: gdt::Descriptor = gdt::Descriptor::UserSegment(0x0020F80000000000); // EXECUTABLE | USER_SEGMENT | USER_MODE | PRESENT | LONG_MODE +const KDATA: gdt::Descriptor = gdt::Descriptor::UserSegment(0x0000920000000000); // DATA_WRITABLE | USER_SEGMENT | PRESENT +const UDATA: gdt::Descriptor = gdt::Descriptor::UserSegment(0x0000F20000000000); // DATA_WRITABLE | USER_SEGMENT | USER_MODE | PRESENT + static TSS: Once = Once::new(); static GDT: Once = Once::new(); const DOUBLE_FAULT_IST_INDEX: usize = 0; pub fn init(memory_controller: &mut MemoryController) { + + test::print_flags(); + use x86_64::structures::gdt::SegmentSelector; use x86_64::instructions::segmentation::set_cs; use x86_64::instructions::tables::load_tss; @@ -43,7 +55,12 @@ pub fn init(memory_controller: &mut MemoryController) { let mut tss_selector = SegmentSelector(0); let gdt = GDT.call_once(|| { let mut gdt = gdt::Gdt::new(); - code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); + gdt.add_entry(GNULL); + kcode_selector = + gdt.add_entry(KCODE); + gdt.add_entry(UCODE); + gdt.add_entry(KDATA); + gdt.add_entry(UDATA); tss_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss)); gdt }); @@ -59,22 +76,21 @@ pub fn init(memory_controller: &mut MemoryController) { IDT.load(); } -extern "x86-interrupt" fn breakpoint_handler( - stack_frame: &mut ExceptionStackFrame) -{ - println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); -} - -extern "x86-interrupt" fn double_fault_handler( - stack_frame: &mut ExceptionStackFrame, _error_code: u64) +pub mod test { - println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); - loop {} -} - -extern "x86-interrupt" fn page_fault_handler( - stack_frame: &mut ExceptionStackFrame, error_code: PageFaultErrorCode) -{ - println!("\nEXCEPTION: PAGE FAULT\n{:#?}\n{:#?}", stack_frame, error_code); - loop {} + pub fn print_flags() { + use super::gdt::*; + // The following 4 GDT entries were copied from xv6 x86_64 + let list: [(&str, Descriptor); 4] = [ + ("KCODE", super::KCODE), // Code, DPL=0, R/X + ("UCODE", super::UCODE), // Code, DPL=3, R/X + ("KDATA", super::KDATA), // Data, DPL=0, W + ("UDATA", super::UDATA), // Data, DPL=3, W + ]; + // Let's see what that means + println!("GDT Segments from xv6 x86_64:"); + for (name, desc) in list.iter() { + println!(" {}: {:?}", name, desc); + } + } } \ No newline at end of file