/* * This file deals with the Interrupt Descriptor Table. It creates a simple * IDT, with hard-coded handler functions. It is these handler functions that * can run custom handlers, registered at runtime. This file does not deal with * dispatching messages/signals to processes on an interrupt. */ #include #include #include #include #include #include #include "desc.h" /* Structure for an IDT Entry */ static struct IDTEntry { uint16_t offsetLower, selector; uint8_t zero, typeAttr; uint16_t offsetHigher; } __attribute__((packed)) *IDT; void (**exceptions)(struct InterruptFrame *, uint32_t); void (**interrupts)(struct InterruptFrame *); /* Install an IDT Entry */ static void install_idt_entry(uint8_t num, void *addr) { IDT[num].offsetLower = (uintptr_t) addr & 0xFFFF; IDT[num].selector = 0x08; IDT[num].zero = 0; IDT[num].typeAttr = 0x8E | 0x60; /* Allowed from ring 3 */ IDT[num].offsetHigher = (uintptr_t) addr >> 16; } /* First level generic exception handler */ static void exc_handler(int num, struct InterruptFrame *frame, uint32_t err) { asm volatile("cli"); if (!exceptions[num]) { panic("Failed to handle exception %d (%#.8x)", num, err); } ASSERT(exceptions[num]); exceptions[num](frame, err); /* Send APIC EOI */ LAPIC(0xB0) = 0; asm volatile("sti"); } /* First level generic interrupt handler */ static void int_handler(int num, struct InterruptFrame *frame) { asm volatile("cli"); if (interrupts[num - 32]) interrupts[num - 32](frame); /* Send EOI */ if (num >= 32 + 8) outb(0xA0, 0x20); outb(0x20, 0x20); /* Send APIC EOI*/ LAPIC(0xB0) = 0; asm volatile("sti"); } /* Exceptions */ __attribute__((interrupt)) static void exc0(struct InterruptFrame *frame) { exc_handler(0, frame, 0); } __attribute__((interrupt)) static void exc1(struct InterruptFrame *frame) { exc_handler(1, frame, 0); } __attribute__((interrupt)) static void exc2(struct InterruptFrame *frame) { exc_handler(2, frame, 0); } __attribute__((interrupt)) static void exc3(struct InterruptFrame *frame) { exc_handler(3, frame, 0); } __attribute__((interrupt)) static void exc4(struct InterruptFrame *frame) { exc_handler(4, frame, 0); } __attribute__((interrupt)) static void exc5(struct InterruptFrame *frame) { exc_handler(5, frame, 0); } __attribute__((interrupt)) static void exc6(struct InterruptFrame *frame) { exc_handler(6, frame, 0); } __attribute__((interrupt)) static void exc7(struct InterruptFrame *frame) { exc_handler(7, frame, 0); } __attribute__((interrupt)) static void exc8(struct InterruptFrame *frame, uint32_t err) { exc_handler(8, frame, err); } __attribute__((interrupt)) static void exc9(struct InterruptFrame *frame) { exc_handler(9, frame, 0); } __attribute__((interrupt)) static void exc10(struct InterruptFrame *frame, uint32_t err) { exc_handler(10, frame, err); } __attribute__((interrupt)) static void exc11(struct InterruptFrame *frame, uint32_t err) { exc_handler(11, frame, err); } __attribute__((interrupt)) static void exc12(struct InterruptFrame *frame, uint32_t err) { exc_handler(12, frame, err); } __attribute__((interrupt)) static void exc13(struct InterruptFrame *frame, uint32_t err) { exc_handler(13, frame, err); } __attribute__((interrupt)) static void exc14(struct InterruptFrame *frame, uint32_t err) { exc_handler(14, frame, err); } __attribute__((interrupt)) static void exc15(struct InterruptFrame *frame) { exc_handler(15, frame, 0); } __attribute__((interrupt)) static void exc16(struct InterruptFrame *frame) { exc_handler(16, frame, 0); } __attribute__((interrupt)) static void exc17(struct InterruptFrame *frame, uint32_t err) { exc_handler(17, frame, err); } __attribute__((interrupt)) static void exc18(struct InterruptFrame *frame) { exc_handler(18, frame, 0); } __attribute__((interrupt)) static void exc19(struct InterruptFrame *frame) { exc_handler(19, frame, 0); } __attribute__((interrupt)) static void exc20(struct InterruptFrame *frame) { exc_handler(20, frame, 0); } __attribute__((interrupt)) static void exc30(struct InterruptFrame *frame) { exc_handler(30, frame, 0); } __attribute__((interrupt)) static void exc128(struct InterruptFrame *frame) { exc_handler(128, frame, 0); } /* Interrupts */ __attribute__((interrupt)) static void int0(struct InterruptFrame *frame) { int_handler(32, frame); } __attribute__((interrupt)) static void int1(struct InterruptFrame *frame) { int_handler(33, frame); } __attribute__((interrupt)) static void int2(struct InterruptFrame *frame) { int_handler(34, frame); } __attribute__((interrupt)) static void int3(struct InterruptFrame *frame) { int_handler(35, frame); } __attribute__((interrupt)) static void int4(struct InterruptFrame *frame) { int_handler(36, frame); } __attribute__((interrupt)) static void int5(struct InterruptFrame *frame) { int_handler(37, frame); } __attribute__((interrupt)) static void int6(struct InterruptFrame *frame) { int_handler(38, frame); } __attribute__((interrupt)) static void int7(struct InterruptFrame *frame) { int_handler(39, frame); } __attribute__((interrupt)) static void int8(struct InterruptFrame *frame) { int_handler(40, frame); } __attribute__((interrupt)) static void int9(struct InterruptFrame *frame) { int_handler(41, frame); } __attribute__((interrupt)) static void int10(struct InterruptFrame *frame) { int_handler(42, frame); } __attribute__((interrupt)) static void int11(struct InterruptFrame *frame) { int_handler(43, frame); } __attribute__((interrupt)) static void int12(struct InterruptFrame *frame) { int_handler(44, frame); } __attribute__((interrupt)) static void int13(struct InterruptFrame *frame) { int_handler(45, frame); } __attribute__((interrupt)) static void int14(struct InterruptFrame *frame) { int_handler(46, frame); } __attribute__((interrupt)) static void int15(struct InterruptFrame *frame) { int_handler(47, frame); } /* Initialise the IDT */ void init_idt(void) { IDT = (void *) alloc_frame(); /* Install exceptions */ install_idt_entry(0, exc0); install_idt_entry(1, exc1); install_idt_entry(2, exc2); install_idt_entry(3, exc3); install_idt_entry(4, exc4); install_idt_entry(5, exc5); install_idt_entry(6, exc6); install_idt_entry(7, exc7); install_idt_entry(8, exc8); install_idt_entry(9, exc9); install_idt_entry(10, exc10); install_idt_entry(11, exc11); install_idt_entry(12, exc12); install_idt_entry(13, exc13); install_idt_entry(14, exc14); install_idt_entry(15, exc15); install_idt_entry(16, exc16); install_idt_entry(17, exc17); install_idt_entry(18, exc18); install_idt_entry(19, exc19); install_idt_entry(20, exc20); install_idt_entry(30, exc30); /* Install interrupts */ install_idt_entry(32, int0); install_idt_entry(33, int1); install_idt_entry(34, int2); install_idt_entry(35, int3); install_idt_entry(36, int4); install_idt_entry(37, int5); install_idt_entry(38, int6); install_idt_entry(39, int7); install_idt_entry(40, int8); install_idt_entry(41, int9); install_idt_entry(42, int10); install_idt_entry(43, int11); install_idt_entry(44, int12); install_idt_entry(45, int13); install_idt_entry(46, int14); install_idt_entry(47, int15); /* Install system call handler */ install_idt_entry(128, exc128); exceptions = (void *) (IDT + 256); interrupts = (void *) (exceptions + 32); memset(exceptions, 0, 1024); } /* Load the IDT */ void cpu_load_idt(void) { struct DescRecord ptr = { .limit = sizeof(struct IDTEntry) * 256, .base = (uintptr_t) IDT, }; asm volatile("lidt %0" :: "m" (ptr)); } /* Register an exception handler */ void register_exception(int num, exc_handler_t addr) { if (num >= 0 && num < 32) exceptions[num] = addr; } /* Register an interrupt handler */ void register_interrupt(int num, int_handler_t addr) { if (num >= 0 && num < 224) interrupts[num] = addr; }