ableos/kernel/src/arch/x86_64/interrupts.rs

70 lines
2 KiB
Rust
Raw Normal View History

2023-03-30 16:43:04 -05:00
use spin::{Lazy, Mutex};
use x2apic::lapic::{LocalApic, LocalApicBuilder};
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
2023-04-07 16:44:33 -05:00
use crate::interp::wasm;
2023-03-30 16:43:04 -05:00
pub unsafe fn init() {
log::info!("Initialising IDT");
IDT.load();
Lazy::force(&LAPIC);
x86_64::instructions::interrupts::enable();
}
#[repr(u8)]
enum Interrupt {
Timer = 32,
ApicErr = u8::MAX - 1,
Spurious = u8::MAX,
}
2023-04-07 16:44:33 -05:00
pub(crate) static LAPIC: Lazy<Mutex<LocalApic>> = Lazy::new(|| {
2023-03-30 16:43:04 -05:00
let mut lapic = LocalApicBuilder::new()
.timer_vector(Interrupt::Timer as usize)
.error_vector(Interrupt::ApicErr as usize)
.spurious_vector(Interrupt::Spurious as usize)
.set_xapic_base(
unsafe { x2apic::lapic::xapic_base() }
+ super::memory::HHDM_OFFSET.load(core::sync::atomic::Ordering::Relaxed),
)
.build()
.expect("failed to setup Local APIC");
unsafe { lapic.enable() };
Mutex::new(lapic)
});
static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
let mut idt = InterruptDescriptorTable::new();
unsafe {
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::Timer as usize].set_handler_fn(timer);
idt
});
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-04-07 16:44:33 -05:00
extern "x86-interrupt" fn timer(isf: InterruptStackFrame) {
2023-03-30 16:43:04 -05:00
unsafe { LAPIC.lock().end_of_interrupt() };
}
extern "x86-interrupt" fn apic_err(_: InterruptStackFrame) {
panic!("Internal APIC error");
}
extern "x86-interrupt" fn spurious(_: InterruptStackFrame) {
unsafe { LAPIC.lock().end_of_interrupt() };
}