/** * 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); 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; 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); } }