summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordzwdz2021-07-21 18:02:53 +0200
committerdzwdz2021-07-21 18:02:53 +0200
commit04b4c029420b010a906d0af3fb7b52108471c4bd (patch)
tree48154dfd8de19f140c242fc1c21b89f780730adb /src
parent1b9c86d59753e2ecaf9529386483aebbe25ba265 (diff)
create ISR stubs, which call a single main isr handler
quick explaination of how this even works: The `call` in each stub pushes its own address onto the stack before calling stage2. We can substract the address of the 0th ISR to get the offset, which we then divide by the size of each stub to get the index.
Diffstat (limited to 'src')
-rw-r--r--src/kernel/arch/i386/interrupts/idt.c14
-rw-r--r--src/kernel/arch/i386/interrupts/isr.c33
-rw-r--r--src/kernel/arch/i386/interrupts/isr.h15
-rw-r--r--src/kernel/arch/i386/interrupts/isr_stub.s25
4 files changed, 46 insertions, 41 deletions
diff --git a/src/kernel/arch/i386/interrupts/idt.c b/src/kernel/arch/i386/interrupts/idt.c
index bbaf610..4c46514 100644
--- a/src/kernel/arch/i386/interrupts/idt.c
+++ b/src/kernel/arch/i386/interrupts/idt.c
@@ -27,14 +27,14 @@ struct lidt_arg {
static struct idt_entry IDT[256];
static struct lidt_arg lidt_arg;
-static inline void idt_add(uint8_t num, bool user, void (*isr));
+static inline void idt_add(uint8_t num, bool user);
static void idt_prepare();
static void idt_load();
static void idt_test();
-static inline void idt_add(uint8_t num, bool user, void (*isr)) {
- uintptr_t offset = (uintptr_t) isr;
+static inline void idt_add(uint8_t num, bool user) {
+ uintptr_t offset = (uintptr_t) &_isr_stubs + 8 * num;
IDT[num] = (struct idt_entry) {
.offset_low = offset,
@@ -52,10 +52,10 @@ static void idt_prepare() {
for (int i = 0; i < 256; i++)
IDT[i].present = 0;
- idt_add(0x08, false, isr_double_fault);
- idt_add(0x0d, false, isr_general_protection_fault);
- idt_add(0x0e, false, isr_page_fault);
- idt_add(0x34, false, isr_test_interrupt);
+ idt_add(0x08, false);
+ idt_add(0x0d, false);
+ idt_add(0x0e, false);
+ idt_add(0x34, false);
}
static void idt_load() {
diff --git a/src/kernel/arch/i386/interrupts/isr.c b/src/kernel/arch/i386/interrupts/isr.c
index 9da06fb..800bdba 100644
--- a/src/kernel/arch/i386/interrupts/isr.c
+++ b/src/kernel/arch/i386/interrupts/isr.c
@@ -4,29 +4,22 @@
#include <stdbool.h>
#include <stdint.h>
-#define UNUSED __attribute__((unused))
+#define log_n_panic(x) {log_const(x); panic();}
bool isr_test_interrupt_called = false;
-__attribute__((interrupt))
-void isr_double_fault(UNUSED struct interrupt_frame *frame) {
- log_const("#DF");
- panic();
-}
-
-__attribute__((interrupt))
-void isr_general_protection_fault(UNUSED struct interrupt_frame *frame) {
- log_const("#GP");
- panic();
-}
+void isr_stage3(int interrupt) {
+ switch (interrupt) {
+ case 0x08: log_n_panic("#DF"); // double fault
+ case 0x0D: log_n_panic("#GP"); // general protection fault
+ case 0x0E: log_n_panic("#PF"); // page fault
-__attribute__((interrupt))
-void isr_page_fault(UNUSED struct interrupt_frame *frame) {
- log_const("#PF");
- panic();
-}
+ case 0x34:
+ isr_test_interrupt_called = true;
+ return;
-__attribute__((interrupt))
-void isr_test_interrupt(UNUSED struct interrupt_frame *frame) {
- isr_test_interrupt_called = true;
+ default:
+ log_const("unknown interrupt");
+ panic();
+ }
}
diff --git a/src/kernel/arch/i386/interrupts/isr.h b/src/kernel/arch/i386/interrupts/isr.h
index c3585dc..09d4328 100644
--- a/src/kernel/arch/i386/interrupts/isr.h
+++ b/src/kernel/arch/i386/interrupts/isr.h
@@ -1,18 +1,5 @@
#pragma once
#include <stdbool.h>
-struct interrupt_frame;
-
extern bool isr_test_interrupt_called; // used in the self-test in idt.c
-
-__attribute__((interrupt))
-void isr_double_fault(struct interrupt_frame *frame);
-
-__attribute__((interrupt))
-void isr_general_protection_fault(struct interrupt_frame *frame);
-
-__attribute__((interrupt))
-void isr_page_fault(struct interrupt_frame *frame);
-
-__attribute__((interrupt))
-void isr_test_interrupt(struct interrupt_frame *frame);
+extern const char _isr_stubs;
diff --git a/src/kernel/arch/i386/interrupts/isr_stub.s b/src/kernel/arch/i386/interrupts/isr_stub.s
new file mode 100644
index 0000000..a8a97b3
--- /dev/null
+++ b/src/kernel/arch/i386/interrupts/isr_stub.s
@@ -0,0 +1,25 @@
+.section .text
+
+.global _isr_stubs
+_isr_stubs:
+
+.rept 256
+ .align 8
+ pushal
+ call _isr_stage2
+.endr
+
+_isr_stage2:
+ cld
+
+ // convert the return address into the vector nr
+ pop %eax
+ add $-_isr_stubs, %eax
+ shr $3, %eax
+ push %eax
+
+ call isr_stage3
+ add $4, %esp
+
+ popal
+ iret