use core::fmt;
bitflags! {
flags SegmentSelector: u16 {
const RPL_0 = 0b00,
const RPL_1 = 0b01,
const RPL_2 = 0b10,
const RPL_3 = 0b11,
const TI_GDT = 0 << 3,
const TI_LDT = 1 << 3,
}
}
impl SegmentSelector {
pub fn new(index: u16) -> SegmentSelector {
SegmentSelector { bits: index << 3 }
}
pub fn from_raw(bits: u16) -> SegmentSelector {
SegmentSelector { bits: bits }
}
}
impl fmt::Debug for SegmentSelector {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let r0 = match self.contains(RPL_0) {
false => "",
true => "Ring 0 segment selector.",
};
let r1 = match self.contains(RPL_1) {
false => "",
true => "Ring 1 segment selector.",
};
let r2 = match self.contains(RPL_2) {
false => "",
true => "Ring 2 segment selector.",
};
let r3 = match self.contains(RPL_3) {
false => "",
true => "Ring 3 segment selector.",
};
let tbl = match self.contains(TI_LDT) {
false => "GDT Table",
true => "LDT Table",
};
write!(f,
"Index {} in {}, {}{}{}{}",
self.bits >> 3,
tbl,
r0,
r1,
r2,
r3)
}
}
bitflags! {
flags SegmentDescriptor: u64 {
const DESC_S = 1 << (32+12),
const DESC_DPL0 = 0b00 << (32+13),
const DESC_DPL1 = 0b01 << (32+13),
const DESC_DPL2 = 0b10 << (32+13),
const DESC_DPL3 = 0b11 << (32+13),
const DESC_P = 1 << (32+15),
const DESC_AVL = 1 << (32+20),
const DESC_L = 1 << (32+21),
const DESC_DB = 1 << (32+22),
const DESC_G = 1 << (32+23),
const TYPE_SYS_LDT = 0b0010 << (32+8),
const TYPE_SYS_TSS_AVAILABLE = 0b1001 << (32+8),
const TYPE_SYS_TSS_BUSY = 0b1011 << (32+8),
const TYPE_SYS_CALL_GATE = 0b1100 << (32+8),
const TYPE_SYS_INTERRUPT_GATE = 0b1110 << (32+8),
const TYPE_SYS_TRAP_GATE = 0b1111 << (32+8),
const TYPE_D_RO = 0b0000 << (32+8),
const TYPE_D_ROA = 0b0001 << (32+8),
const TYPE_D_RW = 0b0010 << (32+8),
const TYPE_D_RWA = 0b0011 << (32+8),
const TYPE_D_ROEXD = 0b0100 << (32+8),
const TYPE_D_ROEXDA = 0b0101 << (32+8),
const TYPE_D_RWEXD = 0b0110 << (32+8),
const TYPE_D_RWEXDA = 0b0111 << (32+8),
const TYPE_C_EO = 0b1000 << (32+8),
const TYPE_C_EOA = 0b1001 << (32+8),
const TYPE_C_ER = 0b1010 << (32+8),
const TYPE_C_ERA = 0b1011 << (32+8),
const TYPE_C_EOC = 0b1100 << (32+8),
const TYPE_C_EOCA = 0b1101 << (32+8),
const TYPE_C_ERC = 0b1110 << (32+8),
const TYPE_C_ERCA = 0b1111 << (32+8),
}
}
impl SegmentDescriptor {
pub fn new(base: u32, limit: u32) -> SegmentDescriptor {
let base_low: u64 = base as u64 & 0xffffff;
let base_high: u64 = (base as u64 >> 24) & 0xff;
let limit_low: u64 = limit as u64 & 0xffff;
let limit_high: u64 = (limit as u64 & (0b1111 << 16)) >> 16;
SegmentDescriptor {
bits: limit_low | base_low << 16 | limit_high << (32 + 16) | base_high << (32 + 24),
}
}
}
impl fmt::Debug for SegmentDescriptor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "SD: 0x{:x}", self.bits)
}
}
pub unsafe fn load_ss(sel: SegmentSelector) {
asm!("movw $0, %ss " :: "r" (sel) : "memory");
}
pub unsafe fn load_ds(sel: SegmentSelector) {
asm!("movw $0, %ds " :: "r" (sel) : "memory");
}
pub unsafe fn load_es(sel: SegmentSelector) {
asm!("movw $0, %es " :: "r" (sel) : "memory");
}
pub unsafe fn load_fs(sel: SegmentSelector) {
asm!("movw $0, %fs " :: "r" (sel) : "memory");
}
pub unsafe fn load_gs(sel: SegmentSelector) {
asm!("movw $0, %gs " :: "r" (sel) : "memory");
}
pub unsafe fn load_cs(sel: SegmentSelector) {
asm!("pushq $0
lea 1f(%rip), %rax
pushq %rax
lretq
1:" :: "r" (sel.bits() as u64) : "{rax}" "memory");
}