summaryrefslogtreecommitdiffstats
path: root/arch/x86_64/hal/idt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/hal/idt.c')
-rw-r--r--arch/x86_64/hal/idt.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/arch/x86_64/hal/idt.c b/arch/x86_64/hal/idt.c
new file mode 100644
index 0000000..b2251bd
--- /dev/null
+++ b/arch/x86_64/hal/idt.c
@@ -0,0 +1,53 @@
+#include "idt.h"
+#include "smp.h"
+#include "gdt.h"
+#include "jove.h"
+#include "lib/printf.h"
+
+ALIGN(8)
+static struct idt_entry s_idt[IDT_ENTRIES];
+
+typedef void (*isr_t)(void);
+extern isr_t __isrs[IDT_ENTRIES];
+
+typedef struct int_stackframe *(*int_handler_t)(struct int_stackframe*);
+int_handler_t __int_handles[IDT_ENTRIES];
+
+static struct int_stackframe*
+s_int_handle_stub(struct int_stackframe* frame)
+{
+ kprintf("Unhandled interrupt %i at %p\n", frame->int_num, frame->int_rip);
+ hcf();
+}
+
+void
+idt_init(void)
+{
+ for(size_t i = 0; i < IDT_ENTRIES; i++) {
+ uintptr_t isr = (uintptr_t)(__isrs[i]);
+
+ s_idt[i] = (struct idt_entry) {
+ .offset_0_15 = (uint16_t)(isr & 0xFFFF),
+ .segment_selector = GDT_KERNEL_CODE * 8,
+ .ist = 0,
+ .type = IDT_INTERRUPT_GATE,
+ .dpl = 0,
+ .p = 1,
+ .offset_16_31 = (uint16_t)((isr >> 16) & 0xFFFF),
+ .offset_32_63 = (uint32_t)(isr >> 32)
+ };
+
+ __int_handles[i] = s_int_handle_stub;
+ }
+}
+
+void
+idt_setup(processor_t *processor)
+{
+ struct idt_descriptor idtr = (struct idt_descriptor) {
+ .limit = sizeof(struct idt_entry) * IDT_ENTRIES - 1,
+ .base = (uint64_t)&s_idt
+ };
+
+ __asm__ volatile("lidt %0":: "m"(idtr));
+}