use x86_64::structures::tss::TaskStateSegment; pub struct Gdt { table: [u64; 8], next_free: usize, } impl Gdt { pub fn new() -> Gdt { Gdt { table: [0; 8], next_free: 1, } } } 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, } }