From 135beae68594ddcf82dc9704fc076e9839869115 Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Sat, 21 Oct 2017 18:11:10 +0200 Subject: Update IdtEntry to the actual descriptor in Intel 3a, Figure 6-7 (including ist_index). Additionally, replace the boolean "block" by a more straightforward "ty" parameter with custom type. Due to the custom type and assert!, we cannot keep this a "const fn", but I think code correctness outweighs this. --- src/bits64/irq.rs | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/bits64/irq.rs b/src/bits64/irq.rs index 84ee0e6..0f8f9ce 100644 --- a/src/bits64/irq.rs +++ b/src/bits64/irq.rs @@ -2,6 +2,7 @@ use core::fmt; +use bits64::segmentation::SegmentSelector; use shared::descriptor::*; use shared::paging::VAddr; use shared::PrivilegeLevel; @@ -9,16 +10,16 @@ use shared::PrivilegeLevel; /// 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". +/// IDT" and "Figure 6-7. 64-Bit IDT Gate Descriptors". #[derive(Debug, Clone, Copy)] #[repr(C, packed)] pub struct IdtEntry { /// Lower 16 bits of ISR. pub base_lo: u16, /// Segment selector. - pub selector: u16, + pub selector: SegmentSelector, /// This must always be zero. - pub reserved0: u8, + pub ist_index: u8, /// Flags. pub flags: Flags, /// The upper 48 bits of ISR (the last 16 bits must be zero). @@ -27,6 +28,20 @@ pub struct IdtEntry { pub reserved1: u16, } +pub enum Type { + InterruptGate, + TrapGate, +} + +impl Type { + pub fn pack(self) -> Flags { + match self { + Type::InterruptGate => FLAGS_TYPE_SYS_NATIVE_INTERRUPT_GATE, + Type::TrapGate => FLAGS_TYPE_SYS_NATIVE_TRAP_GATE, + } + } +} + impl IdtEntry { /// A "missing" IdtEntry. /// @@ -35,8 +50,8 @@ impl IdtEntry { /// some other data stored in the error code. pub const MISSING: IdtEntry = IdtEntry { base_lo: 0, - selector: 0, - reserved0: 0, + selector: SegmentSelector::from_raw(0), + ist_index: 0, flags: Flags::BLANK, base_hi: 0, reserved1: 0, @@ -49,20 +64,17 @@ impl 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 { + pub fn new(handler: VAddr, gdt_code_selector: SegmentSelector, + dpl: PrivilegeLevel, ty: Type, ist_index: u8) -> IdtEntry { + assert!(ist_index < 0b1000); IdtEntry { base_lo: ((handler.as_usize() as u64) & 0xFFFF) as u16, base_hi: handler.as_usize() as u64 >> 16, selector: gdt_code_selector, - reserved0: 0, - // Nice bitflags operations don't work in const fn, hence these - // ad-hoc methods. + ist_index: ist_index, 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), + | ty.pack() + | FLAGS_PRESENT, reserved1: 0, } } -- cgit v1.2.3 From 07b527e510ced52960a5051368828822f1672a0c Mon Sep 17 00:00:00 2001 From: Colin Finck Date: Tue, 14 Nov 2017 09:04:36 +0100 Subject: Fix return value for 32-bit version of new_tss. Thanks to @robert-w-gries for noticing! --- src/bits32/segmentation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/bits32/segmentation.rs b/src/bits32/segmentation.rs index 6fbe5f0..31547b0 100644 --- a/src/bits32/segmentation.rs +++ b/src/bits32/segmentation.rs @@ -28,7 +28,7 @@ impl SegmentDescriptor { seg } - pub fn new_tss(tss: &TaskStateSegment, dpl: PrivilegeLevel) -> [SegmentDescriptor; 2] { + pub fn new_tss(tss: &TaskStateSegment, dpl: PrivilegeLevel) -> SegmentDescriptor { let tss_ptr = tss as *const TaskStateSegment; let ty1 = descriptor::Type::SystemDescriptor { size: true, -- cgit v1.2.3