summaryrefslogtreecommitdiff
path: root/src/kernel/arch/i386/interrupts
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/arch/i386/interrupts')
-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