diff --git a/src/hulk/gdt.d b/src/hulk/gdt.d new file mode 100644 index 0000000..83c41c6 --- /dev/null +++ b/src/hulk/gdt.d @@ -0,0 +1,58 @@ +/** + * GDT (Global Descriptor Table) functionality. + */ +module hulk.gdt; + +import ldc.llvmasm; + +struct gdt +{ + struct gdtr_t + { + ushort limit; + align(2) ulong offset; + } + 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; + + static __gshared ulong[SELECTOR_COUNT] gdt; + static __gshared gdtr_t gdtr; + + public static void initialize() + { + gdt[SELECTOR_KERNEL_CODE / ulong.sizeof] = 0x00_A_F_9A_000000_0000u; + gdt[SELECTOR_KERNEL_DATA / ulong.sizeof] = 0x00_C_F_92_000000_0000u; + gdtr.limit = gdt.sizeof - 1u; + gdtr.offset = cast(ulong)&gdt; + lgdt(&gdtr); + load_data_selectors(SELECTOR_KERNEL_DATA); + load_code_selector(SELECTOR_KERNEL_CODE); + } + + private static void lgdt(gdtr_t * gdtr) + { + __asm("lgdt $0", "*m", gdtr); + } + + private static void load_data_selectors(ulong selector) + { + __asm(`mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss`, "{rax}", selector); + } + + private static void load_code_selector(ulong selector) + { + __asm(`push %rax + movabs $$1f, %rax + push %rax + lretq + 1:`, "{rax}", selector); + } +} diff --git a/src/hulk/hulk.d b/src/hulk/hulk.d index 34283a8..f6c695d 100644 --- a/src/hulk/hulk.d +++ b/src/hulk/hulk.d @@ -13,6 +13,7 @@ import hulk.klog; import hulk.hurl; import hulk.hippo; import hulk.pci; +import hulk.gdt; extern extern(C) __gshared ubyte _hulk_total_size; @@ -31,6 +32,7 @@ private __gshared HulkHeader hulk_header = { */ void hulk_start() { + gdt.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();