|
|
|
@ -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::<TaskStateSegment>() - 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,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|