summaryrefslogtreecommitdiff
path: root/src/kernel/arch
diff options
context:
space:
mode:
authordzwdz2023-01-25 21:49:14 +0100
committerdzwdz2023-01-25 21:49:14 +0100
commitf9ce893e143a7c2356a0f2204afac1f37d3e54d2 (patch)
treee93e569328ea61b71e785a52964238dc032aeefd /src/kernel/arch
parentc24a9376b4a048a3f9408df2d47eaad367459bd7 (diff)
kernel/irq: use a lookup table for irqs
Diffstat (limited to 'src/kernel/arch')
-rw-r--r--src/kernel/arch/amd64/boot.c3
-rw-r--r--src/kernel/arch/amd64/boot.h1
-rw-r--r--src/kernel/arch/amd64/driver/ps2.c8
-rw-r--r--src/kernel/arch/amd64/driver/rtl8139.c2
-rw-r--r--src/kernel/arch/amd64/driver/serial.c4
-rw-r--r--src/kernel/arch/amd64/interrupts.h (renamed from src/kernel/arch/amd64/interrupts/irq.h)7
-rw-r--r--src/kernel/arch/amd64/interrupts/idt.c9
-rw-r--r--src/kernel/arch/amd64/interrupts/irq.c2
-rw-r--r--src/kernel/arch/amd64/interrupts/isr.c63
-rw-r--r--src/kernel/arch/amd64/interrupts/isr.h8
-rw-r--r--src/kernel/arch/amd64/pci.c2
-rw-r--r--src/kernel/arch/amd64/time.c6
12 files changed, 48 insertions, 67 deletions
diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c
index 32d0452..bc9a675 100644
--- a/src/kernel/arch/amd64/boot.c
+++ b/src/kernel/arch/amd64/boot.c
@@ -5,7 +5,7 @@
#include <kernel/arch/amd64/driver/ps2.h>
#include <kernel/arch/amd64/driver/serial.h>
#include <kernel/arch/amd64/driver/video.h>
-#include <kernel/arch/amd64/interrupts/irq.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/arch/amd64/pci.h>
#include <kernel/arch/amd64/tty/tty.h>
#include <kernel/arch/generic.h>
@@ -37,6 +37,7 @@ void kmain_early(void *mbi) {
idt_init();
kprintf("irq...");
irq_init();
+ timer_init();
{
kprintf("mem...\n");
diff --git a/src/kernel/arch/amd64/boot.h b/src/kernel/arch/amd64/boot.h
index b68f52b..7c36cd3 100644
--- a/src/kernel/arch/amd64/boot.h
+++ b/src/kernel/arch/amd64/boot.h
@@ -16,6 +16,7 @@ enum gdt_segs {
void kmain_early(void *mbi);
void gdt_init(void);
void idt_init(void);
+void timer_init(void);
/* used from asm */
extern struct lgdt_arg lgdt_arg;
diff --git a/src/kernel/arch/amd64/driver/ps2.c b/src/kernel/arch/amd64/driver/ps2.c
index 971d7d1..4aa17ff 100644
--- a/src/kernel/arch/amd64/driver/ps2.c
+++ b/src/kernel/arch/amd64/driver/ps2.c
@@ -1,7 +1,7 @@
#include <camellia/errno.h>
#include <kernel/arch/amd64/driver/ps2.h>
#include <kernel/arch/amd64/driver/util.h>
-#include <kernel/arch/amd64/interrupts/irq.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/arch/amd64/port_io.h>
#include <kernel/panic.h>
#include <kernel/proc.h>
@@ -50,8 +50,12 @@ void ps2_init(void) {
wait_out();
port_out8(PS2, 0xF4); /* packet streaming */
wait_in();
- if (port_in8(PS2) != 0xFA) /* check ACK */
+ if (port_in8(PS2) != 0xFA) { /* check ACK */
panic_unimplemented();
+ }
+
+ irq_fn[IRQ_PS2KB] = ps2_irq;
+ irq_fn[IRQ_PS2MOUSE] = ps2_irq;
vfs_root_register("/ps2", accept);
}
diff --git a/src/kernel/arch/amd64/driver/rtl8139.c b/src/kernel/arch/amd64/driver/rtl8139.c
index d0e4d90..bf8a67a 100644
--- a/src/kernel/arch/amd64/driver/rtl8139.c
+++ b/src/kernel/arch/amd64/driver/rtl8139.c
@@ -1,5 +1,6 @@
#include <kernel/arch/amd64/driver/rtl8139.h>
#include <kernel/arch/amd64/driver/util.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/arch/amd64/pci.h>
#include <kernel/arch/amd64/port_io.h>
#include <kernel/panic.h>
@@ -47,6 +48,7 @@ static void rx_irq_enable(bool v) {
void rtl8139_init(uint32_t bdf) {
if (iobase) panic_unimplemented(); /* multiple devices */
iobase = pcicfg_iobase(bdf);
+ irq_fn[IRQ_RTL8139] = rtl8139_irq;
/* also includes the status, because i have only implemented w32 */
uint32_t cmd = pcicfg_r32(bdf, PCICFG_CMD);
diff --git a/src/kernel/arch/amd64/driver/serial.c b/src/kernel/arch/amd64/driver/serial.c
index 5004c31..e8774b6 100644
--- a/src/kernel/arch/amd64/driver/serial.c
+++ b/src/kernel/arch/amd64/driver/serial.c
@@ -1,6 +1,6 @@
#include <kernel/arch/amd64/driver/serial.h>
#include <kernel/arch/amd64/driver/util.h>
-#include <kernel/arch/amd64/interrupts/irq.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/arch/amd64/port_io.h>
#include <kernel/panic.h>
#include <kernel/proc.h>
@@ -25,6 +25,8 @@ static void serial_selftest(void) {
}
void serial_preinit(void) {
+ irq_fn[IRQ_COM1] = serial_irq;
+
// see https://www.sci.muni.cz/docs/pc/serport.txt
// set baud rate divisor
port_out8(COM1 + 3, 0b10000000); // enable DLAB
diff --git a/src/kernel/arch/amd64/interrupts/irq.h b/src/kernel/arch/amd64/interrupts.h
index f949824..262ea16 100644
--- a/src/kernel/arch/amd64/interrupts/irq.h
+++ b/src/kernel/arch/amd64/interrupts.h
@@ -2,13 +2,16 @@
#include <stdbool.h>
#include <stdint.h>
+#define IRQ_COM1 4
#define IRQ_IBASE 0x20
#define IRQ_PIT 0
#define IRQ_PS2KB 1
-#define IRQ_COM1 4
#define IRQ_PS2MOUSE 12
-
#define IRQ_RTL8139 11
+extern void (*irq_fn[16])(void);
+extern const char _isr_stubs;
+
void irq_init(void);
void irq_eoi(uint8_t line);
+void isr_stage3(uint8_t interrupt, uint64_t *stackframe);
diff --git a/src/kernel/arch/amd64/interrupts/idt.c b/src/kernel/arch/amd64/interrupts/idt.c
index 622ac1a..8f37cb9 100644
--- a/src/kernel/arch/amd64/interrupts/idt.c
+++ b/src/kernel/arch/amd64/interrupts/idt.c
@@ -1,5 +1,5 @@
#include <kernel/arch/amd64/boot.h>
-#include <kernel/arch/amd64/interrupts/isr.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/panic.h>
#include <stdbool.h>
#include <stdint.h>
@@ -30,7 +30,6 @@ static struct lidt_arg lidt_arg;
static void idt_prepare(void);
static void idt_load(void);
-static void idt_test(void);
static void idt_prepare(void) {
@@ -55,13 +54,7 @@ static void idt_load(void) {
asm("lidt (%0)" : : "r" (&lidt_arg) : "memory");
}
-static void idt_test(void) {
- asm("int $0x34" : : : "memory");
- assert(isr_test_interrupt_called);
-}
-
void idt_init(void) {
idt_prepare();
idt_load();
- idt_test();
}
diff --git a/src/kernel/arch/amd64/interrupts/irq.c b/src/kernel/arch/amd64/interrupts/irq.c
index 818ea8e..e900450 100644
--- a/src/kernel/arch/amd64/interrupts/irq.c
+++ b/src/kernel/arch/amd64/interrupts/irq.c
@@ -1,4 +1,4 @@
-#include <kernel/arch/amd64/interrupts/irq.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/arch/amd64/port_io.h>
#include <stdint.h>
diff --git a/src/kernel/arch/amd64/interrupts/isr.c b/src/kernel/arch/amd64/interrupts/isr.c
index 1059530..ff00f2f 100644
--- a/src/kernel/arch/amd64/interrupts/isr.c
+++ b/src/kernel/arch/amd64/interrupts/isr.c
@@ -1,21 +1,15 @@
-#include <kernel/arch/amd64/driver/ps2.h>
-#include <kernel/arch/amd64/driver/rtl8139.h>
-#include <kernel/arch/amd64/driver/serial.h>
-#include <kernel/arch/amd64/interrupts/irq.h>
-#include <kernel/arch/amd64/interrupts/isr.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/arch/amd64/port_io.h>
-#include <kernel/arch/amd64/time.h>
#include <kernel/arch/generic.h>
-#include <kernel/mem/alloc.h>
#include <kernel/panic.h>
#include <kernel/proc.h>
#include <stdbool.h>
#include <stdint.h>
-bool isr_test_interrupt_called = false;
+void (*irq_fn[16])(void) = {0};
static void log_interrupt(int interrupt, uint64_t *stackframe) {
- kprintf("interrupt %x, rip = k/%08x, cs 0x%x, code 0x%x\n",
+ kprintf("interrupt %d, rip = k/%08x, cs 0x%x, code 0x%x\n",
interrupt, stackframe[0], stackframe[1], stackframe[-1]);
if ((stackframe[1] & 0x3) == 0) {
uint64_t *stack = (void*)stackframe[3];
@@ -28,42 +22,25 @@ static void log_interrupt(int interrupt, uint64_t *stackframe) {
}
}
-void isr_stage3(int interrupt, uint64_t *stackframe) {
- if (interrupt == 0xe || interrupt == 0xd) stackframe++;
- switch (interrupt) {
- case 0x34:
- isr_test_interrupt_called = true;
- return;
-
- case IRQ_IBASE + IRQ_PIT:
- pit_irq();
- irq_eoi(IRQ_PIT);
- return;
-
- case IRQ_IBASE + IRQ_PS2KB:
- case IRQ_IBASE + IRQ_PS2MOUSE:
- ps2_irq();
- irq_eoi(interrupt - IRQ_IBASE);
- return;
-
- case IRQ_IBASE + IRQ_COM1:
- serial_irq();
- irq_eoi(IRQ_COM1);
+void isr_stage3(uint8_t interrupt, uint64_t *stackframe) {
+ uint8_t irqn = interrupt - IRQ_IBASE;
+ if (irqn < 16) {
+ if (irq_fn[irqn]) {
+ irq_fn[irqn]();
+ irq_eoi(irqn);
return;
+ }
+ }
- case IRQ_IBASE + IRQ_RTL8139:
- rtl8139_irq();
- irq_eoi(interrupt - IRQ_IBASE);
- return;
+ if (interrupt == 0xe || interrupt == 0xd) {
+ stackframe++;
+ }
- default:
- if ((stackframe[1] & 0x3) == 0) {
- // mem_debugprint();
- log_interrupt(interrupt, stackframe);
- cpu_halt();
- } else {
- proc_kill(proc_cur, interrupt);
- proc_switch_any();
- }
+ if ((stackframe[1] & 0x3) == 0) { /* in kernel */
+ log_interrupt(interrupt, stackframe);
+ cpu_halt();
+ } else { /* in user */
+ proc_kill(proc_cur, interrupt);
+ proc_switch_any();
}
}
diff --git a/src/kernel/arch/amd64/interrupts/isr.h b/src/kernel/arch/amd64/interrupts/isr.h
deleted file mode 100644
index 01f5236..0000000
--- a/src/kernel/arch/amd64/interrupts/isr.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-#include <stdbool.h>
-#include <stdint.h>
-
-extern bool isr_test_interrupt_called; // used in the self-test in idt.c
-extern const char _isr_stubs;
-
-void isr_stage3(int interrupt, uint64_t *stackframe);
diff --git a/src/kernel/arch/amd64/pci.c b/src/kernel/arch/amd64/pci.c
index 92e2697..23cd457 100644
--- a/src/kernel/arch/amd64/pci.c
+++ b/src/kernel/arch/amd64/pci.c
@@ -1,5 +1,5 @@
#include <kernel/arch/amd64/driver/rtl8139.h>
-#include <kernel/arch/amd64/interrupts/irq.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/arch/amd64/pci.h>
#include <kernel/arch/amd64/port_io.h>
#include <kernel/arch/generic.h>
diff --git a/src/kernel/arch/amd64/time.c b/src/kernel/arch/amd64/time.c
index 0e40521..aa7603c 100644
--- a/src/kernel/arch/amd64/time.c
+++ b/src/kernel/arch/amd64/time.c
@@ -1,3 +1,5 @@
+#include <kernel/arch/amd64/boot.h>
+#include <kernel/arch/amd64/interrupts.h>
#include <kernel/arch/amd64/time.h>
#include <kernel/panic.h>
#include <kernel/proc.h>
@@ -48,3 +50,7 @@ void timer_deschedule(Proc *p) {
update_goal();
}
+
+void timer_init(void) {
+ irq_fn[IRQ_PIT] = pit_irq;
+}