Skip to content

Commit

Permalink
feat(x86_64): make raw IDT methods public (#487)
Browse files Browse the repository at this point in the history
MnemOS would like us to provide lower-level access to the IDT in
`hal-x86_64` so that they can work around the nice, high level
abstractions we worked so hard to provide for them (see
tosc-rs/mnemos#337). This PR capitulates to mnemOS' demands by making
the IDT methods for registering raw ISR functions public. I hope mnemOS
doesn't shoot themselves in the foot using this :)
  • Loading branch information
hawkw authored Oct 8, 2024
1 parent 73ba776 commit ba56bb4
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 24 deletions.
28 changes: 14 additions & 14 deletions hal-x86_64/src/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ impl hal_core::interrupt::Control for Idt {
($self:ident, $h:ty, $($vector:path => fn $name:ident($($rest:tt)+),)+) => {
$(
gen_code_faults! {@ $name($($rest)+); }
$self.set_isr($vector, $name::<$h> as *const ());
$self.register_isr($vector, $name::<$h> as *const ());
)+
};
(@ $name:ident($kind:literal);) => {
Expand Down Expand Up @@ -575,32 +575,32 @@ impl hal_core::interrupt::Control for Idt {
}

// other exceptions, not mapped to the "code fault" handler
self.set_isr(Self::PAGE_FAULT, page_fault_isr::<H> as *const ());
self.set_isr(Self::INVALID_TSS, invalid_tss_isr::<H> as *const ());
self.set_isr(
self.register_isr(Self::PAGE_FAULT, page_fault_isr::<H> as *const ());
self.register_isr(Self::INVALID_TSS, invalid_tss_isr::<H> as *const ());
self.register_isr(
Self::SEGMENT_NOT_PRESENT,
segment_not_present_isr::<H> as *const (),
);
self.set_isr(
self.register_isr(
Self::STACK_SEGMENT_FAULT,
stack_segment_isr::<H> as *const (),
);
self.set_isr(Self::GENERAL_PROTECTION_FAULT, gpf_isr::<H> as *const ());
self.set_isr(Self::DOUBLE_FAULT, double_fault_isr::<H> as *const ());
self.register_isr(Self::GENERAL_PROTECTION_FAULT, gpf_isr::<H> as *const ());
self.register_isr(Self::DOUBLE_FAULT, double_fault_isr::<H> as *const ());

// === hardware interrupts ===
// ISA standard hardware interrupts mapped on both the PICs and IO APIC
// interrupt models.
self.set_isr(Self::PIC_PIT_TIMER, pit_timer_isr::<H> as *const ());
self.set_isr(Self::IOAPIC_PIT_TIMER, pit_timer_isr::<H> as *const ());
self.set_isr(Self::PIC_PS2_KEYBOARD, keyboard_isr::<H> as *const ());
self.set_isr(Self::IOAPIC_PS2_KEYBOARD, keyboard_isr::<H> as *const ());
self.register_isr(Self::PIC_PIT_TIMER, pit_timer_isr::<H> as *const ());
self.register_isr(Self::IOAPIC_PIT_TIMER, pit_timer_isr::<H> as *const ());
self.register_isr(Self::PIC_PS2_KEYBOARD, keyboard_isr::<H> as *const ());
self.register_isr(Self::IOAPIC_PS2_KEYBOARD, keyboard_isr::<H> as *const ());
// local APIC specific hardware itnerrupts
self.set_isr(Self::LOCAL_APIC_SPURIOUS, spurious_isr as *const ());
self.set_isr(Self::LOCAL_APIC_TIMER, apic_timer_isr::<H> as *const ());
self.register_isr(Self::LOCAL_APIC_SPURIOUS, spurious_isr as *const ());
self.register_isr(Self::LOCAL_APIC_TIMER, apic_timer_isr::<H> as *const ());

// vector 69 (nice) is reserved by the HAL for testing the IDT.
self.set_isr(69, test_isr::<H> as *const ());
self.register_isr(69, test_isr::<H> as *const ());

Ok(())
}
Expand Down
89 changes: 79 additions & 10 deletions hal-x86_64/src/interrupt/idt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl bits::FromBits<u8> for GateKind {
// === impl Idt ===

impl Idt {
pub(super) const NUM_VECTORS: usize = 256;
pub const NUM_VECTORS: usize = 256;

/// Divide-by-zero interrupt (#D0)
pub const DIVIDE_BY_ZERO: usize = 0;
Expand Down Expand Up @@ -155,26 +155,95 @@ impl Idt {
/// Chosen by fair die roll, guaranteed to be random.
pub const DOUBLE_FAULT_IST_OFFSET: usize = 4;

/// PIC Programmable Interval Timer (PIT) interrupt vector mapped by
/// [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the PICs may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const PIC_PIT_TIMER: usize = Self::PIC_BIG_START;

/// PIC PS/2 interrupt vector mapped by
/// [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the PICs may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const PIC_PS2_KEYBOARD: usize = Self::PIC_BIG_START + 1;

pub(super) const LOCAL_APIC_TIMER: usize = (Self::NUM_VECTORS - 2);
pub(super) const LOCAL_APIC_SPURIOUS: usize = (Self::NUM_VECTORS - 1);
pub(super) const PIC_BIG_START: usize = 0x20;
pub(super) const PIC_LITTLE_START: usize = 0x28;
/// Local APIC timer interrupt vector mapped by
/// [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the local APIC may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const LOCAL_APIC_TIMER: usize = (Self::NUM_VECTORS - 2);

/// Local APIC spurious interrupt vector mapped by
/// [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the local APIC may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const LOCAL_APIC_SPURIOUS: usize = (Self::NUM_VECTORS - 1);

/// Base of the primary PIC's interrupt vector region mapped by
/// [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the PICs may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const PIC_BIG_START: usize = 0x20;

/// Base of the secondary PIC's interrupt vector region mapped by
/// [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the PICs may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const PIC_LITTLE_START: usize = 0x28;
// put the IOAPIC right after the PICs
pub(super) const IOAPIC_START: usize = 0x30;
pub(super) const IOAPIC_PIT_TIMER: usize = Self::IOAPIC_START + IoApic::PIT_TIMER_IRQ as usize;
pub(super) const IOAPIC_PS2_KEYBOARD: usize =
Self::IOAPIC_START + IoApic::PS2_KEYBOARD_IRQ as usize;

/// Base of the IOAPIC's interrupt vector region mapped by
/// [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the IOAPIC may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const IOAPIC_START: usize = 0x30;

/// IOAPIC Programmable Interval Timer (PIT) interrupt vector region mapped
/// by [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the IOAPIC may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const IOAPIC_PIT_TIMER: usize = Self::IOAPIC_START + IoApic::PIT_TIMER_IRQ as usize;

/// IOAPIC PS/2 keyboard interrupt vector mapped by
/// [`Controller::enable_hardware_interrupts`].
///
/// Systems which do not use that function to initialize the IOAPIC may
/// map this interrupt to a different IDT vector.
///
/// [`Controller::enable_hardware_interrupts`]: super::Controller::enable_hardware_interrupts
pub const IOAPIC_PS2_KEYBOARD: usize = Self::IOAPIC_START + IoApic::PS2_KEYBOARD_IRQ as usize;

pub const fn new() -> Self {
Self {
descriptors: [Descriptor::null(); Self::NUM_VECTORS],
}
}

pub(super) fn set_isr(&mut self, vector: usize, isr: *const ()) {
pub fn register_isr(&mut self, vector: usize, isr: *const ()) {
let descr = self.descriptors[vector].set_handler(isr);
if vector == Self::DOUBLE_FAULT {
descr.set_ist_offset(Self::DOUBLE_FAULT_IST_OFFSET as u8);
Expand Down

0 comments on commit ba56bb4

Please sign in to comment.