diff options
-rw-r--r-- | kernel/SConscript | 2 | ||||
-rw-r--r-- | kernel/idt.c | 63 | ||||
-rw-r--r-- | kernel/idt.h | 32 | ||||
-rw-r--r-- | kernel/main.c | 4 |
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( |