From c0019e9d0bd2059351dc7d0274ee0479a71192fc Mon Sep 17 00:00:00 2001 From: Danny Holman Date: Tue, 28 Sep 2021 09:08:38 -0500 Subject: 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 --- arch/i386/boot/idt.c | 82 +++++++++++++++++++++++++----------------- arch/i386/boot/isr.s | 36 ++++++++++++------- arch/i386/include/kernel/idt.h | 35 ++++++++++++++++++ arch/i386/include/kernel/isr.h | 37 +++++++++++++++++++ 4 files changed, 145 insertions(+), 45 deletions(-) create mode 100644 arch/i386/include/kernel/idt.h create mode 100644 arch/i386/include/kernel/isr.h (limited to 'arch/i386') 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 +#include #include +#include +#include #include -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 + +// 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 -- cgit v1.2.3