#include "interrupt/interrupt.h" #include #include "debug/debug.h" #define IDT_INTERRUPT_GATE 0x8E #define KERNEL_CS 0x8 struct InterruptDescriptorTablePointer { uint16_t size; uint64_t base; } __attribute__((packed)); struct InterruptDescriptor { uint16_t offset_low; uint16_t selector; uint8_t ist; uint8_t flags; uint16_t offset_medium; uint32_t offset_high; uint32_t zero; } __attribute__((packed)); static InterruptDescriptor gIdt[256]; InterruptDescriptor CreateDescriptor(void isr(void)) { uint64_t offset = reinterpret_cast(isr); return InterruptDescriptor{ .offset_low = static_cast(offset), .selector = KERNEL_CS, .ist = 0, .flags = IDT_INTERRUPT_GATE, .offset_medium = static_cast(offset >> 16), .offset_high = static_cast(offset >> 32), .zero = 0x0, }; } struct InterruptFrame { uint64_t rax; uint64_t rbx; uint64_t rcx; uint64_t rdx; uint64_t rsi; uint64_t rdi; uint64_t r8; uint64_t r9; uint64_t r10; uint64_t r11; uint64_t r12; uint64_t r13; uint64_t r14; uint64_t r15; uint64_t rbp; uint64_t error_code; uint64_t rip; uint64_t cs; uint64_t eflags; uint64_t rsp; uint64_t ss; }; extern "C" void isr_divide_by_zero(); extern "C" void interrupt_divide_by_zero(void* frame) { panic("DIV0"); } extern "C" void isr_protection_fault(); extern "C" void interrupt_protection_fault(void* frame) { panic("GP"); } extern "C" void isr_page_fault(); extern "C" void interrupt_page_fault(InterruptFrame* frame) { dbgln("Page Fault:"); uint64_t err = frame->error_code; if (err & 0x1) { dbgln("Page Protection"); } else { dbgln("Page Not Present"); } if (err & 0x2) { dbgln("Write"); } else { dbgln("Read"); } if (err & 0x8) { dbgln("Instruction Fetch"); } uint64_t cr2; asm volatile("mov %%cr2, %0" : "=r"(cr2)); dbgln("rip: %m", frame->rip); dbgln("addr: %m", cr2); panic("PF"); } void InitIdt() { gIdt[0] = CreateDescriptor(isr_divide_by_zero); gIdt[13] = CreateDescriptor(isr_protection_fault); gIdt[14] = CreateDescriptor(isr_page_fault); InterruptDescriptorTablePointer idtp{ .size = sizeof(gIdt), .base = reinterpret_cast(gIdt), }; asm volatile("lidt %0" ::"m"(idtp)); }