summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Holman <dholman@gymli.org>2024-02-16 12:59:43 -0600
committerDanny Holman <dholman@gymli.org>2024-02-16 12:59:43 -0600
commitbcb79aaff44f126064c4698ea74ffe2b68baeb0e (patch)
treeb176c8e6352b78342e622d3384f9b68242773f6b
parent157bea025cf120be22efe6327e6dd6b390fc4ba1 (diff)
arch: i386: move IRQ functions to PIC driver
Move all the functions that control IRQ lines to the PIC driver. This allows the IDT controller to handle only raw interrupts no matter where they come from. Signed-off-by: Danny Holman <dholman@gymli.org>
-rw-r--r--arch/i386/boot/idt.c43
-rw-r--r--arch/i386/include/kernel/pic.h2
-rw-r--r--arch/i386/kernel/pic.c12
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;