forked from AbleOS/ableos
68 lines
2 KiB
Rust
68 lines
2 KiB
Rust
|
use spin::{Lazy, Mutex};
|
||
|
use x2apic::lapic::{LocalApic, LocalApicBuilder};
|
||
|
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
||
|
|
||
|
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,
|
||
|
}
|
||
|
|
||
|
static LAPIC: Lazy<Mutex<LocalApic>> = Lazy::new(|| {
|
||
|
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:?}")
|
||
|
}
|
||
|
|
||
|
extern "x86-interrupt" fn timer(_: InterruptStackFrame) {
|
||
|
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() };
|
||
|
}
|