diff options
author | Danny Holman <dholman@gymli.org> | 2022-01-15 16:11:30 -0600 |
---|---|---|
committer | Danny Holman <dholman@gymli.org> | 2022-01-15 16:11:30 -0600 |
commit | c83d7bdcb60859f232e0fa6994ffba01509aba2e (patch) | |
tree | 66425a7362be26d27acf12015c7b3353a0e4159c /arch/i386/boot/idt.c | |
parent | 45e882197b3c2ab97d671bad87c995dff0380661 (diff) |
arch: i386: simplify IDT setup
Simplify the interrupt descriptor table setup and frame assembly.
Signed-off-by: Danny Holman <dholman@gymli.org>
Diffstat (limited to 'arch/i386/boot/idt.c')
-rw-r--r-- | arch/i386/boot/idt.c | 104 |
1 files changed, 100 insertions, 4 deletions
diff --git a/arch/i386/boot/idt.c b/arch/i386/boot/idt.c index d741381..dbcfaa2 100644 --- a/arch/i386/boot/idt.c +++ b/arch/i386/boot/idt.c @@ -5,17 +5,113 @@ #include <kernel/string.h> #include <stdint.h> +#define SEGMENT_PRESENT 0x80 +#define SEGMENT_RING0 0x00 +#define SEGMENT_RING3 0x60 +#define SEGMENT_STORAGE 0x00 +#define SEGMENT_INTERRUPT 0x0E +#define IDT_EXCEPTION (SEGMENT_PRESENT | SEGMENT_INTERRUPT) +#define IDT_INTERRUPT (SEGMENT_PRESENT | SEGMENT_INTERRUPT) + +#define IDT_MAX_DESCRIPTORS 256 + +struct idt_entry { + uint16_t isr_low; + uint16_t kernel_cs; + uint8_t reserved; + uint8_t flags; + uint16_t isr_high; +} __attribute__((packed)); + +struct idt_ptr { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); + __attribute__((aligned(0x10))) struct idt_entry idt[256]; struct idt_ptr idtr; +char *exceptions[] = { + "Division by zero", + "Debug", + "Non-maskable interrupt", + "Breakpoint", + "Overflow", + "Out-of-bounds", + "Invalid opcode", + "FPU not available", + "Double fault", + "RESERVED", + "Invalid TSS", + "Segment not present", + "Stack fault", + "General protection fault", + "Page fault", + "RESERVED", + "FPU exception", + "Alignment check", + "Machine check", + "FPU-SIMD exception", + "Virtualization exception", + "Control protection" + "RESERVED", + "Hypervisor injection", + "VMM exception", + "Security exception", + "RESERVED", + "Triple fault", + "RESERVED" +}; + __attribute__((noreturn)) -void exception_handler(struct isr_frame *frame) { - kprintf("Error: CPU exception: %d\n", frame->vector); +void halt_catch_fire(struct isr_frame *frame) { + kprintf("Registers at interrupt:\n"); + kprintf("\tEAX = %x\n", frame->eax); + kprintf("\tEBX = %x\n", frame->ebx); + kprintf("\tECX = %x\n", frame->ecx); + kprintf("\tEDX = %x\n", frame->edx); + kprintf("\tESI = %x\n", frame->esi); + kprintf("\tEDI = %x\n", frame->edi); + kprintf("\tESP = %x\n", frame->esp); + kprintf("\tEBP = %x\n", frame->ebp); + kprintf("\tEIP = %x\n", frame->eip); + kprintf("\tEFLAGS = %x\n", frame->eflags); + kprintf("Current code selector: %d\n", frame->cs); __asm__ volatile("cli;hlt"); } -extern void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_t flags) { +__attribute__((noreturn)) +void exception_handler(struct isr_frame *frame) { + switch (frame->vector) { + default: + kprintf("Unhandled exception: %s\n", exceptions[frame->vector]); + halt_catch_fire(frame); + } +} + +void irq_dispatch(uint8_t irq, struct isr_frame *frame) { + return; +} + +__attribute__((noreturn)) +void interrupt_handler(struct isr_frame *frame) { + if (frame->vector < 32) + exception_handler(frame); + else if (frame->vector > 32 && frame->vector < 48) + irq_dispatch(frame->vector - 16, frame); + switch (frame->vector) { + case 0x80: + syscall_dispatch(frame); + break; + default: + kprintf("Error: Unmapped interrupt: %d\n", frame->vector); + halt_catch_fire(frame); + __asm__ volatile("cli;hlt"); + } +} + +void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_t flags) { struct idt_entry *desc = &idt[num]; desc->isr_low = (uint16_t)(((uint32_t)handler >> 0) & 0xFFFF); desc->isr_high = (uint16_t)(((uint32_t)handler >> 16) & 0xFFFF); @@ -26,7 +122,7 @@ extern void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_ void idt_install(void) { idtr.limit = (uint16_t)sizeof(struct idt_entry) * 256 - 1; - idtr.base = (uint32_t)&idt[0]; + idtr.base = (uint32_t)idt; idt_set_gate(0, isr_stub_0, 0x08, IDT_EXCEPTION); idt_set_gate(1, isr_stub_1, 0x08, IDT_EXCEPTION); |