summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanny Holman <dholman@gymli.xyz>2021-09-28 09:08:38 -0500
committerDanny Holman <dholman@gymli.xyz>2021-09-28 09:28:33 -0500
commitc0019e9d0bd2059351dc7d0274ee0479a71192fc (patch)
tree99a9ee22a5e8a102e719d6710226b9c181fae74a
parent0ec9e9824e32d3d54d2ad43c3f2743d52127aa92 (diff)
arch: i386: fix IDT exception handler
Fix the i386's general exception handler to actually work. Fix provided by Jon Sanderson (jjs295356@gmail.com). Signed-off-by: Danny Holman <dholman@gymli.xyz>
-rw-r--r--arch/i386/boot/idt.c82
-rw-r--r--arch/i386/boot/isr.s36
-rw-r--r--arch/i386/include/kernel/idt.h35
-rw-r--r--arch/i386/include/kernel/isr.h37
4 files changed, 145 insertions, 45 deletions
diff --git a/arch/i386/boot/idt.c b/arch/i386/boot/idt.c
index 752b679..7213fe5 100644
--- a/arch/i386/boot/idt.c
+++ b/arch/i386/boot/idt.c
@@ -1,50 +1,66 @@
+#include <kernel/idt.h>
+#include <kernel/isr.h>
#include <kernel/io.h>
+#include <kernel/pic.h>
+#include <kernel/string.h>
#include <stdint.h>
-struct idt_entry {
- uint16_t isr_low;
- uint16_t kernel_cs;
- uint8_t reserved;
- uint8_t attributes;
- uint16_t isr_high;
-} __attribute__((packed));
-
-struct idt_ptr {
- uint16_t limit;
- uint32_t base;
-} __attribute__((packed));
-
__attribute__((aligned(0x10)))
-static struct idt_entry idt[256];
-static struct idt_ptr idtr;
+struct idt_entry idt[256];
+struct idt_ptr idtr;
__attribute__((noreturn))
-void exception_handler(int in) {
- kprintf("EXCEPTION %d CAUGHT\n", in);
+void exception_handler(int number) {
+ kprintf("EXCEPTION %d CAUGHT\n", number);
+ __asm__ volatile("cli;hlt");
}
-extern void* isr_stub_table[];
-
-void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags) {
- struct idt_entry *desc = &idt[vector];
-
- desc->isr_low = (uint32_t)isr & 0xFFFF;
- desc->kernel_cs = 0x08;
- desc->attributes = flags;
- desc->isr_high = (uint32_t)isr >> 16;
- desc->reserved = 0;
+extern void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_t flags) {
+ idt[num].isr_low = (uint16_t)(((uint32_t)handler >> 0) & 0xFFFF);
+ idt[num].isr_high = (uint16_t)(((uint32_t)handler >> 16) & 0xFFFF);
+ idt[num].reserved = 0;
+ idt[num].kernel_cs = cs;
+ idt[num].flags = flags;
}
void idt_install(void) {
- idtr.base = (uintptr_t)&idt[0];
idtr.limit = (uint16_t)sizeof(struct idt_entry) * 256 - 1;
+ idtr.base = (uint32_t)&idt[0];
- for (uint8_t vector = 0; vector < 32; vector++) {
- idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
- isr_stub_table[vector] = 1;
- }
+ memset(&idt, 0, sizeof(struct idt_entry) * 256);
+ idt_set_gate(0, isr_stub_0, 0x08, 0x8e);
+ idt_set_gate(1, isr_stub_1, 0x08, 0x8e);
+ idt_set_gate(2, isr_stub_2, 0x08, 0x8e);
+ idt_set_gate(3, isr_stub_3, 0x08, 0x8e);
+ idt_set_gate(4, isr_stub_4, 0x08, 0x8e);
+ idt_set_gate(5, isr_stub_5, 0x08, 0x8e);
+ idt_set_gate(6, isr_stub_6, 0x08, 0x8e);
+ idt_set_gate(7, isr_stub_7, 0x08, 0x8e);
+ idt_set_gate(8, isr_stub_8, 0x08, 0x8e);
+ idt_set_gate(9, isr_stub_9, 0x08, 0x8e);
+ idt_set_gate(10, isr_stub_10, 0x08, 0x8e);
+ idt_set_gate(11, isr_stub_11, 0x08, 0x8e);
+ idt_set_gate(12, isr_stub_12, 0x08, 0x8e);
+ idt_set_gate(13, isr_stub_13, 0x08, 0x8e);
+ idt_set_gate(14, isr_stub_14, 0x08, 0x8e);
+ idt_set_gate(15, isr_stub_15, 0x08, 0x8e);
+ idt_set_gate(16, isr_stub_16, 0x08, 0x8e);
+ idt_set_gate(17, isr_stub_17, 0x08, 0x8e);
+ idt_set_gate(18, isr_stub_18, 0x08, 0x8e);
+ idt_set_gate(19, isr_stub_19, 0x08, 0x8e);
+ idt_set_gate(20, isr_stub_20, 0x08, 0x8e);
+ idt_set_gate(21, isr_stub_21, 0x08, 0x8e);
+ idt_set_gate(22, isr_stub_22, 0x08, 0x8e);
+ idt_set_gate(23, isr_stub_23, 0x08, 0x8e);
+ idt_set_gate(24, isr_stub_24, 0x08, 0x8e);
+ idt_set_gate(25, isr_stub_25, 0x08, 0x8e);
+ idt_set_gate(26, isr_stub_26, 0x08, 0x8e);
+ idt_set_gate(27, isr_stub_27, 0x08, 0x8e);
+ idt_set_gate(28, isr_stub_28, 0x08, 0x8e);
+ idt_set_gate(29, isr_stub_29, 0x08, 0x8e);
+ idt_set_gate(30, isr_stub_30, 0x08, 0x8e);
+ idt_set_gate(31, isr_stub_31, 0x08, 0x8e);
__asm__ volatile("lidt %0" : : "memory"(idtr));
__asm__ volatile("sti");
- kprintf("Interrupts on\n");
}
diff --git a/arch/i386/boot/isr.s b/arch/i386/boot/isr.s
index 0f2640f..43ef3be 100644
--- a/arch/i386/boot/isr.s
+++ b/arch/i386/boot/isr.s
@@ -4,18 +4,40 @@
.global isr_stub_\num
.type isr_stub_\num, @function
isr_stub_\num:
- movl $\num, %eax
+ cli
pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushl %ds
+ pushl %esp
+ pushl $\num
call exception_handler
+ popl %esp
+ popl %ds
+ popl %edx
+ popl %ecx
+ popl %eax
+ addl $8, %esp
iret
.endm
.macro isr_no_err_stub num
.global isr_stub_\num
.type isr_stub_\num, @function
isr_stub_\num:
- movl $\num, %eax
+ cli
pushl %eax
+ pushl %ecx
+ pushl %edx
+ pushl %ds
+ pushl %esp
+ pushl $\num
call exception_handler
+ popl %esp
+ popl %ds
+ popl %edx
+ popl %ecx
+ popl %eax
+ addl $8, %esp
iret
.endm
@@ -51,13 +73,3 @@ isr_no_err_stub 28
isr_no_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
-
-.section .data
-
-.global isr_stub_table
-isr_stub_table:
- .set i, 0
- .rept
- 32 dd isr_stub_i
- .set i i+0
- .endr
diff --git a/arch/i386/include/kernel/idt.h b/arch/i386/include/kernel/idt.h
new file mode 100644
index 0000000..7ccad30
--- /dev/null
+++ b/arch/i386/include/kernel/idt.h
@@ -0,0 +1,35 @@
+#ifndef I386_IDT_H
+#define I386_IDT_H
+
+#include <stdint.h>
+
+// IDT Flags
+#define SEGMENT_PRESENT 0x8
+#define SEGMENT_RING0 0x0
+#define SEGMENT_STORAGE 0x0
+#define SEGMENT_GATE 0xE
+#define SEGMENT_DPL 0x8
+
+#define SEGMENT_FLAG SEGMENT_PRESENT | SEGMENT_RING0 | SEGMENT_STORAGE |\
+ SEGMENT_GATE | SEGMENT_DPL;
+
+struct idt_entry {
+ uint16_t isr_low;
+ uint16_t kernel_cs;
+ uint8_t reserved;
+ uint8_t flags;
+ uint16_t isr_high;
+} __attribute__((packed));
+
+struct idt_ptr {
+ uint16_t limit;
+ uint32_t base;
+} __attribute__((packed));
+
+extern struct idt_entry idt[256];
+extern struct idt_ptr idtr;
+
+extern void idt_set_gate(uint8_t num, void(*handler)(void), uint16_t cs, uint8_t flags);
+extern void exception_handler(int num);
+
+#endif \ No newline at end of file
diff --git a/arch/i386/include/kernel/isr.h b/arch/i386/include/kernel/isr.h
new file mode 100644
index 0000000..a924cd6
--- /dev/null
+++ b/arch/i386/include/kernel/isr.h
@@ -0,0 +1,37 @@
+#ifndef I386_ISR_H
+#define I386_ISR_H
+
+extern void isr_stub_0(void);
+extern void isr_stub_1(void);
+extern void isr_stub_2(void);
+extern void isr_stub_3(void);
+extern void isr_stub_4(void);
+extern void isr_stub_5(void);
+extern void isr_stub_6(void);
+extern void isr_stub_7(void);
+extern void isr_stub_8(void);
+extern void isr_stub_9(void);
+extern void isr_stub_10(void);
+extern void isr_stub_11(void);
+extern void isr_stub_12(void);
+extern void isr_stub_13(void);
+extern void isr_stub_14(void);
+extern void isr_stub_15(void);
+extern void isr_stub_16(void);
+extern void isr_stub_17(void);
+extern void isr_stub_18(void);
+extern void isr_stub_19(void);
+extern void isr_stub_20(void);
+extern void isr_stub_21(void);
+extern void isr_stub_22(void);
+extern void isr_stub_23(void);
+extern void isr_stub_24(void);
+extern void isr_stub_25(void);
+extern void isr_stub_26(void);
+extern void isr_stub_27(void);
+extern void isr_stub_28(void);
+extern void isr_stub_29(void);
+extern void isr_stub_30(void);
+extern void isr_stub_31(void);
+
+#endif \ No newline at end of file