summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVegard Storheil Eriksen <zyp@jvnv.net>2010-01-09 17:56:48 +0100
committerVegard Storheil Eriksen <zyp@jvnv.net>2010-01-09 17:56:48 +0100
commit51a6ac67b761182d67eeb2f625d8476a2e79e632 (patch)
tree829809e758bfd3e0005dc0905ac9ad4cbf5f0ef9
parent5fe4102bc546b95d42d357f418f64c372d26b903 (diff)
Rudimentary interrupt handling.
-rw-r--r--kernel/SConscript2
-rw-r--r--kernel/idt.c63
-rw-r--r--kernel/idt.h32
-rw-r--r--kernel/main.c4
4 files changed, 100 insertions, 1 deletions
diff --git a/kernel/SConscript b/kernel/SConscript
index d9988ac..856d2b5 100644
--- a/kernel/SConscript
+++ b/kernel/SConscript
@@ -27,4 +27,4 @@ kernel_bld = Builder(
env.Append(BUILDERS = {'Kernel' : kernel_bld})
-kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c', 'gdt.c'])
+kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c', 'gdt.c', 'idt.c'])
diff --git a/kernel/idt.c b/kernel/idt.c
new file mode 100644
index 0000000..3fdc3dc
--- /dev/null
+++ b/kernel/idt.c
@@ -0,0 +1,63 @@
+#include "idt.h"
+
+#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port));
+
+#define isr_panic(num) void isr_ ## num(); \
+asm( \
+ ".globl isr_" #num "\n" \
+ "isr_" #num ":\n" \
+ "push $" #num "\n" \
+ "call panic\n" \
+ "iret\n" \
+)
+
+char* panic_msg[] = {
+ [0] = "Divide error.",
+ [8] = "Double fault.",
+ [14] = "Page fault."
+};
+
+isr_panic(0);
+isr_panic(8);
+isr_panic(14);
+
+void panic(uint32_t num) {
+ char* str = panic_msg[num];
+ while(*str) {
+ outb(0x3f8, *str++);
+ }
+ outb(0x3f8, '\r');
+ outb(0x3f8, '\n');
+ asm volatile(
+ "cli\n"
+ "hlt\n"
+ );
+ while(1);
+}
+
+idt_entry idt[] = {
+ {.base_low = 1}, // Keep IDT in .data.
+ [1 ... 255] = idt_entry_null
+};
+
+idt_ptr idtr = {
+ .base = idt,
+ .limit = sizeof(idt) - 1
+};
+
+void idt_set_gate(uint8_t num, uint32_t base, uint16_t segment, uint16_t flags) {
+ idt[num].base_low = base & 0xffff;
+ idt[num].base_high = base >> 16 & 0xffff;
+ idt[num].segment = segment;
+ idt[num].flags = flags;
+}
+
+void idt_init() {
+ idt_set_gate(0, (uint32_t)isr_0, 0x08, 0x8e00);
+ idt_set_gate(8, (uint32_t)isr_8, 0x08, 0x8e00);
+ idt_set_gate(14, (uint32_t)isr_14, 0x08, 0x8e00);
+ asm volatile(
+ "lidt (%0)\n"
+ : : "r" (&idtr)
+ );
+}
diff --git a/kernel/idt.h b/kernel/idt.h
new file mode 100644
index 0000000..aafa477
--- /dev/null
+++ b/kernel/idt.h
@@ -0,0 +1,32 @@
+#ifndef IDT_H
+#define IDT_H
+
+#include "types.h"
+
+typedef struct {
+ uint16_t base_low;
+ uint16_t segment;
+ uint16_t flags;
+ uint16_t base_high;
+} __attribute__((packed)) idt_entry;
+
+typedef struct {
+ uint16_t limit;
+ idt_entry* base;
+} __attribute__((packed)) idt_ptr;
+
+#define idt_entry_init(b, s, f) { \
+ .base_low = (b & 0xffff), \
+ .base_high = (b >> 16 & 0xffff), \
+ .segment = (s), \
+ .flags = (f)}
+
+#define idt_entry_null { \
+ .base_low = 0, \
+ .base_high = 0, \
+ .segment = 0, \
+ .flags = 0}
+
+void idt_init();
+
+#endif
diff --git a/kernel/main.c b/kernel/main.c
index 25ad1f1..cc0dc35 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -1,4 +1,5 @@
#include "gdt.h"
+#include "idt.h"
void kernel_serial_out(char* str);
@@ -9,6 +10,9 @@ void main() {
gdt_init();
kernel_serial_out("GDT set.\n");
+ idt_init();
+ kernel_serial_out("IDT set.\n");
+
kernel_serial_out("Halting.\n");
asm volatile(