From bc7fd3f2fcef59981bd6cb5e29ed5a2a3e8cd7af Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Sun, 4 Sep 2022 22:25:46 -0400 Subject: [PATCH] Add idt module and set up IDT --- src/hulk/gdt.d | 8 ++-- src/hulk/hulk.d | 2 + src/hulk/idt.d | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 src/hulk/idt.d diff --git a/src/hulk/gdt.d b/src/hulk/gdt.d index 83c41c6..313f457 100644 --- a/src/hulk/gdt.d +++ b/src/hulk/gdt.d @@ -14,10 +14,10 @@ struct gdt } static assert(gdtr_t.sizeof == 10u); - private enum size_t SELECTOR_NULL = 0x00u; - private enum size_t SELECTOR_KERNEL_CODE = 0x08u; - private enum size_t SELECTOR_KERNEL_DATA = 0x10u; - private enum size_t SELECTOR_COUNT = 3u; + public enum size_t SELECTOR_NULL = 0x00u; + public enum size_t SELECTOR_KERNEL_CODE = 0x08u; + public enum size_t SELECTOR_KERNEL_DATA = 0x10u; + public enum size_t SELECTOR_COUNT = 3u; static __gshared ulong[SELECTOR_COUNT] gdt; static __gshared gdtr_t gdtr; diff --git a/src/hulk/hulk.d b/src/hulk/hulk.d index 43c1284..d01f861 100644 --- a/src/hulk/hulk.d +++ b/src/hulk/hulk.d @@ -14,6 +14,7 @@ import hulk.hurl; import hulk.hippo; import hulk.pci; import hulk.gdt; +import hulk.idt; import hos.cpu; extern extern(C) __gshared ubyte _hulk_total_size; @@ -35,6 +36,7 @@ void hulk_start() { cli(); gdt.initialize(); + idt.initialize(); fb.initialize(cast(uint *)HULK_VIRTUAL_FRAMEBUFFER_ADDRESS, hulk_header.bootinfo.fb.width, hulk_header.bootinfo.fb.height, hulk_header.bootinfo.fb.stride); console.initialize(); console.clear(); diff --git a/src/hulk/idt.d b/src/hulk/idt.d new file mode 100644 index 0000000..6579b9a --- /dev/null +++ b/src/hulk/idt.d @@ -0,0 +1,105 @@ +/** + * IDT (Interrupt Descriptor Table) functionality. + */ +module hulk.idt; + +import hulk.gdt; +import ldc.llvmasm; +import hulk.fb; +import hulk.console; +import hulk.klog; + +struct idt +{ + struct idtr_t + { + ushort limit; + align(2) ulong offset; + } + static assert(idtr_t.sizeof == 10u); + + alias descriptor_t = ulong[2]; + + static __gshared align(0x10) descriptor_t[256] idt; + static assert(idt.sizeof == (256u * 16u)); + static __gshared idtr_t idtr; + + public static void initialize() + { + set_isrs(); + idtr.limit = idt.sizeof - 1u; + idtr.offset = cast(ulong)&idt; + lidt(&idtr); + } + + private static void lidt(idtr_t * idtr) + { + __asm("lidt $0", "*m", idtr); + } + + private static bool isr_has_error_code(size_t isr) + { + return (isr == 8) || + ((10 <= isr) && (isr <= 14)) || + (isr == 17) || + (isr == 21) || + (isr == 29) || + (isr == 30); + } + + private static bool isr_is_trap(size_t isr) + { + return (isr < 32u) && (isr != 2u); + } + + private static void set_isrs() + { + ulong isr_address; + static foreach(isr; 0 .. 256) + { + mixin("isr_address = __asm!ulong(` + movabs $$1f, %rax + jmp 2f + 1: + pushq %rdi + pushq %rsi + pushq %rax + mov $$", isr, ", %rdi + " ~ (isr_has_error_code(isr) ? "mov 0x18(%rsp), %rsi" : "") ~ " + movabs $$isr, %rax + callq *%rax + popq %rax + popq %rsi + popq %rdi + " ~ (isr_has_error_code(isr) ? "add $$8, %rsp" : "") ~ " + iretq + 2:`, `={rax}`);"); + mixin("set_descriptor(", isr, ", 0u, " ~ + (isr_is_trap(isr) ? "true" : "false") ~ ", isr_address);"); + } + } + + private static void set_descriptor(size_t index, ulong dpl, bool trap, ulong offset) + { + idt[index][0] = + 0x0000_8E_00_0000_0000u | + ((offset & 0xFFFF_0000u) << 32u) | + (dpl << 45u) | + ((trap ? 1uL : 0uL) << 40u) | + (gdt.SELECTOR_KERNEL_CODE << 16u) | + (offset & 0xFFFFu); + idt[index][1] = offset >> 32u; + } +} + +public extern(C) void isr(ulong vector, ulong arg) +{ + console.initialize(); + fb.clear(0xFF8000u); + klog.writefln("ISR %u, 0x%x", vector, arg); + __asm("cli", ""); + for (;;) + { + __asm("hlt", ""); + } +}