diff options
-rw-r--r-- | src/kernel/arch/i386/interrupts/idt.c | 14 | ||||
-rw-r--r-- | src/kernel/arch/i386/interrupts/isr.c | 33 | ||||
-rw-r--r-- | src/kernel/arch/i386/interrupts/isr.h | 15 | ||||
-rw-r--r-- | src/kernel/arch/i386/interrupts/isr_stub.s | 25 |
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 |