From c961fdc32bb1edd69ddfb3ed964d1d4990701f37 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Wed, 25 May 2016 14:03:43 +0200 Subject: [PATCH] wip --- src/interrupts/gdt.rs | 115 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/interrupts/gdt.rs diff --git a/src/interrupts/gdt.rs b/src/interrupts/gdt.rs new file mode 100644 index 00000000..930b1caf --- /dev/null +++ b/src/interrupts/gdt.rs @@ -0,0 +1,115 @@ +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)); +}