#include #include #include #include "idt.h" #include "backtrace.h" #include "debugger.h" #include "../bindings.h" #include "../drivers/pic.h" #define IDT_SIZE 256 struct idt_entry { uint16_t isr_low; // low 16 bits of isr uint16_t kernel_cs; // kernel segment selector uint8_t ist; // interrupt stack table uint8_t flags; // gate type, privilege level, present bit uint16_t isr_mid; // middle 16 bits of isr uint32_t isr_high; // high 32 bits of isr uint32_t reserved; } __attribute__((packed)); struct idtr { uint16_t size; uint64_t address; } __attribute__((packed)); // interrupt gate #define GATE_64BIT_INT 0x0E // trap gate #define GATE_64BIT_TRAP 0x0F // privilege ring allowed to call interrupt #define RING0 0x00 #define RING1 0x20 #define RING2 0x40 #define RING3 0x60 // interrupt is present in IDT #define PRESENT 0x80 __attribute__((aligned(0x10))) static struct idt_entry idt[256]; static struct idtr idtr; // from idt.S extern void *isr_stub_table[]; // initialize and load the IDT void idt_init(void) { // initialize idtr idtr.address = (uint64_t)&idt; idtr.size = (uint16_t)sizeof(struct idt_entry) * IDT_SIZE - 1; // initialize idt for (size_t vector = 0; vector < IDT_SIZE; vector++) { struct idt_entry *entry = &idt[vector]; uint64_t isr = (uint64_t)isr_stub_table[vector]; // interrupts before 0x20 are for cpu exceptions uint8_t gate_type = (vector < 0x20) ? GATE_64BIT_TRAP : GATE_64BIT_INT; entry->kernel_cs = 0x08; // offset of 1 into GDT entry->ist = 0; entry->flags = PRESENT | RING0 | gate_type; entry->isr_low = isr & 0xffff; entry->isr_mid = (isr >> 16) & 0xffff; entry->isr_high = (isr >> 32) & 0xffffffff; entry->reserved = 0; } __asm__ volatile ("lidt %0" : : "m"(idtr)); } // Intel manual vol 3 ch 6.3.1 char *EXCEPTIONS[] = { "Division Error", "Debug", "NMI", "Breakpoint", "Overflow", "BOUND Range Exceeded", "Invalid Opcode", "Device Not Available", "Double Fault", "Coprocessor Segment Overrun", "Invalid TSS", "Segment Not Present", "Stack-Segment Fault", "General Protection Fault", "Page Fault", "Reserved", "x87 Floating-Point Error", "Alignment Check", "Machine Check", "SIMD Floaing-Point Exception", "Virtualization Exception", "Control Protection Exception", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Reserved", "Hypervisor Injection Exception", "VMM Communication Exception", "Security Exception", "Reserved", }; void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *state) { switch (exception) { case 0x01: // debug debugger(state, DEBUG_DBG); return; case 0x03: // breakpoint debugger(state, DEBUG_INT3); return; } kputs("\n\n!!! EXCEPTION !!!\n"); kprintf("0x%02lX %s\n", exception, EXCEPTIONS[exception]); kprintf("Error code 0x%lX\n", code); // page faults store the offending address in cr2 if (exception == 0x0E) { uint64_t cr2; __asm__ volatile ("mov %%cr2, %0" : "=r"(cr2)); kprintf("Page fault address: 0x%lX\n", cr2); } kputs("\n"); log_backtrace_ex((void *)state->rip, (void *)state->rbp); while (1) { halt(); } } void idt_pic_eoi(uint8_t exception) { pic_eoi(exception - PIC_REMAP_OFFSET); } int counter = 0; void idt_pic_timer(void) { // print a message once we know the timer works // but avoid spamming the logs if (counter == 3) { //kputs("pic timer!\n"); } if (counter <= 3) { counter++; } } void idt_pic_keyboard(void) {} void idt_pic_mouse(void) {}