diff options
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/boot/idt.c | 43 | ||||
-rw-r--r-- | arch/i386/include/kernel/pic.h | 2 | ||||
-rw-r--r-- | arch/i386/kernel/pic.c | 12 |
3 files changed, 39 insertions, 18 deletions
diff --git a/arch/i386/boot/idt.c b/arch/i386/boot/idt.c index 0e641be..7b9401d 100644 --- a/arch/i386/boot/idt.c +++ b/arch/i386/boot/idt.c @@ -1,4 +1,6 @@ #include <kernel/syscall.h> +#include <kernel/panic.h> +#include <kernel/gdt.h> #include <kernel/isr.h> #include <kernel/io.h> #include <kernel/pic.h> @@ -10,7 +12,7 @@ __attribute__((aligned(0x10))) struct idt_entry idt[256]; struct idt_ptr idtr; -char *exceptions[] = { +const char* exceptions[] = { "Division by zero", "Debug", "Non-maskable interrupt", @@ -45,39 +47,47 @@ char *exceptions[] = { __attribute__((noreturn)) void halt_catch_fire(struct isr_frame *frame) { dump_reg(frame); + kprintf("ERRNO=%x\n", frame->errno); __asm__ volatile("cli;hlt"); while (1); } void exception_handler(struct isr_frame *frame) { switch (frame->vector) { + case 0x00: + panic("Division by zero in kernel address space"); + halt_catch_fire(frame); + case 0x06: + panic("Invalid opcode in kernel address space"); + halt_catch_fire(frame); + case 0x08: + panic("Double fault in interrupt handler"); + halt_catch_fire(frame); + case 0x0D: + panic("Protection fault in kernel address space"); + halt_catch_fire(frame); case 0x0E: page_fault_handler(frame); break; default: - kprintf("Unhandled exception: %s\n", exceptions[frame->vector]); + panic("Unhandled exception"); halt_catch_fire(frame); } } -void irq_dispatch(struct isr_frame *frame) { - pic_eoi(frame->vector-32); - return; -} - -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); +void interrupt_handler(struct isr_frame frame) { + if (frame.vector < 32) { + exception_handler(&frame); + } else if (frame.vector < 48) { + irq_dispatch(&frame); } else { - switch (frame->vector) { + switch (frame.vector) { case 0x80: - handle_syscall(frame); + handle_syscall(&frame); break; default: - kprintf("Error: Unmapped interrupt: %d\n", frame->vector); - halt_catch_fire(frame); + panic("Unmapped interrupt"); + halt_catch_fire(&frame); __asm__ volatile("cli;hlt"); } } @@ -149,5 +159,4 @@ void idt_install(void) { idt_set_gate(0x80, syscall_stub, 0x08, IDT_INTERRUPT); __asm__ volatile("lidt %0" : : "memory"(idtr)); - __asm__ volatile("sti"); } diff --git a/arch/i386/include/kernel/pic.h b/arch/i386/include/kernel/pic.h index af7b5ba..ca3cc99 100644 --- a/arch/i386/include/kernel/pic.h +++ b/arch/i386/include/kernel/pic.h @@ -1,6 +1,7 @@ #ifndef I386_PIC_H #define I386_PIC_H +#include <kernel/isr.h> #include <kernel/idt.h> #include <stdint.h> @@ -46,6 +47,7 @@ uint16_t pic_get_irr(void); uint16_t pic_get_isr(void); void register_irq_handler(uint8_t irq, void (*handler)(struct isr_frame *frame)); +void irq_dispatch(struct isr_frame *frame); void irq_set_mask(uint8_t irq); void irq_clear_mask(uint8_t irq); diff --git a/arch/i386/kernel/pic.c b/arch/i386/kernel/pic.c index 9494b92..7a51763 100644 --- a/arch/i386/kernel/pic.c +++ b/arch/i386/kernel/pic.c @@ -1,6 +1,6 @@ #include <kernel/pic.h> -void (*irq_handlers[16])(struct isr_frame *frame); +static void (*irq_handlers[16])(struct isr_frame *frame); void pic_eoi(uint8_t irq) { if (irq >= 8) @@ -38,6 +38,16 @@ uint16_t pic_get_isr(void) { return __pic_get_irq_reg(PIC_READ_ISR); } +void register_irq_handler(uint8_t irq, void (*handler)(struct isr_frame *frame)) { + irq_handlers[irq] = handler; +} + +void irq_dispatch(struct isr_frame *frame) { + (*irq_handlers[frame->vector-32])(frame); + pic_eoi(frame->vector-32); + return; +} + void irq_set_mask(uint8_t irq) { uint16_t port; uint8_t data; |