summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/i386/boot/idt.c80
-rw-r--r--arch/i386/boot/isr.s76
-rw-r--r--arch/i386/include/kernel/idt.h19
-rw-r--r--arch/i386/include/kernel/isr.h27
4 files changed, 129 insertions, 73 deletions
diff --git a/arch/i386/boot/idt.c b/arch/i386/boot/idt.c
index 7213fe5..d741381 100644
--- a/arch/i386/boot/idt.c
+++ b/arch/i386/boot/idt.c
@@ -10,56 +10,56 @@ struct idt_entry idt[256];
struct idt_ptr idtr;
__attribute__((noreturn))
-void exception_handler(int number) {
- kprintf("EXCEPTION %d CAUGHT\n", number);
+void exception_handler(struct isr_frame *frame) {
+ kprintf("Error: CPU exception: %d\n", frame->vector);
__asm__ volatile("cli;hlt");
}
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;
+ struct idt_entry *desc = &idt[num];
+ desc->isr_low = (uint16_t)(((uint32_t)handler >> 0) & 0xFFFF);
+ desc->isr_high = (uint16_t)(((uint32_t)handler >> 16) & 0xFFFF);
+ desc->reserved = 0;
+ desc->kernel_cs = cs;
+ desc->flags = flags;
}
void idt_install(void) {
idtr.limit = (uint16_t)sizeof(struct idt_entry) * 256 - 1;
idtr.base = (uint32_t)&idt[0];
- 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);
+ idt_set_gate(0, isr_stub_0, 0x08, IDT_EXCEPTION);
+ idt_set_gate(1, isr_stub_1, 0x08, IDT_EXCEPTION);
+ idt_set_gate(2, isr_stub_2, 0x08, IDT_EXCEPTION);
+ idt_set_gate(3, isr_stub_3, 0x08, IDT_EXCEPTION);
+ idt_set_gate(4, isr_stub_4, 0x08, IDT_EXCEPTION);
+ idt_set_gate(5, isr_stub_5, 0x08, IDT_EXCEPTION);
+ idt_set_gate(6, isr_stub_6, 0x08, IDT_EXCEPTION);
+ idt_set_gate(7, isr_stub_7, 0x08, IDT_EXCEPTION);
+ idt_set_gate(8, isr_stub_8, 0x08, IDT_EXCEPTION);
+ idt_set_gate(9, isr_stub_9, 0x08, IDT_EXCEPTION);
+ idt_set_gate(10, isr_stub_10, 0x08, IDT_EXCEPTION);
+ idt_set_gate(11, isr_stub_11, 0x08, IDT_EXCEPTION);
+ idt_set_gate(12, isr_stub_12, 0x08, IDT_EXCEPTION);
+ idt_set_gate(13, isr_stub_13, 0x08, IDT_EXCEPTION);
+ idt_set_gate(14, isr_stub_14, 0x08, IDT_EXCEPTION);
+ idt_set_gate(15, isr_stub_15, 0x08, IDT_EXCEPTION);
+ idt_set_gate(16, isr_stub_16, 0x08, IDT_EXCEPTION);
+ idt_set_gate(17, isr_stub_17, 0x08, IDT_EXCEPTION);
+ idt_set_gate(18, isr_stub_18, 0x08, IDT_EXCEPTION);
+ idt_set_gate(19, isr_stub_19, 0x08, IDT_EXCEPTION);
+ idt_set_gate(20, isr_stub_20, 0x08, IDT_EXCEPTION);
+ idt_set_gate(21, isr_stub_21, 0x08, IDT_EXCEPTION);
+ idt_set_gate(22, isr_stub_22, 0x08, IDT_EXCEPTION);
+ idt_set_gate(23, isr_stub_23, 0x08, IDT_EXCEPTION);
+ idt_set_gate(24, isr_stub_24, 0x08, IDT_EXCEPTION);
+ idt_set_gate(25, isr_stub_25, 0x08, IDT_EXCEPTION);
+ idt_set_gate(26, isr_stub_26, 0x08, IDT_EXCEPTION);
+ idt_set_gate(27, isr_stub_27, 0x08, IDT_EXCEPTION);
+ idt_set_gate(28, isr_stub_28, 0x08, IDT_EXCEPTION);
+ idt_set_gate(29, isr_stub_29, 0x08, IDT_EXCEPTION);
+ idt_set_gate(30, isr_stub_30, 0x08, IDT_EXCEPTION);
+ idt_set_gate(31, isr_stub_31, 0x08, IDT_EXCEPTION);
__asm__ volatile("lidt %0" : : "memory"(idtr));
__asm__ volatile("sti");
diff --git a/arch/i386/boot/isr.s b/arch/i386/boot/isr.s
index 43ef3be..b5f8be5 100644
--- a/arch/i386/boot/isr.s
+++ b/arch/i386/boot/isr.s
@@ -4,42 +4,74 @@
.global isr_stub_\num
.type isr_stub_\num, @function
isr_stub_\num:
- 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
+ jmp isr_frame_asm
.endm
.macro isr_no_err_stub num
.global isr_stub_\num
.type isr_stub_\num, @function
isr_stub_\num:
- cli
+ pushl $0
+ pushl $\num
+ jmp isr_frame_asm
+.endm
+
+isr_frame_asm:
+ pushl %ebp
+ movl %esp, %ebp
pushl %eax
+ pushl %ebx
+ pushl %ecx
pushl %ecx
pushl %edx
- pushl %ds
- pushl %esp
- pushl $\num
+ pushl %esi
+ pushl %edi
+
+ movl %cr0, %eax
+ pushl %eax
+ movl %cr2, %eax
+ pushl %eax
+ movl %cr3, %eax
+ pushl %eax
+ movl %cr4, %eax
+ pushl %eax
+
+ movw %ds, %ax
+ pushl %eax
+ pushl $0
+ movw $0x10, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+
+ lea 0xC(%esp), %edi
+ pushl %edi
call exception_handler
- popl %esp
- popl %ds
+
+ popl %eax
+ popl %eax
+ movw %ax, %ds
+ movw %ax, %es
+
+ popl %eax
+ movl %eax, %cr4
+ popl %eax
+ movl %eax, %cr3
+ popl %eax
+ movl %eax, %cr2
+ popl %eax
+ movl %eax, %cr0
+
+ popl %edi
+ popl %esi
popl %edx
popl %ecx
+ popl %ebx
popl %eax
- addl $8, %esp
+
+ popl %ebp
+ add $0x10, %esp
iret
-.endm
isr_no_err_stub 0
isr_no_err_stub 1
diff --git a/arch/i386/include/kernel/idt.h b/arch/i386/include/kernel/idt.h
index 7ccad30..699eb96 100644
--- a/arch/i386/include/kernel/idt.h
+++ b/arch/i386/include/kernel/idt.h
@@ -4,14 +4,14 @@
#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_PRESENT 0x80
+#define SEGMENT_RING0 0x00
+#define SEGMENT_RING3 0x60
+#define SEGMENT_STORAGE 0x00
+#define SEGMENT_INTERRUPT 0x0E
+#define IDT_EXCEPTION (SEGMENT_PRESENT | SEGMENT_INTERRUPT)
-#define SEGMENT_FLAG SEGMENT_PRESENT | SEGMENT_RING0 | SEGMENT_STORAGE |\
- SEGMENT_GATE | SEGMENT_DPL;
+#define IDT_MAX_DESCRIPTORS 256
struct idt_entry {
uint16_t isr_low;
@@ -26,10 +26,9 @@ struct idt_ptr {
uint32_t base;
} __attribute__((packed));
-extern struct idt_entry idt[256];
+extern struct idt_entry idt[IDT_MAX_DESCRIPTORS];
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
+#endif
diff --git a/arch/i386/include/kernel/isr.h b/arch/i386/include/kernel/isr.h
index a924cd6..61fe22f 100644
--- a/arch/i386/include/kernel/isr.h
+++ b/arch/i386/include/kernel/isr.h
@@ -1,6 +1,31 @@
#ifndef I386_ISR_H
#define I386_ISR_H
+#include <stdint.h>
+
+struct isr_frame {
+ uint32_t cr4;
+ uint32_t cr3;
+ uint32_t cr2;
+ uint32_t cr0;
+
+ uint32_t edi;
+ uint32_t esi;
+ uint32_t edx;
+ uint32_t ecx;
+ uint32_t ebx;
+ uint32_t eax;
+
+ uint32_t ebp;
+ uint32_t vector;
+ uint32_t errno;
+ uint32_t eip;
+ uint32_t cs;
+ uint32_t eflags;
+ uint32_t esp;
+ uint32_t dss;
+} __attribute__((packed));
+
extern void isr_stub_0(void);
extern void isr_stub_1(void);
extern void isr_stub_2(void);
@@ -34,4 +59,4 @@ 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
+#endif