diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bits32/irq.rs | 57 | ||||
-rw-r--r-- | src/bits32/mod.rs | 40 | ||||
-rw-r--r-- | src/bits64/irq.rs | 273 | ||||
-rw-r--r-- | src/bits64/paging.rs | 48 | ||||
-rw-r--r-- | src/shared/descriptor.rs | 109 | ||||
-rw-r--r-- | src/shared/irq.rs | 207 | ||||
-rw-r--r-- | src/shared/mod.rs | 69 | ||||
-rw-r--r-- | src/shared/paging.rs | 48 |
8 files changed, 473 insertions, 378 deletions
diff --git a/src/bits32/irq.rs b/src/bits32/irq.rs new file mode 100644 index 0000000..5d6eb0d --- /dev/null +++ b/src/bits32/irq.rs @@ -0,0 +1,57 @@ +//! Interrupt description and set-up code. + +use shared::descriptor::*; +use shared::paging::VAddr; +use shared::PrivilegeLevel; + +/// An interrupt gate or trap gate descriptor. +/// +/// See Intel manual 3a for details, specifically section 6.11. +#[derive(Debug, Copy, Clone)] +#[repr(C, packed)] +pub struct IdtEntry { + /// Lower 16 bits of ISR. + pub offset_lo: u16, + /// Segment selector. + pub selector: u16, + /// This must always be zero. + pub reserved: u8, + /// flags. + pub flags: Flags, + /// The upper 16 bits of ISR. + pub offset_hi: u16 +} + +impl IdtEntry { + pub const MISSING: IdtEntry = IdtEntry { + offset_lo: 0, + selector: 0, + reserved: 0, + flags: Flags::BLANK, + offset_hi: 0 + }; + + /// Create a new IdtEntry pointing at `handler`, which must be a function + /// with interrupt calling conventions. (This must be currently defined in + /// assembly language.) The `gdt_code_selector` value must be the offset of + /// code segment entry in the GDT. + /// + /// The "Present" flag set, which is the most common case. If you need + /// something else, you can construct it manually. + pub const fn new(handler: VAddr, gdt_code_selector: u16, + dpl: PrivilegeLevel, block: bool) -> IdtEntry { + IdtEntry { + offset_lo: ((handler.as_usize() as u32) & 0xFFFF) as u16, + offset_hi: ((handler.as_usize() as u32 & 0xFFFF0000) >> 16) as u16, + selector: gdt_code_selector, + reserved: 0, + // Nice bitflags operations don't work in const fn, hence these + // ad-hoc methods. + flags: Flags::from_priv(dpl) + .const_or(FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE + .const_mux(FLAGS_TYPE_SYS_NATIVE_TRAP_GATE, + block)) + .const_or(FLAGS_PRESENT), + } + } +} diff --git a/src/bits32/mod.rs b/src/bits32/mod.rs index 84e78f2..9b30258 100644 --- a/src/bits32/mod.rs +++ b/src/bits32/mod.rs @@ -1,8 +1,12 @@ -//! Data structures and functions used by Protected Mode but not IA-32e. - #![allow(non_upper_case_globals)] -pub use shared::*; +pub mod irq; + +pub use shared::{ + Flags, + PrivilegeLevel, +}; +pub use self::irq::IdtEntry; use core::mem::size_of; @@ -27,16 +31,6 @@ pub struct GdtEntry { base3: u8, } -#[derive(Copy, Clone)] -#[repr(C, packed)] -pub struct IdtEntry { - offset1: u16, - selector: u16, - reserved: u8, - flags: u8, - offset2: u16 -} - impl GdtEntry { pub const NULL: GdtEntry = GdtEntry { base1: 0, @@ -67,26 +61,6 @@ impl GdtEntry { } } -impl IdtEntry { - pub const NULL: IdtEntry = IdtEntry { - offset1: 0, - selector: 0, - reserved: 0, - flags: 0, - offset2: 0 - }; - - pub fn new(f: unsafe extern "C" fn(), dpl: PrivilegeLevel, block: bool) -> IdtEntry { - IdtEntry { - offset1: f as u16, - offset2: ((f as usize & 0xFFFF0000) >> 16) as u16, - selector: 8, - reserved: 0, - flags: if block { 0x8E } else { 0x8F } | ((dpl as u8) << 5) - } - } -} - #[derive(Copy, Clone, Debug)] #[repr(C, packed)] pub struct Tss { diff --git a/src/bits64/irq.rs b/src/bits64/irq.rs index a1b6d12..84ee0e6 100644 --- a/src/bits64/irq.rs +++ b/src/bits64/irq.rs @@ -1,266 +1,69 @@ //! Interrupt description and set-up code. use core::fmt; -use super::paging::VAddr; -/// x86 Exception description (see also Intel Vol. 3a Chapter 6). -#[derive(Debug)] -pub struct InterruptDescription { - pub vector: u8, - pub mnemonic: &'static str, - pub description: &'static str, - pub irqtype: &'static str, - pub source: &'static str, -} - -impl fmt::Display for InterruptDescription { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, - "{} ({}, vec={}) {}", - self.mnemonic, - self.irqtype, - self.vector, - self.description) - } -} - - -/// x86 External Interrupts (1-16). -pub static EXCEPTIONS: [InterruptDescription; 21] = [InterruptDescription { - vector: 0, - mnemonic: "#DE", - description: "Divide Error", - irqtype: "Fault", - source: "DIV and IDIV instructions.", - }, - InterruptDescription { - vector: 1, - mnemonic: "#DB", - description: "Debug", - irqtype: "Fault/ Trap", - source: "Debug condition", - }, - InterruptDescription { - vector: 2, - mnemonic: "NMI", - description: "Nonmaskable Interrupt", - irqtype: "Interrupt", - source: "Nonmaskable external interrupt.", - }, - InterruptDescription { - vector: 3, - mnemonic: "#BP", - description: "Breakpoint", - irqtype: "Trap", - source: "INT 3 instruction.", - }, - InterruptDescription { - vector: 4, - mnemonic: "#OF", - description: "Overflow", - irqtype: "Trap", - source: "INTO instruction.", - }, - InterruptDescription { - vector: 5, - mnemonic: "#BR", - description: "BOUND Range Exceeded", - irqtype: "Fault", - source: "BOUND instruction.", - }, - InterruptDescription { - vector: 6, - mnemonic: "#UD", - description: "Invalid Opcode (Undefined \ - Opcode)", - irqtype: "Fault", - source: "UD2 instruction or reserved \ - opcode.", - }, - InterruptDescription { - vector: 7, - mnemonic: "#NM", - description: "Device Not Available (No \ - Math Coprocessor)", - irqtype: "Fault", - source: "Floating-point or WAIT/FWAIT \ - instruction.", - }, - InterruptDescription { - vector: 8, - mnemonic: "#DF", - description: "Double Fault", - irqtype: "Abort", - source: "Any instruction that can \ - generate an exception, an NMI, \ - or an INTR.", - }, - InterruptDescription { - vector: 9, - mnemonic: "", - description: "Coprocessor Segment Overrun", - irqtype: "Fault", - source: "Floating-point instruction.", - }, - InterruptDescription { - vector: 10, - mnemonic: "#TS", - description: "Invalid TSS", - irqtype: "Fault", - source: "Task switch or TSS access.", - }, - InterruptDescription { - vector: 11, - mnemonic: "#NP", - description: "Segment Not Present", - irqtype: "Fault", - source: "Loading segment registers or \ - accessing system segments.", - }, - InterruptDescription { - vector: 12, - mnemonic: "#SS", - description: "Stack-Segment Fault", - irqtype: "Fault", - source: "Stack operations and SS register \ - loads.", - }, - InterruptDescription { - vector: 13, - mnemonic: "#GP", - description: "General Protection", - irqtype: "Fault", - source: "Any memory reference and other \ - protection checks.", - }, - InterruptDescription { - vector: 14, - mnemonic: "#PF", - description: "Page Fault", - irqtype: "Fault", - source: "Any memory reference.", - }, - InterruptDescription { - vector: 15, - mnemonic: "", - description: "RESERVED", - irqtype: "", - source: "None.", - }, - InterruptDescription { - vector: 16, - mnemonic: "#MF", - description: "x87 FPU Floating-Point", - irqtype: "Fault", - source: "x87 FPU instructions.", - }, - InterruptDescription { - vector: 17, - mnemonic: "#AC", - description: "Alignment Check", - irqtype: "Fault", - source: "Unaligned memory access.", - }, - InterruptDescription { - vector: 18, - mnemonic: "#MC", - description: "Machine Check", - irqtype: "Abort", - source: "Internal machine error.", - }, - InterruptDescription { - vector: 19, - mnemonic: "#XM", - description: "SIMD Floating-Point", - irqtype: "Fault", - source: "SSE SIMD instructions.", - }, - InterruptDescription { - vector: 20, - mnemonic: "#VE", - description: "Virtualization", - irqtype: "Fault", - source: "EPT violation.", - }]; - - -/// Enable Interrupts. -pub unsafe fn enable() { - asm!("sti"); -} +use shared::descriptor::*; +use shared::paging::VAddr; +use shared::PrivilegeLevel; -/// Disable Interrupts. -pub unsafe fn disable() { - asm!("cli"); -} - -/// Generate a software interrupt. -/// This is a macro argument needs to be an immediate. -#[macro_export] -macro_rules! int { - ( $x:expr ) => { - { - asm!("int $0" :: "N" ($x)); - } - }; -} - -/// A struct describing an interrupt gate. See the Intel manual mentioned -/// above for details, specifically, the section "6.14.1 64-Bit Mode IDT" -/// and "Table 3-2. System-Segment and Gate-Descriptor Types". +/// An interrupt gate descriptor. +/// +/// See Intel manual 3a for details, specifically section "6.14.1 64-Bit Mode +/// IDT" and "Table 3-2. System-Segment and Gate-Descriptor Types". #[derive(Debug, Clone, Copy)] #[repr(C, packed)] pub struct IdtEntry { /// Lower 16 bits of ISR. pub base_lo: u16, /// Segment selector. - pub sel: u16, + pub selector: u16, /// This must always be zero. - pub res0: u8, + pub reserved0: u8, /// Flags. - pub flags: u8, + pub flags: Flags, /// The upper 48 bits of ISR (the last 16 bits must be zero). pub base_hi: u64, /// Must be zero. - pub res1: u16, + pub reserved1: u16, } impl IdtEntry { - /// Create a "missing" IdtEntry. This is a `const` function, so we can - /// call it at compile time to initialize static variables. + /// A "missing" IdtEntry. /// /// If the CPU tries to invoke a missing interrupt, it will instead /// send a General Protection fault (13), with the interrupt number and /// some other data stored in the error code. - pub const fn missing() -> IdtEntry { - IdtEntry { - base_lo: 0, - sel: 0, - res0: 0, - flags: 0, - base_hi: 0, - res1: 0, - } - } + pub const MISSING: IdtEntry = IdtEntry { + base_lo: 0, + selector: 0, + reserved0: 0, + flags: Flags::BLANK, + base_hi: 0, + reserved1: 0, + }; - /// Create a new IdtEntry pointing at `handler`, which must be a - /// function with interrupt calling conventions. (This must be - /// currently defined in assembly language.) The `gdt_code_selector` - /// value must be the offset of code segment entry in the GDT. + /// Create a new IdtEntry pointing at `handler`, which must be a function + /// with interrupt calling conventions. (This must be currently defined in + /// assembly language.) The `gdt_code_selector` value must be the offset of + /// code segment entry in the GDT. /// - /// Create an interrupt gate with the "Present" flag set, which is the - /// most common case. If you need something else, you can construct it - /// manually. - pub const fn interrupt_gate(gdt_code_selector: u16, handler: VAddr) -> IdtEntry { + /// The "Present" flag set, which is the most common case. If you need + /// something else, you can construct it manually. + pub const fn new(handler: VAddr, gdt_code_selector: u16, + dpl: PrivilegeLevel, block: bool) -> IdtEntry { IdtEntry { base_lo: ((handler.as_usize() as u64) & 0xFFFF) as u16, - sel: gdt_code_selector, - res0: 0, - // Bit 7: "Present" flag set. - // Bits 0-4: This is an interrupt gate. - flags: 0b1000_1110, base_hi: handler.as_usize() as u64 >> 16, - res1: 0, + selector: gdt_code_selector, + reserved0: 0, + // Nice bitflags operations don't work in const fn, hence these + // ad-hoc methods. + flags: Flags::from_priv(dpl) + .const_or(FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE + .const_mux(FLAGS_TYPE_SYS_NATIVE_TRAP_GATE, + block)) + .const_or(FLAGS_PRESENT), + reserved1: 0, } } } diff --git a/src/bits64/paging.rs b/src/bits64/paging.rs index cc519b2..47ac8ed 100644 --- a/src/bits64/paging.rs +++ b/src/bits64/paging.rs @@ -1,14 +1,13 @@ //! Description of the data-structures for IA-32e paging mode. + use core::fmt; +use shared::paging::*; + /// Represents a physical memory address #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] pub struct PAddr(u64); -/// Represent a virtual (linear) memory address -#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct VAddr(usize); - impl PAddr { /// Convert to `u64` pub const fn as_u64(&self) -> u64 { @@ -20,17 +19,6 @@ impl PAddr { } } -impl VAddr { - /// Convert to `usize` - pub const fn as_usize(&self) -> usize { - self.0 - } - /// Convert from `usize` - pub const fn from_usize(v: usize) -> Self { - VAddr(v) - } -} - impl fmt::Binary for PAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) @@ -61,36 +49,6 @@ impl fmt::UpperHex for PAddr { } } -impl fmt::Binary for VAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -impl fmt::Display for VAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -impl fmt::LowerHex for VAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -impl fmt::Octal for VAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - -impl fmt::UpperHex for VAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.0.fmt(f) - } -} - pub const BASE_PAGE_SIZE: u64 = 4096; // 4 KiB pub const LARGE_PAGE_SIZE: u64 = 1024 * 1024 * 2; // 2 MiB pub const HUGE_PAGE_SIZE: u64 = 1024 * 1024 * 1024; // 1 GiB diff --git a/src/shared/descriptor.rs b/src/shared/descriptor.rs new file mode 100644 index 0000000..201d8cc --- /dev/null +++ b/src/shared/descriptor.rs @@ -0,0 +1,109 @@ +//! Fields which are common to all segment-section and gate descriptors + +use shared::PrivilegeLevel; + +/// 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. +pub enum Type { + SystemDescriptor { + /// false/0: 16-bit + /// true/1: native (32- or 64-bit) + size: bool, + ty: SystemType + }, +} + +impl Type { + pub fn pack(self) -> u8 { + match self { + Type::SystemDescriptor { size, ty } => + (size as u8) << 3 | (ty as u8) | 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, + + // 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, + } +} + +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)) + } +} diff --git a/src/shared/irq.rs b/src/shared/irq.rs new file mode 100644 index 0000000..4654ad3 --- /dev/null +++ b/src/shared/irq.rs @@ -0,0 +1,207 @@ +//! Shared interrupt description and set-up code. +//! See the `bits*::irq` modules for arch-specific portions. + +use core::fmt; + +/// x86 Exception description (see also Intel Vol. 3a Chapter 6). +#[derive(Debug)] +pub struct InterruptDescription { + pub vector: u8, + pub mnemonic: &'static str, + pub description: &'static str, + pub irqtype: &'static str, + pub source: &'static str, +} + +impl fmt::Display for InterruptDescription { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, + "{} ({}, vec={}) {}", + self.mnemonic, + self.irqtype, + self.vector, + self.description) + } +} + + +/// x86 External Interrupts (1-16). +pub static EXCEPTIONS: [InterruptDescription; 21] = [ + InterruptDescription { + vector: 0, + mnemonic: "#DE", + description: "Divide Error", + irqtype: "Fault", + source: "DIV and IDIV instructions.", + }, + InterruptDescription { + vector: 1, + mnemonic: "#DB", + description: "Debug", + irqtype: "Fault/ Trap", + source: "Debug condition", + }, + InterruptDescription { + vector: 2, + mnemonic: "NMI", + description: "Nonmaskable Interrupt", + irqtype: "Interrupt", + source: "Nonmaskable external interrupt.", + }, + InterruptDescription { + vector: 3, + mnemonic: "#BP", + description: "Breakpoint", + irqtype: "Trap", + source: "INT 3 instruction.", + }, + InterruptDescription { + vector: 4, + mnemonic: "#OF", + description: "Overflow", + irqtype: "Trap", + source: "INTO instruction.", + }, + InterruptDescription { + vector: 5, + mnemonic: "#BR", + description: "BOUND Range Exceeded", + irqtype: "Fault", + source: "BOUND instruction.", + }, + InterruptDescription { + vector: 6, + mnemonic: "#UD", + description: "Invalid Opcode (Undefined \ + Opcode)", + irqtype: "Fault", + source: "UD2 instruction or reserved \ + opcode.", + }, + InterruptDescription { + vector: 7, + mnemonic: "#NM", + description: "Device Not Available (No \ + Math Coprocessor)", + irqtype: "Fault", + source: "Floating-point or WAIT/FWAIT \ + instruction.", + }, + InterruptDescription { + vector: 8, + mnemonic: "#DF", + description: "Double Fault", + irqtype: "Abort", + source: "Any instruction that can \ + generate an exception, an NMI, \ + or an INTR.", + }, + InterruptDescription { + vector: 9, + mnemonic: "", + description: "Coprocessor Segment Overrun", + irqtype: "Fault", + source: "Floating-point instruction.", + }, + InterruptDescription { + vector: 10, + mnemonic: "#TS", + description: "Invalid TSS", + irqtype: "Fault", + source: "Task switch or TSS access.", + }, + InterruptDescription { + vector: 11, + mnemonic: "#NP", + description: "Segment Not Present", + irqtype: "Fault", + source: "Loading segment registers or \ + accessing system segments.", + }, + InterruptDescription { + vector: 12, + mnemonic: "#SS", + description: "Stack-Segment Fault", + irqtype: "Fault", + source: "Stack operations and SS register \ + loads.", + }, + InterruptDescription { + vector: 13, + mnemonic: "#GP", + description: "General Protection", + irqtype: "Fault", + source: "Any memory reference and other \ + protection checks.", + }, + InterruptDescription { + vector: 14, + mnemonic: "#PF", + description: "Page Fault", + irqtype: "Fault", + source: "Any memory reference.", + }, + InterruptDescription { + vector: 15, + mnemonic: "", + description: "RESERVED", + irqtype: "", + source: "None.", + }, + InterruptDescription { + vector: 16, + mnemonic: "#MF", + description: "x87 FPU Floating-Point", + irqtype: "Fault", + source: "x87 FPU instructions.", + }, + InterruptDescription { + vector: 17, + mnemonic: "#AC", + description: "Alignment Check", + irqtype: "Fault", + source: "Unaligned memory access.", + }, + InterruptDescription { + vector: 18, + mnemonic: "#MC", + description: "Machine Check", + irqtype: "Abort", + source: "Internal machine error.", + }, + InterruptDescription { + vector: 19, + mnemonic: "#XM", + description: "SIMD Floating-Point", + irqtype: "Fault", + source: "SSE SIMD instructions.", + }, + InterruptDescription { + vector: 20, + mnemonic: "#VE", + description: "Virtualization", + irqtype: "Fault", + source: "EPT violation.", + }, +]; + +/// Enable Interrupts. +pub unsafe fn enable() { + asm!("sti"); +} + +/// Disable Interrupts. +pub unsafe fn disable() { + asm!("cli"); +} + +/// Generate a software interrupt. +/// This is a macro argument needs to be an immediate. +#[macro_export] +macro_rules! int { + ( $x:expr ) => { + { + asm!("int $0" :: "N" ($x)); + } + }; +} diff --git a/src/shared/mod.rs b/src/shared/mod.rs index ad1d23c..a461c08 100644 --- a/src/shared/mod.rs +++ b/src/shared/mod.rs @@ -1,7 +1,10 @@ #![allow(non_upper_case_globals)] pub mod control_regs; +pub mod descriptor; pub mod io; +pub mod irq; +pub mod paging; bitflags! { pub flags Flags: usize { @@ -92,61 +95,6 @@ bitflags!( ); #[derive(Copy, Clone, PartialEq, Eq)] -pub enum Exception { - DivisionByZero = 0, - Debug = 1, - Nmi = 2, - Breakpoint = 3, - Overflow = 4, - Bounds = 5, - InvalidOpcode = 6, - NotAvailable = 7, - DoubleFault = 8, - CoprocessorSegment = 9, - Tss = 10, - NotPresent = 11, - StackSegment = 12, - GeneralProtection = 13, - PageFault = 14, - Fpu = 16, - Alignment = 17, - MachineCheck = 18, - Simd = 19, - Virtualization = 20, - Security = 30 -} - -impl Exception { - pub fn from_code(code: u32) -> Option<Exception> { - Some(match code { - 0 => Exception::DivisionByZero, - 1 => Exception::Debug, - 2 => Exception::Nmi, - 3 => Exception::Breakpoint, - 4 => Exception::Overflow, - 5 => Exception::Bounds, - 6 => Exception::InvalidOpcode, - 7 => Exception::NotAvailable, - 8 => Exception::DoubleFault, - 9 => Exception::CoprocessorSegment, - 10 => Exception::Tss, - 11 => Exception::NotPresent, - 12 => Exception::StackSegment, - 13 => Exception::GeneralProtection, - 14 => Exception::PageFault, - 16 => Exception::Fpu, - 17 => Exception::Alignment, - 18 => Exception::MachineCheck, - 19 => Exception::Simd, - 20 => Exception::Virtualization, - 30 => Exception::Security, - - _ => return None - }) - } -} - -#[derive(Copy, Clone, PartialEq, Eq)] pub enum Msr { ApicBase = 0x1B } @@ -176,6 +124,7 @@ pub unsafe fn read_msr(msr: Msr) -> u64 { } #[derive(Copy, Clone, PartialEq, Eq)] +#[repr(u8)] pub enum PrivilegeLevel { Ring0 = 0, Ring1 = 1, @@ -241,16 +190,6 @@ pub unsafe fn set_cs(selector: SegmentSelector) { } #[inline(always)] -pub unsafe fn enable_interrupts() { - asm!("sti" :::: "volatile", "intel"); -} - -#[inline(always)] -pub unsafe fn disable_interrupts() { - asm!("cli" :::: "volatile", "intel"); -} - -#[inline(always)] pub unsafe fn halt() { asm!("hlt" :::: "volatile", "intel"); } diff --git a/src/shared/paging.rs b/src/shared/paging.rs new file mode 100644 index 0000000..41705a9 --- /dev/null +++ b/src/shared/paging.rs @@ -0,0 +1,48 @@ +//! Description of the data-structures for IA-32e paging mode. + +use core::fmt; + +/// Represent a virtual (linear) memory address +#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct VAddr(usize); + +impl VAddr { + /// Convert to `usize` + pub const fn as_usize(&self) -> usize { + self.0 + } + /// Convert from `usize` + pub const fn from_usize(v: usize) -> Self { + VAddr(v) + } +} + +impl fmt::Binary for VAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::Display for VAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::LowerHex for VAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::Octal for VAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::UpperHex for VAddr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.0.fmt(f) + } +} |