2023-05-06 06:50:24 -05:00
|
|
|
use {
|
2024-09-16 14:15:51 -05:00
|
|
|
core::mem::MaybeUninit,
|
2023-05-26 06:30:17 -05:00
|
|
|
log::trace,
|
2023-05-06 06:50:24 -05:00
|
|
|
x2apic::lapic::{LocalApic, LocalApicBuilder},
|
|
|
|
x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
|
|
|
};
|
|
|
|
|
2024-09-16 14:15:51 -05:00
|
|
|
/// Safety: Using LAPIC or IDT before init() is UB
|
|
|
|
/// Using
|
|
|
|
static mut LAPIC: LocalApic = unsafe { MaybeUninit::zeroed().assume_init() };
|
|
|
|
static mut IDT: InterruptDescriptorTable = unsafe { MaybeUninit::zeroed().assume_init() };
|
2023-03-30 16:43:04 -05:00
|
|
|
|
|
|
|
#[repr(u8)]
|
|
|
|
enum Interrupt {
|
|
|
|
Timer = 32,
|
|
|
|
ApicErr = u8::MAX - 1,
|
|
|
|
Spurious = u8::MAX,
|
|
|
|
}
|
|
|
|
|
2024-09-16 14:15:51 -05:00
|
|
|
pub unsafe fn init() {
|
|
|
|
trace!("Initializing IDT and LAPIC");
|
|
|
|
|
|
|
|
// Initialize and load the IDT
|
|
|
|
IDT = InterruptDescriptorTable::new();
|
|
|
|
IDT.double_fault
|
|
|
|
.set_handler_fn(double_fault)
|
|
|
|
.set_stack_index(super::gdt::DOUBLE_FAULT_IX);
|
|
|
|
IDT.page_fault.set_handler_fn(page_fault);
|
|
|
|
|
|
|
|
IDT[Interrupt::ApicErr as u8].set_handler_fn(apic_err);
|
|
|
|
IDT[Interrupt::Spurious as u8].set_handler_fn(spurious);
|
|
|
|
IDT[Interrupt::Timer as u8].set_handler_fn(timer);
|
|
|
|
|
|
|
|
IDT.load();
|
|
|
|
|
|
|
|
LAPIC = LocalApicBuilder::new()
|
2023-03-30 16:43:04 -05:00
|
|
|
.timer_vector(Interrupt::Timer as usize)
|
|
|
|
.error_vector(Interrupt::ApicErr as usize)
|
|
|
|
.spurious_vector(Interrupt::Spurious as usize)
|
|
|
|
.set_xapic_base(
|
2024-09-16 14:15:51 -05:00
|
|
|
x2apic::lapic::xapic_base()
|
2023-03-30 16:43:04 -05:00
|
|
|
+ super::memory::HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed),
|
|
|
|
)
|
|
|
|
.build()
|
2024-09-16 14:15:51 -05:00
|
|
|
.expect("Failed to setup Local APIC");
|
|
|
|
LAPIC.enable();
|
2023-03-30 16:43:04 -05:00
|
|
|
|
2024-09-16 14:15:51 -05:00
|
|
|
x86_64::instructions::interrupts::enable();
|
|
|
|
}
|
2023-03-30 16:43:04 -05:00
|
|
|
|
|
|
|
extern "x86-interrupt" fn double_fault(stack_frame: InterruptStackFrame, error_code: u64) -> ! {
|
|
|
|
panic!("Double fault: error code {error_code} \n{stack_frame:#?}")
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "x86-interrupt" fn page_fault(
|
|
|
|
stack_frame: InterruptStackFrame,
|
|
|
|
error_code: PageFaultErrorCode,
|
|
|
|
) {
|
|
|
|
panic!("Page fault ({error_code:?}): {stack_frame:?}")
|
|
|
|
}
|
|
|
|
|
2023-05-23 05:16:14 -05:00
|
|
|
extern "x86-interrupt" fn timer(_isf: InterruptStackFrame) {
|
2024-09-16 14:15:51 -05:00
|
|
|
unsafe {
|
|
|
|
LAPIC.end_of_interrupt();
|
|
|
|
}
|
2023-03-30 16:43:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
|
|
|
|
panic!("Internal APIC error");
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
|
2024-09-16 14:15:51 -05:00
|
|
|
unsafe {
|
|
|
|
LAPIC.end_of_interrupt();
|
|
|
|
}
|
2023-03-30 16:43:04 -05:00
|
|
|
}
|