summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/i386/boot/crti.s4
-rw-r--r--arch/i386/boot/idt.c104
-rw-r--r--arch/i386/boot/isr.s45
-rw-r--r--arch/i386/include/kernel/idt.h1
-rw-r--r--arch/i386/include/kernel/isr.h5
5 files changed, 128 insertions, 31 deletions
diff --git a/arch/i386/boot/crti.s b/arch/i386/boot/crti.s
index 4e1e4cb..8386b77 100644
--- a/arch/i386/boot/crti.s
+++ b/arch/i386/boot/crti.s
@@ -1,15 +1,15 @@
.section .init
+
.global _init
.type _init, @function
-
_init:
pushl %ebp
movl %esp, %ebp
.section .fini
+
.global _fini
.type _fini, @function
-
_fini:
pushl %ebp
movl %esp, %ebp
diff --git a/arch/i386/boot/idt.c b/arch/i386/boot/idt.c
index d741381..dbcfaa2 100644
--- a/arch/i386/boot/idt.c
+++ b/arch/i386/boot/idt.c
@@ -5,17 +5,113 @@
#include <kernel/string.h>
#include <stdint.h>
+#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 IDT_INTERRUPT (SEGMENT_PRESENT | SEGMENT_INTERRUPT)
+
+#define IDT_MAX_DESCRIPTORS 256
+
+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));
+
__attribute__((aligned(0x10)))
struct idt_entry idt[256];
struct idt_ptr idtr;
+char *exceptions[] = {
+ "Division by zero",
+ "Debug",
+ "Non-maskable interrupt",
+ "Breakpoint",
+ "Overflow",
+ "Out-of-bounds",
+ "Invalid opcode",
+ "FPU not available",
+ "Double fault",
+ "RESERVED",
+ "Invalid TSS",
+ "Segment not present",
+ "Stack fault",
+ "General protection fault",
+ "Page fault",
+ "RESERVED",
+ "FPU exception",
+ "Alignment check",
+ "Machine check",
+ "FPU-SIMD exception",
+ "Virtualization exception",
+ "Control protection"
+ "RESERVED",
+ "Hypervisor injection",
+ "VMM exception",
+ "Security exception",
+ "RESERVED",
+ "Triple fault",
+ "RESERVED"
+};
+
__attribute__((noreturn))
-void exception_handler(struct isr_frame *frame) {
- kprintf("Error: CPU exception: %d\n", frame->vector);
+void halt_catch_fire(struct isr_frame *frame) {
+ kprintf("Registers at interrupt:\n");
+ kprintf("\tEAX = %x\n", frame->eax);
+ kprintf("\tEBX = %x\n", frame->ebx);
+ kprintf("\tECX = %x\n", frame->ecx);
+ kprintf("\tEDX = %x\n", frame->edx);
+ kprintf("\tESI = %x\n", frame->esi);
+ kprintf("\tEDI = %x\n", frame->edi);
+ kprintf("\tESP = %x\n", frame->esp);
+ kprintf("\tEBP = %x\n", frame->ebp);
+ kprintf("\tEIP = %x\n", frame->eip);
+ kprintf("\tEFLAGS = %x\n", frame->eflags);
+ kprintf("Current code selector: %d\n", frame->cs);
__asm__ volatile("cli;hlt");
}
-extern void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_t flags) {
+__attribute__((noreturn))
+void exception_handler(struct isr_frame *frame) {
+ switch (frame->vector) {
+ default:
+ kprintf("Unhandled exception: %s\n", exceptions[frame->vector]);
+ halt_catch_fire(frame);
+ }
+}
+
+void irq_dispatch(uint8_t irq, struct isr_frame *frame) {
+ return;
+}
+
+__attribute__((noreturn))
+void interrupt_handler(struct isr_frame *frame) {
+ if (frame->vector < 32)
+ exception_handler(frame);
+ else if (frame->vector > 32 && frame->vector < 48)
+ irq_dispatch(frame->vector - 16, frame);
+ switch (frame->vector) {
+ case 0x80:
+ syscall_dispatch(frame);
+ break;
+ default:
+ kprintf("Error: Unmapped interrupt: %d\n", frame->vector);
+ halt_catch_fire(frame);
+ __asm__ volatile("cli;hlt");
+ }
+}
+
+void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_t 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);
@@ -26,7 +122,7 @@ extern void idt_set_gate(uint8_t num, void (*handler)(void), uint16_t cs, uint8_
void idt_install(void) {
idtr.limit = (uint16_t)sizeof(struct idt_entry) * 256 - 1;
- idtr.base = (uint32_t)&idt[0];
+ idtr.base = (uint32_t)idt;
idt_set_gate(0, isr_stub_0, 0x08, IDT_EXCEPTION);
idt_set_gate(1, isr_stub_1, 0x08, IDT_EXCEPTION);
diff --git a/arch/i386/boot/isr.s b/arch/i386/boot/isr.s
index b5f8be5..76afa9f 100644
--- a/arch/i386/boot/isr.s
+++ b/arch/i386/boot/isr.s
@@ -4,6 +4,7 @@
.global isr_stub_\num
.type isr_stub_\num, @function
isr_stub_\num:
+ cli
pushl $\num
jmp isr_frame_asm
.endm
@@ -11,18 +12,32 @@ isr_stub_\num:
.global isr_stub_\num
.type isr_stub_\num, @function
isr_stub_\num:
+ cli
pushl $0
pushl $\num
jmp isr_frame_asm
.endm
+.macro irq_stub num
+.global irq_stub_\num
+.type irq_stub_\num, @function
+irq_stub_\num:
+ cli
+ pushl $0
+ pushl $\num
+ jmp isr_frame_asm
+.endm
+
+.global syscall_stub
+syscall_stub:
+ pushl $0
+ pushl $0x80
+ jmp isr_frame_asm
+
isr_frame_asm:
- pushl %ebp
- movl %esp, %ebp
pushl %eax
pushl %ebx
pushl %ecx
- pushl %ecx
pushl %edx
pushl %esi
pushl %edi
@@ -36,22 +51,9 @@ isr_frame_asm:
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
+ lea -8(%esp), %edi
pushl %edi
- call exception_handler
-
- popl %eax
- popl %eax
- movw %ax, %ds
- movw %ax, %es
+ call interrupt_handler
popl %eax
movl %eax, %cr4
@@ -69,8 +71,7 @@ isr_frame_asm:
popl %ebx
popl %eax
- popl %ebp
- add $0x10, %esp
+ addl $4, %esp
iret
isr_no_err_stub 0
@@ -94,7 +95,7 @@ isr_err_stub 17
isr_no_err_stub 18
isr_no_err_stub 19
isr_no_err_stub 20
-isr_no_err_stub 21
+isr_err_stub 21
isr_no_err_stub 22
isr_no_err_stub 23
isr_no_err_stub 24
@@ -102,6 +103,6 @@ isr_no_err_stub 25
isr_no_err_stub 26
isr_no_err_stub 27
isr_no_err_stub 28
-isr_no_err_stub 29
+isr_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
diff --git a/arch/i386/include/kernel/idt.h b/arch/i386/include/kernel/idt.h
index 699eb96..190e15e 100644
--- a/arch/i386/include/kernel/idt.h
+++ b/arch/i386/include/kernel/idt.h
@@ -10,6 +10,7 @@
#define SEGMENT_STORAGE 0x00
#define SEGMENT_INTERRUPT 0x0E
#define IDT_EXCEPTION (SEGMENT_PRESENT | SEGMENT_INTERRUPT)
+#define IDT_INTERRUPT (SEGMENT_PRESENT | SEGMENT_INTERRUPT)
#define IDT_MAX_DESCRIPTORS 256
diff --git a/arch/i386/include/kernel/isr.h b/arch/i386/include/kernel/isr.h
index 61fe22f..9d88958 100644
--- a/arch/i386/include/kernel/isr.h
+++ b/arch/i386/include/kernel/isr.h
@@ -11,19 +11,18 @@ struct isr_frame {
uint32_t edi;
uint32_t esi;
+ uint32_t ebp;
+ uint32_t esp;
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);