aboutsummaryrefslogtreecommitdiff
path: root/src/shared/descriptor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/descriptor.rs')
-rw-r--r--src/shared/descriptor.rs194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/shared/descriptor.rs b/src/shared/descriptor.rs
new file mode 100644
index 0000000..32abb79
--- /dev/null
+++ b/src/shared/descriptor.rs
@@ -0,0 +1,194 @@
+//! Fields which are common to all segment-section and gate descriptors
+
+use shared::PrivilegeLevel;
+use shared::segmentation;
+
+/// System-Segment and Gate-Descriptor Types for IA32e mode. When the `S`
+/// (descriptor type) flag in a segment descriptor is clear, the descriptor type
+/// is a system descriptor.
+///
+/// See Intel manual 3a, 3.5 "System Descriptor Types", and Table 3-2,
+/// System-Segment and Gate-Descriptor Types".
+#[repr(u8)]
+pub enum SystemType {
+ // Reserved = 0
+ TssAvailable = 1,
+ /// Only for 16-bit
+ LocalDescriptorTable = 2,
+ TssBusy = 3,
+ CallGate = 4,
+ /// Only for 16-bit
+ TaskGate = 5,
+ InterruptGate = 6,
+ TrapGate = 7,
+}
+
+/// A high-level representation of a descriptor type. One can convert to and
+/// from the `Flags` bitfield to encode/decode an actual descriptor.
+#[repr(u8)]
+pub enum Type {
+ SystemDescriptor {
+ /// false/0: 16-bit
+ /// true/1: native (32- or 64-bit)
+ size: bool,
+ ty: SystemType
+ },
+ SegmentDescriptor {
+ ty: segmentation::Type,
+ accessed: bool
+ }
+}
+
+impl Type {
+ pub fn pack(self) -> u8 {
+ match self {
+ Type::SystemDescriptor { size, ty } =>
+ (size as u8) << 3 | (ty as u8) | FLAGS_TYPE_SYS.bits,
+ Type::SegmentDescriptor { ty, accessed } =>
+ (accessed as u8) | ty.pack() | FLAGS_TYPE_SYS.bits,
+ }
+ }
+}
+
+
+bitflags!{
+ /// Actual encoding of the flags in byte 6 common to all descriptors.
+ ///
+ /// See Intel manual 3a, figures 3-8, 6-2, and 6-7.
+ pub flags Flags: u8 {
+ /// Descriptor is Present.
+ const FLAGS_PRESENT = 1 << 7,
+
+ // Descriptor privilege level
+ const FLAGS_DPL_RING_0 = 0b00 << 5,
+ const FLAGS_DPL_RING_1 = 0b01 << 5,
+ const FLAGS_DPL_RING_2 = 0b10 << 5,
+ const FLAGS_DPL_RING_3 = 0b11 << 5,
+
+ // Is system descriptor
+ const FLAGS_TYPE_SYS = 0 << 4,
+ const FLAGS_TYPE_SEG = 1 << 4,
+
+ // System-Segment and Gate-Descriptor Types.
+ // When the S (descriptor type) flag in a segment descriptor is clear,
+ // the descriptor type is a system descriptor
+
+ // All modes (supporting segments)
+ const TYPE_SYS_LDT = 0b0_0010,
+
+ // Protected Mode and older
+ const FLAGS_TYPE_SYS_16BIT_TSS_AVAILABLE = 0b0_0001,
+ const FLAGS_TYPE_SYS_16BIT_TSS_BUSY = 0b0_0011,
+ const FLAGS_TYPE_SYS_16BIT_CALL_GATE = 0b0_0100,
+ const FLAGS_TYPE_SYS_16BIT_TASK_GATE = 0b0_0101,
+ const FLAGS_TYPE_SYS_16BIT_INTERRUPT_GATE = 0b0_0110,
+ const FLAGS_TYPE_SYS_16BIT_TRAP_GATE = 0b0_0111,
+
+ // 64-bit in IA-32e Mode (either submode), 32-bit in Protected Mode
+ const FLAGS_TYPE_SYS_NATIVE_TSS_AVAILABLE = 0b0_1001,
+ const FLAGS_TYPE_SYS_NATIVE_TSS_BUSY = 0b0_1011,
+ const FLAGS_TYPE_SYS_NATIVE_CALL_GATE = 0b0_1100,
+ const FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE = 0b0_1110,
+ const FLAGS_TYPE_SYS_NATIVE_TRAP_GATE = 0b0_1111,
+
+ // Code- and Data-Segment Descriptor Types.
+ // When the S (descriptor type) flag in a segment descriptor is set,
+ // the descriptor is for either a code or a data segment.
+
+ /// Data or code, accessed
+ const FLAGS_TYPE_SEG_ACCESSED = 0b1_0001,
+
+ const FLAGS_TYPE_DATA = 0b1_0000,
+ const FLAGS_TYPE_CODE = 0b1_1000,
+
+ // Data => permissions
+ const FLAGS_TYPE_SEG_D_WRITE = 0b1_0010,
+ const FLAGS_TYPE_SEG_D_EXPAND_DOWN = 0b1_0100,
+
+ // Code => permissions
+ const FLAGS_TYPE_SEG_C_READ = 0b1_0010,
+ const FLAGS_TYPE_SEG_D_CONFORMING = 0b1_0100,
+
+ /// Data Read-Only
+ const FLAGS_TYPE_SEG_D_RO = FLAGS_TYPE_DATA.bits,
+ /// Data Read-Only, accessed
+ const FLAGS_TYPE_SEG_D_ROA = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_ACCESSED.bits,
+ /// Data Read/Write
+ const FLAGS_TYPE_SEG_D_RW = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_D_WRITE.bits,
+ /// Data Read/Write, accessed
+ const FLAGS_TYPE_SEG_D_RWA = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_D_WRITE.bits
+ | FLAGS_TYPE_SEG_ACCESSED.bits,
+ /// Data Read-Only, expand-down
+ const FLAGS_TYPE_SEG_D_ROEXD = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
+ /// Data Read-Only, expand-down, accessed
+ const FLAGS_TYPE_SEG_D_ROEXDA = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
+ | FLAGS_TYPE_SEG_ACCESSED.bits,
+ /// Data Read/Write, expand-down
+ const FLAGS_TYPE_SEG_D_RWEXD = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_D_WRITE.bits
+ | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits,
+ /// Data Read/Write, expand-down, accessed
+ const FLAGS_TYPE_SEG_D_RWEXDA = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_D_WRITE.bits
+ | FLAGS_TYPE_SEG_D_EXPAND_DOWN.bits
+ | FLAGS_TYPE_SEG_ACCESSED.bits,
+
+ /// Code Execute-Only
+ const FLAGS_TYPE_SEG_C_EO = FLAGS_TYPE_DATA.bits,
+ /// Code Execute-Only, accessed
+ const FLAGS_TYPE_SEG_C_EOA = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_ACCESSED.bits,
+ /// Code Execute/Read
+ const FLAGS_TYPE_SEG_C_ER = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_C_READ.bits,
+ /// Code Execute/Read, accessed
+ const FLAGS_TYPE_SEG_C_ERA = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_C_READ.bits
+ | FLAGS_TYPE_SEG_ACCESSED.bits,
+ /// Code Execute-Only, conforming
+ const FLAGS_TYPE_SEG_C_EOC = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_D_CONFORMING.bits,
+ /// Code Execute-Only, conforming, accessed
+ const FLAGS_TYPE_SEG_C_EOCA = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_D_CONFORMING.bits
+ | FLAGS_TYPE_SEG_ACCESSED.bits,
+ /// Code Execute/Read, conforming
+ const FLAGS_TYPE_SEG_C_ERC = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_C_READ.bits
+ | FLAGS_TYPE_SEG_D_CONFORMING.bits,
+ /// Code Execute/Read, conforming, accessed
+ const FLAGS_TYPE_SEG_C_ERCA = FLAGS_TYPE_DATA.bits
+ | FLAGS_TYPE_SEG_C_READ.bits
+ | FLAGS_TYPE_SEG_D_CONFORMING.bits
+ | FLAGS_TYPE_SEG_ACCESSED.bits,
+ }
+}
+
+impl Flags {
+ pub const BLANK: Flags = Flags { bits: 0 };
+
+ pub const fn from_priv(dpl: PrivilegeLevel) -> Flags {
+ Flags { bits: (dpl as u8) << 5 }
+ }
+
+ pub fn from_type(ty: Type) -> Flags {
+ Flags { bits: ty.pack() }
+ }
+
+ pub const fn const_or(self, other: Self) -> Flags {
+ Flags { bits: self.bits | other.bits }
+ }
+
+ pub const fn cond(self, cond: bool) -> Flags {
+ Flags { bits: (-(cond as i8) as u8) & self.bits }
+ }
+
+ pub const fn const_mux(self, other: Self, cond: bool) -> Flags {
+ self.cond(cond).const_or(other.cond(!cond))
+ }
+}