#include #include #include #include #include #include union GateDescriptor { struct { uint16_t offset_lo; uint16_t selector; uint8_t reserved; uint8_t type : 4; uint8_t zero : 1; uint8_t dpl : 2; uint8_t present : 1; uint16_t offset_hi; }; struct { uint32_t low; uint32_t high; }; } __attribute__((packed)); struct IDTR { uint16_t size; void* offset; } __attribute((packed)); static IDTR s_idtr; static GateDescriptor s_idt[0x100]; static void (*s_irq_handlers[0xFF])() { nullptr }; #define INTERRUPT_HANDLER(i, msg) \ static void interrupt ## i () \ { \ uint32_t cr0, cr2, cr3, cr4; \ asm volatile("movl %%cr0, %%eax":"=a"(cr0)); \ asm volatile("movl %%cr2, %%eax":"=a"(cr2)); \ asm volatile("movl %%cr3, %%eax":"=a"(cr3)); \ asm volatile("movl %%cr4, %%eax":"=a"(cr4)); \ Kernel::panic(msg ", CR0={} CR2={} CR3={} CR4={}", cr0, cr2, cr3, cr4); \ } INTERRUPT_HANDLER(0x00, "Divide error") INTERRUPT_HANDLER(0x01, "Debug exception") INTERRUPT_HANDLER(0x02, "Unknown error") INTERRUPT_HANDLER(0x03, "Breakpoint") INTERRUPT_HANDLER(0x04, "Overflow") INTERRUPT_HANDLER(0x05, "Bounds check") INTERRUPT_HANDLER(0x06, "Invalid opcode") INTERRUPT_HANDLER(0x07, "Coprocessor not available") INTERRUPT_HANDLER(0x08, "Double fault") INTERRUPT_HANDLER(0x09, "Coprocessor segment overrun") INTERRUPT_HANDLER(0x0a, "Invalid TSS") INTERRUPT_HANDLER(0x0b, "Segment not present") INTERRUPT_HANDLER(0x0c, "Stack exception") INTERRUPT_HANDLER(0x0d, "General protection fault") INTERRUPT_HANDLER(0x0e, "Page fault") INTERRUPT_HANDLER(0x0f, "Unknown error") INTERRUPT_HANDLER(0x10, "Coprocessor error") #define REGISTER_HANDLER(i) register_interrupt_handler(i, interrupt ## i) void handle_irq() { uint16_t isr = PIC::get_isr(); if (!isr) { //kprint("Spurious IRQ\n"); return; } uint8_t irq = 0; for (uint8_t i = 0; i < 16; ++i) { if (i == 2) continue; if (isr & (1 << i)) { irq = i; break; } } if (s_irq_handlers[irq]) s_irq_handlers[irq](); else kprint("no handler for irq {}\n", irq); PIC::eoi(irq); } namespace IDT { static void flush_idt() { asm volatile("lidt %0"::"m"(s_idtr)); } static void unimplemented_trap() { Kernel::panic("Unhandeled IRQ"); } static void register_interrupt_handler(uint8_t index, void (*f)()) { s_idt[index].low = 0x00080000 | ((uint32_t)(f) & 0x0000ffff); s_idt[index].high = ((uint32_t)(f) & 0xffff0000) | 0x8e00; flush_idt(); } void register_irq_handler(uint8_t irq, void (*f)()) { s_irq_handlers[IRQ_VECTOR_BASE + irq] = f; register_interrupt_handler(IRQ_VECTOR_BASE + irq, handle_irq_common); } void initialize() { s_idtr.offset = s_idt; s_idtr.size = sizeof(s_idt); for (uint8_t i = 0xFF; i > IRQ_VECTOR_BASE; i--) register_irq_handler(i, nullptr); REGISTER_HANDLER(0x00); REGISTER_HANDLER(0x01); REGISTER_HANDLER(0x02); REGISTER_HANDLER(0x03); REGISTER_HANDLER(0x04); REGISTER_HANDLER(0x05); REGISTER_HANDLER(0x06); REGISTER_HANDLER(0x07); REGISTER_HANDLER(0x08); REGISTER_HANDLER(0x09); REGISTER_HANDLER(0x0A); REGISTER_HANDLER(0x0B); REGISTER_HANDLER(0x0C); REGISTER_HANDLER(0x0D); REGISTER_HANDLER(0x0E); REGISTER_HANDLER(0x0F); REGISTER_HANDLER(0x10); REGISTER_HANDLER(0x11); REGISTER_HANDLER(0x12); REGISTER_HANDLER(0x13); REGISTER_HANDLER(0x14); REGISTER_HANDLER(0x15); REGISTER_HANDLER(0x16); REGISTER_HANDLER(0x17); REGISTER_HANDLER(0x18); REGISTER_HANDLER(0x19); REGISTER_HANDLER(0x1A); REGISTER_HANDLER(0x1B); REGISTER_HANDLER(0x1C); REGISTER_HANDLER(0x1D); REGISTER_HANDLER(0x1E); REGISTER_HANDLER(0x1F); flush_idt(); } }