#include #include #include #include #include #include #include #include #include #include #include #include #include struct IdtEntry { uint16_t isr_low; uint16_t kernel_cs; uint8_t _reserved; uint8_t attributes; uint16_t isr_high; } __attribute__((packed)); struct Idtr { uint16_t limit; uint32_t base; } __attribute__((packed)); enum IDTFlags { IDT_FLAG_GATE_TASK = 0x5, IDT_FLAG_GATE_16BIT_INT = 0x6, IDT_FLAG_GATE_16BIT_TRAP = 0x7, IDT_FLAG_GATE_32BIT_INT = 0xE, IDT_FLAG_GATE_32BIT_TRAP = 0xF, IDT_FLAG_RING0 = (0 << 5), IDT_FLAG_RING1 = (1 << 5), IDT_FLAG_RING2 = (2 << 5), IDT_FLAG_RING3 = (3 << 5), IDT_FLAG_PRESENT = 0x80, }; static size_t timer = 0; void idt_pic_eoi(uint8_t exception) { pic_eoi(exception - PIC_REMAP_OFFSET); } void idt_pic_timer(void) { timer += 1; } size_t get_systemtime(void) { return timer; } void idt_pic_keyboard(void) { ps2kb_recv(); } void idt_pic_mouse(void) { ps2mouse_recv(); } void idt_exception_handler(uint8_t exception) { char* msg; switch(exception) { case 0x00: msg = "Division by zero"; break; case 0x02: msg = "NMI"; break; case 0x04: msg = "Overflow"; break; case 0x06: msg = "invalid opcode"; break; case 0x08: msg = "double fault"; break; case 0x0A: msg = "invalid task state segment"; break; case 0x0C: msg = "stack segment fault"; break; case 0x0D: msg = "general protection fault"; break; case 0x0E: msg = "page fault"; break; default: msg = "unknown exception"; break; } panic("E%u: %s", exception, msg); } __attribute__((aligned(0x10))) static struct IdtEntry idt[256]; static struct Idtr idtr; extern void* isr_stub_table[]; static void set_descriptor(uint8_t vector, void* isr, uint8_t flags) { struct IdtEntry* entry = &idt[vector]; entry->isr_low = (size_t)isr & 0xffff; entry->kernel_cs = 0x08; entry->attributes = flags; entry->isr_high = (size_t)isr >> 16; entry->_reserved = 0; } void idt_init(void) { idtr.base = (uintptr_t)&idt[0]; idtr.limit = (uint16_t)sizeof(struct IdtEntry) * IDT_SIZE - 1; for(int i = 0; i < IDT_INTERRUPTS; i++) { set_descriptor(i, isr_stub_table[i], 0x8e); } __asm__ volatile ("lidt %0" : : "m"(idtr)); }