use core::fmt;
use bit_field::BitField;
use bitflags::bitflags;
bitflags! {
#[repr(transparent)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy)]
pub struct PageFaultErrorCode: u64 {
const PROTECTION_VIOLATION = 1;
const CAUSED_BY_WRITE = 1 << 1;
const USER_MODE = 1 << 2;
const MALFORMED_TABLE = 1 << 3;
const INSTRUCTION_FETCH = 1 << 4;
const PROTECTION_KEY = 1 << 5;
const SHADOW_STACK = 1 << 6;
const SGX = 1 << 15;
const RMP = 1 << 31;
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct SelectorErrorCode {
flags: u64,
}
impl SelectorErrorCode {
pub const fn new(value: u64) -> Option<Self> {
if value > u16::MAX as u64 {
None
} else {
Some(Self { flags: value })
}
}
pub const fn new_truncate(value: u64) -> Self {
Self {
flags: (value as u16) as u64,
}
}
pub fn external(&self) -> bool {
self.flags.get_bit(0)
}
pub fn descriptor_table(&self) -> DescriptorTable {
match self.flags.get_bits(1..3) {
0b00 => DescriptorTable::Gdt,
0b01 => DescriptorTable::Idt,
0b10 => DescriptorTable::Ldt,
0b11 => DescriptorTable::Idt,
_ => unreachable!(),
}
}
pub fn index(&self) -> u64 {
self.flags.get_bits(3..16)
}
pub fn is_null(&self) -> bool {
self.flags == 0
}
}
impl fmt::Debug for SelectorErrorCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut s = f.debug_struct("Selector Error");
s.field("external", &self.external());
s.field("descriptor table", &self.descriptor_table());
s.field("index", &self.index());
s.finish()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DescriptorTable {
Gdt,
Idt,
Ldt,
}