From e87e6e387138a3ad01e0b6523bd648f26fffb040 Mon Sep 17 00:00:00 2001 From: Nathan Singer Date: Thu, 29 May 2025 11:33:40 -0400 Subject: [PATCH] adds an idt --- kernel/arch/idt/idt.c | 43 ++++++++++++++++++++++++++ kernel/arch/idt/idt_src.s | 54 +++++++++++++++++++++++++++++++++ kernel/include/kernel/x86/idt.h | 26 ++++++++++++++++ kernel/kmain.c | 2 ++ 4 files changed, 125 insertions(+) create mode 100644 kernel/arch/idt/idt.c create mode 100644 kernel/arch/idt/idt_src.s create mode 100644 kernel/include/kernel/x86/idt.h diff --git a/kernel/arch/idt/idt.c b/kernel/arch/idt/idt.c new file mode 100644 index 0000000..5be9f1a --- /dev/null +++ b/kernel/arch/idt/idt.c @@ -0,0 +1,43 @@ +#include + +#include + +__attribute__((aligned(0x10))) +static idt_entry_t idt[256]; + +static idtr_t idtr; + +static bool vectors[IDT_MAX_DESCRIPTORS]; + +void exception_handler() +{ + __asm__ volatile ("cli; hlt"); // hangs the computer +} + +void idt_set_descriptor(uint8_t vector, void *isr, uint8_t flags) +{ + idt_entry_t* descriptor = &idt[vector]; + + descriptor->isr_low = (uint32_t) isr & 0xFFFF; + descriptor->kernel_cs = 0x08; // this is whatever the kernel code selector is in the GDT + descriptor->attributes = flags; + descriptor->isr_high = (uint32_t) isr >> 16; + descriptor->reserved = 0; +} + + +extern void* isr_stub_table[]; +void idt_init(void) +{ + idtr.base = (uintptr_t)&idt[0]; + idtr.limit = (uint16_t) sizeof(idt_entry_t) * IDT_MAX_DESCRIPTORS - 1; + + for (uint8_t vector = 0; vector < 32; vector++) { + idt_set_descriptor(vector, isr_stub_table[vector], 0x8E); + vectors[vector] = true; + } + + __asm__ volatile("lidt %0" : : "m"(idtr)); // load the new IDT + __asm__ volatile("sti"); // set the interrupt flag +} + diff --git a/kernel/arch/idt/idt_src.s b/kernel/arch/idt/idt_src.s new file mode 100644 index 0000000..176a639 --- /dev/null +++ b/kernel/arch/idt/idt_src.s @@ -0,0 +1,54 @@ +extern exception_handler + +%macro isr_err_stub 1 +isr_stub_%+%1: + call exception_handler + iret +%endmacro + +%macro isr_no_err_stub 1 +isr_stub_%+%1: + call exception_handler + iret +%endmacro + +isr_no_err_stub 0 +isr_no_err_stub 1 +isr_no_err_stub 2 +isr_no_err_stub 3 +isr_no_err_stub 4 +isr_no_err_stub 5 +isr_no_err_stub 6 +isr_no_err_stub 7 +isr_err_stub 8 +isr_no_err_stub 9 +isr_err_stub 10 +isr_err_stub 11 +isr_err_stub 12 +isr_err_stub 13 +isr_err_stub 14 +isr_no_err_stub 15 +isr_no_err_stub 16 +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_no_err_stub 22 +isr_no_err_stub 23 +isr_no_err_stub 24 +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 30 +isr_no_err_stub 31 + +global isr_stub_table +isr_stub_table: +%assign i 0 +%rep 32 + dd isr_stub_%+i +%assign i i+1 +%endrep diff --git a/kernel/include/kernel/x86/idt.h b/kernel/include/kernel/x86/idt.h new file mode 100644 index 0000000..968507d --- /dev/null +++ b/kernel/include/kernel/x86/idt.h @@ -0,0 +1,26 @@ +#include + +#ifndef ARCH_IDT_H +#define ARCH_IDT_H + +#define IDT_MAX_DESCRIPTORS 32 // number of entries in the idt table, 32 i believe + +void exception_handler(void); + +typedef struct { + uint16_t isr_low; // The lower 16 bits of the ISR's address + uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR + uint8_t reserved; // set to zero + uint8_t attributes; // Type and attributes + uint16_t isr_high; // The higher 16 bits of the ISR's address +} __attribute__((packed)) idt_entry_t; + +typedef struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)) idtr_t; + +void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags); +void idt_init(void); + +#endif diff --git a/kernel/kmain.c b/kernel/kmain.c index 76f9e77..fc0fe92 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -4,6 +4,7 @@ #include #include #include +#include #define GDT_SIZE 5 @@ -27,6 +28,7 @@ void gdt_init(void) void kmain(void) { gdt_init(); + idt_init(); terminal_initialize(); serial_initialize();