Nucleus
Barry Improved context switching and interrupt handling d46e09a (3 years, 2 months ago)
diff --git a/kernel/idt.c b/kernel/idt.c
index d835d15..a9f7c79 100644
--- a/kernel/idt.c
+++ b/kernel/idt.c
@@ -21,7 +21,7 @@ static struct IDTEntry {
uint16_t offsetHigher;
} __attribute__((packed)) *IDT;
-void (**exceptions)(struct InterruptFrame *, uint32_t);
+void (**exceptions)(struct InterruptFrame *);
void (**interrupts)(struct InterruptFrame *);
/* Install an IDT Entry */
@@ -35,294 +35,57 @@ install_idt_entry(uint8_t num, void *addr)
IDT[num].offsetHigher = (uintptr_t) addr >> 16;
}
-/* First level generic exception handler */
-static void
-exc_handler(int num, struct InterruptFrame *frame, uint32_t err)
-{
- asm volatile("cli");
-
- if (!exceptions[num]) {
- panic("Failed to handle exception %d (%#.8x)",
- num, err);
- }
-
- ASSERT(exceptions[num]);
- exceptions[num](frame, err);
-
- /* Send APIC EOI */
- if (apic)
- LAPIC(0xB0) = 0;
-
- asm volatile("sti");
-}
-
-/* First level generic interrupt handler */
-static void
-int_handler(int num, struct InterruptFrame *frame)
+/* Generic ISR handler */
+void
+isr_handler(struct InterruptFrame frame)
{
- asm volatile("cli");
+ if (!exceptions[frame.intnum] && frame.intnum < 32)
+ panic("[CPU#%d] Failed to handle exception %d (%#.8x) @ %#.8x",
+ CPUID, frame.intnum, frame.err, frame.eip);
- if (interrupts[num - 32])
- interrupts[num - 32](frame);
+ /* Run registered handler */
+ if (exceptions[frame.intnum])
+ exceptions[frame.intnum](&frame);
/* Send EOI */
- if (num >= 32 + 8)
+ if (frame.intnum >= 40 && frame.intnum < 48)
outb(0xA0, 0x20);
- outb(0x20, 0x20);
- /* Send APIC EOI*/
- if (apic)
- LAPIC(0xB0) = 0;
-
- asm volatile("sti");
-}
-
-/* Exceptions */
-__attribute__((interrupt))
-static void
-exc0(struct InterruptFrame *frame)
-{
- exc_handler(0, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc1(struct InterruptFrame *frame)
-{
- exc_handler(1, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc2(struct InterruptFrame *frame)
-{
- exc_handler(2, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc3(struct InterruptFrame *frame)
-{
- exc_handler(3, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc4(struct InterruptFrame *frame)
-{
- exc_handler(4, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc5(struct InterruptFrame *frame)
-{
- exc_handler(5, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc6(struct InterruptFrame *frame)
-{
- exc_handler(6, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc7(struct InterruptFrame *frame)
-{
- exc_handler(7, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc8(struct InterruptFrame *frame, uint32_t err)
-{
- exc_handler(8, frame, err);
-}
-__attribute__((interrupt))
-static void
-exc9(struct InterruptFrame *frame)
-{
- exc_handler(9, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc10(struct InterruptFrame *frame, uint32_t err)
-{
- exc_handler(10, frame, err);
-}
-__attribute__((interrupt))
-static void
-exc11(struct InterruptFrame *frame, uint32_t err)
-{
- exc_handler(11, frame, err);
-}
-__attribute__((interrupt))
-static void
-exc12(struct InterruptFrame *frame, uint32_t err)
-{
- exc_handler(12, frame, err);
-}
-__attribute__((interrupt))
-static void
-exc13(struct InterruptFrame *frame, uint32_t err)
-{
- exc_handler(13, frame, err);
-}
-__attribute__((interrupt))
-static void
-exc14(struct InterruptFrame *frame, uint32_t err)
-{
- exc_handler(14, frame, err);
-}
-__attribute__((interrupt))
-static void
-exc15(struct InterruptFrame *frame)
-{
- exc_handler(15, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc16(struct InterruptFrame *frame)
-{
- exc_handler(16, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc17(struct InterruptFrame *frame, uint32_t err)
-{
- exc_handler(17, frame, err);
-}
-__attribute__((interrupt))
-static void
-exc18(struct InterruptFrame *frame)
-{
- exc_handler(18, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc19(struct InterruptFrame *frame)
-{
- exc_handler(19, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc20(struct InterruptFrame *frame)
-{
- exc_handler(20, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc30(struct InterruptFrame *frame)
-{
- exc_handler(30, frame, 0);
-}
-__attribute__((interrupt))
-static void
-exc128(struct InterruptFrame *frame)
-{
- uintptr_t esi, *eax;
- asm volatile(
- "mov %%esi, %0;"
- "lea -12(%%ebp), %1;"
- : "=r" (esi), "=r" (eax));
- *eax = syscall_handler(*eax, esi);
+ if (frame.intnum >= 32 && frame.intnum < 48)
+ outb(0x20, 0x20);
/* Send APIC EOI */
if (apic)
LAPIC(0xB0) = 0;
}
-/* Interrupts */
-__attribute__((interrupt))
-static void
-int0(struct InterruptFrame *frame)
-{
- int_handler(32, frame);
-}
-__attribute__((interrupt))
-static void
-int1(struct InterruptFrame *frame)
-{
- int_handler(33, frame);
-}
-__attribute__((interrupt))
-static void
-int2(struct InterruptFrame *frame)
-{
- int_handler(34, frame);
-}
-__attribute__((interrupt))
-static void
-int3(struct InterruptFrame *frame)
-{
- int_handler(35, frame);
-}
-__attribute__((interrupt))
-static void
-int4(struct InterruptFrame *frame)
-{
- int_handler(36, frame);
-}
-__attribute__((interrupt))
-static void
-int5(struct InterruptFrame *frame)
-{
- int_handler(37, frame);
-}
-__attribute__((interrupt))
-static void
-int6(struct InterruptFrame *frame)
-{
- int_handler(38, frame);
-}
-__attribute__((interrupt))
-static void
-int7(struct InterruptFrame *frame)
-{
- int_handler(39, frame);
-}
-__attribute__((interrupt))
-static void
-int8(struct InterruptFrame *frame)
-{
- int_handler(40, frame);
-}
-__attribute__((interrupt))
-static void
-int9(struct InterruptFrame *frame)
-{
- int_handler(41, frame);
-}
-__attribute__((interrupt))
-static void
-int10(struct InterruptFrame *frame)
-{
- int_handler(42, frame);
-}
-__attribute__((interrupt))
-static void
-int11(struct InterruptFrame *frame)
-{
- int_handler(43, frame);
-}
-__attribute__((interrupt))
-static void
-int12(struct InterruptFrame *frame)
-{
- int_handler(44, frame);
-}
-__attribute__((interrupt))
-static void
-int13(struct InterruptFrame *frame)
-{
- int_handler(45, frame);
-}
-__attribute__((interrupt))
-static void
-int14(struct InterruptFrame *frame)
+/* Register an exception handler */
+void
+register_exception(int num, exc_handler_t addr)
{
- int_handler(46, frame);
+ if ((num >= 0 && num < 32) || num >= 48)
+ exceptions[num] = addr;
}
-__attribute__((interrupt))
-static void
-int15(struct InterruptFrame *frame)
+
+/* Register an interrupt handler */
+void
+register_interrupt(int num, int_handler_t addr)
{
- int_handler(47, frame);
+ if (num >= 0 && num < 16)
+ interrupts[num] = addr;
}
+/* Exceptions */
+extern char exc0[], exc1[], exc2[], exc3[], exc4[], exc5[], exc6[],
+ exc7[], exc8[], exc9[], exc10[], exc11[], exc12[], exc13[],
+ exc14[], exc15[], exc16[], exc17[], exc18[], exc19[], exc20[],
+ exc30[];
+/* Interrutps */
+extern char exc32[], exc33[], exc34[], exc35[], exc36[], exc37[], exc38[],
+ exc39[], exc40[], exc41[], exc42[], exc43[], exc44[], exc45[],
+ exc46[], exc47[];
+/* System Call */
+extern char exc128[];
+
/* Initialise the IDT */
void
init_idt(void)
@@ -354,22 +117,22 @@ init_idt(void)
install_idt_entry(30, exc30);
/* Install interrupts */
- install_idt_entry(32, int0);
- install_idt_entry(33, int1);
- install_idt_entry(34, int2);
- install_idt_entry(35, int3);
- install_idt_entry(36, int4);
- install_idt_entry(37, int5);
- install_idt_entry(38, int6);
- install_idt_entry(39, int7);
- install_idt_entry(40, int8);
- install_idt_entry(41, int9);
- install_idt_entry(42, int10);
- install_idt_entry(43, int11);
- install_idt_entry(44, int12);
- install_idt_entry(45, int13);
- install_idt_entry(46, int14);
- install_idt_entry(47, int15);
+ install_idt_entry(32, exc32);
+ install_idt_entry(33, exc33);
+ install_idt_entry(34, exc34);
+ install_idt_entry(35, exc35);
+ install_idt_entry(36, exc36);
+ install_idt_entry(37, exc37);
+ install_idt_entry(38, exc38);
+ install_idt_entry(39, exc39);
+ install_idt_entry(40, exc40);
+ install_idt_entry(41, exc41);
+ install_idt_entry(42, exc42);
+ install_idt_entry(43, exc43);
+ install_idt_entry(44, exc44);
+ install_idt_entry(45, exc45);
+ install_idt_entry(46, exc46);
+ install_idt_entry(47, exc47);
/* Install system call handler */
install_idt_entry(128, exc128);
@@ -389,19 +152,3 @@ cpu_load_idt(void)
};
asm volatile("lidt %0" :: "m" (ptr));
}
-
-/* Register an exception handler */
-void
-register_exception(int num, exc_handler_t addr)
-{
- if (num >= 0 && num < 32)
- exceptions[num] = addr;
-}
-
-/* Register an interrupt handler */
-void
-register_interrupt(int num, int_handler_t addr)
-{
- if (num >= 0 && num < 224)
- interrupts[num] = addr;
-}
diff --git a/kernel/isr.S b/kernel/isr.S
new file mode 100644
index 0000000..c807e7b
--- /dev/null
+++ b/kernel/isr.S
@@ -0,0 +1,94 @@
+/*
+ * This file contains the interrupt service routine stubs. For the most part
+ * they just call into the generic handlers after setting up the stack for them.
+ */
+
+.extern isr_handler
+
+/* Exception with an error */
+.macro exc_err num
+.globl exc\num
+exc\num:
+ cli
+ push $\num
+ jmp isr_stub
+.endm
+/* Exception without an error */
+.macro exc_noerr num
+.globl exc\num
+exc\num:
+ cli
+ push $0
+ push $\num
+ jmp isr_stub
+.endm
+
+/* Exceptions */
+EXC_NOERR 0
+EXC_NOERR 1
+EXC_NOERR 2
+EXC_NOERR 3
+EXC_NOERR 4
+EXC_NOERR 5
+EXC_NOERR 6
+EXC_NOERR 7
+EXC_ERR 8
+EXC_NOERR 9
+EXC_ERR 10
+EXC_ERR 11
+EXC_ERR 12
+EXC_ERR 13
+EXC_ERR 14
+EXC_NOERR 15
+EXC_NOERR 16
+EXC_ERR 17
+EXC_NOERR 18
+EXC_NOERR 19
+EXC_NOERR 20
+EXC_NOERR 30
+/* Interrupts */
+EXC_NOERR 32
+EXC_NOERR 33
+EXC_NOERR 34
+EXC_NOERR 35
+EXC_NOERR 36
+EXC_NOERR 37
+EXC_NOERR 38
+EXC_NOERR 39
+EXC_NOERR 40
+EXC_NOERR 41
+EXC_NOERR 42
+EXC_NOERR 43
+EXC_NOERR 44
+EXC_NOERR 45
+EXC_NOERR 46
+EXC_NOERR 47
+/* System Call */
+EXC_NOERR 128
+
+/* Generic ISR stub */
+isr_stub:
+ pusha
+ mov %ds, %ax
+ pushl %eax
+
+ /* Switch to kernel segments */
+ mov $0x10, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+
+ call isr_handler
+
+ /* Restore original segments */
+ popl %ebx
+ mov %bx, %ds
+ mov %bx, %es
+ mov %bx, %fs
+ mov %bx, %gs
+
+ popa
+ addl $8, %esp
+ sti
+ iret
diff --git a/kernel/main.c b/kernel/main.c
index 5d95c4a..bf1fd8c 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -18,7 +18,7 @@
#include "acpi/acpi.h"
extern char _bss[], _end[];
-void page_fault_handler(struct InterruptFrame *frame, uint32_t err);
+void page_fault_handler(struct InterruptFrame *frame);
/* Per-CPU Setup */
void
diff --git a/kernel/panic.c b/kernel/panic.c
index a489a0a..2c07d24 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -30,8 +30,6 @@ panic(char *fmt, ...)
outb(0xE9, '\n');
/* Halt processor */
- asm volatile("cli");
- while (1)
- asm volatile("hlt");
+ while (1) asm volatile("cli; hlt");
__builtin_unreachable();
}