diff options
Diffstat (limited to 'src/bits32/irq.rs')
-rw-r--r-- | src/bits32/irq.rs | 57 |
1 files changed, 57 insertions, 0 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), + } + } +} |