#![allow(unused)]
use core::arch::global_asm;
use bitfield_struct::bitfield;
use super::super::gdt::GDT;
use super::Vector;
use crate::arch::int::idt::*;
use crate::arch::regs::Cr2;
use crate::util::Once;
static IDT: Once<InterruptDescriptorTable> = Once::new();
pub fn load() {
IDT.get_or_init(|| {
let mut idt = InterruptDescriptorTable::new();
idt.double_fault.set_handler_fn(double_fault);
idt.general_protection_fault
.set_handler_fn(general_protection_fault);
idt.page_fault.set_handler_fn(page_fault);
idt.invalid_tss.set_handler_fn(invalid_tss);
idt[Vector::Panic as usize].set_handler_fn(panic);
idt
})
.activate();
}
extern "x86-interrupt" fn double_fault(stack: InterruptStack, error: u32) -> ! {
panic!("DOUBLE FAULT {error:x}\n{:#x?}", stack);
}
extern "x86-interrupt" fn invalid_tss(stack: InterruptStack, error: u32) {
panic!("TSS {error:x}\n{:#x?}", stack);
}
#[bitfield(u32)]
struct SelectorError {
external: bool,
#[bits(2)]
table: u8,
#[bits(13)]
index: usize,
#[bits(16)]
__: (),
}
extern "x86-interrupt" fn general_protection_fault(stack: InterruptStack, error: u32) {
unsafe {
serial!("GDT: {:x?}", GDT.0.map(u64::from));
}
panic!(
"GENERAL PROTECTION FAULT {:?}\n{stack:#x?}",
SelectorError(error),
);
}
extern "x86-interrupt" fn page_fault(stack: InterruptStack, error: PageFaultError) {
let vaddr = Cr2::read().0 as *mut u8;
panic!("PAGE FAULT {error:?} at {vaddr:?} @ {stack:#x?}");
}
extern "x86-interrupt" fn panic(stack: InterruptStack) {
panic!("PANIC\n{:#?}", stack);
}
extern "x86-interrupt" fn timer(_stack: InterruptStack) {
todo!("BSB A5")
}
extern "x86-interrupt" fn keyboard(_stack: InterruptStack) {
todo!("BSB A2")
}
extern "x86-interrupt" fn assassin(_stack: InterruptStack) {
todo!("BSB A5")
}
extern "x86-interrupt" fn wake_up(_stack: InterruptStack) {
todo!("BSB A6")
}
#[derive(Debug)]
pub struct InterruptContext {
pub eax: usize,
pub ecx: usize,
pub edx: usize,
pub ebx: usize,
pub edi: usize,
pub stack: InterruptStack,
}
extern "x86-interrupt" {
pub fn syscall_trampoline(stack: InterruptStack);
}
global_asm!(
".align 4
.globl {trampoline}
{trampoline}:
call {handler}
iretd", trampoline = sym syscall_trampoline,
handler = sym syscall,
);
#[no_mangle]
pub extern "C" fn syscall(_context: &mut InterruptContext) {
todo!("BST B1 - Implement syscalls")
}