aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bits32/irq.rs57
-rw-r--r--src/bits32/mod.rs40
-rw-r--r--src/bits64/irq.rs273
-rw-r--r--src/bits64/paging.rs48
-rw-r--r--src/shared/descriptor.rs109
-rw-r--r--src/shared/irq.rs207
-rw-r--r--src/shared/mod.rs69
-rw-r--r--src/shared/paging.rs48
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)
+ }
+}