From d2060e76f8b02cc19a67b25ccc4dd0e09ff855c9 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Wed, 19 Apr 2017 12:08:08 +0200 Subject: [PATCH] Create a GDT descriptor struct --- src/interrupts/gdt.rs | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/interrupts/gdt.rs b/src/interrupts/gdt.rs index bf23aaf..50e73e5 100644 --- a/src/interrupts/gdt.rs +++ b/src/interrupts/gdt.rs @@ -1,3 +1,5 @@ +use x86_64::structures::tss::TaskStateSegment; + pub struct Gdt { table: [u64; 8], next_free: usize, @@ -11,3 +13,46 @@ impl Gdt { } } } + +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; + use bit_field::BitField; + + let ptr = tss as *const _ as u64; + + let mut low = PRESENT.bits(); + // base + low.set_bits(16..40, ptr.get_bits(0..24)); + low.set_bits(56..64, ptr.get_bits(24..32)); + // limit (the `-1` in needed since the bound is inclusive) + low.set_bits(0..16, (size_of::() - 1) as u64); + // type (0b1001 = available 64-bit tss) + low.set_bits(40..44, 0b1001); + + let mut high = 0; + high.set_bits(0..32, ptr.get_bits(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, + } +}