#include "gdt.h" #include using seg = GDT::SegmentDescriptor; static_assert(sizeof(GDT::Pointer) == 6); constexpr uint32_t null_sz = 0; /* TODO kcode should only contain the .text segment * TODO kdata should contain the other segments * */ constexpr uint32_t kseg_start = 0; constexpr uint32_t kseg_sz = 0xffffffff; static GDT::SegmentDescriptor segments[256]{ [GDT::null0] = seg::make(0, {}), [GDT::kcode] = seg::make(kseg_start, {.r_w = true, .exe = true, .segment = true, .present = true}), [GDT::kdata] = seg::make(kseg_start, {.r_w = true, .segment = true, .present = true}), }; GDT::GDT() { Pointer gdtr{.limit = sizeof(segments) - 1, .base = reinterpret_cast(segments)}; asm volatile("lgdt %0" : : "p"(gdtr)); // flush the segment registers const auto cs = descriptor(kcode); const auto ds = descriptor(kdata); asm volatile( "jmp %0,$.reload_cs\n\t" // far jump takes cs ".reload_cs:\n\t" " mov %1, %%ds\n\t" // ds " mov %1, %%es\n\t" " mov %1, %%fs\n\t" " mov %1, %%gs\n\t" " mov %1, %%ss\n\t" ::"i"(cs), "r"(ds)); printk("GDT installed at ", uhex{gdtr.base}, '\n'); } uint16_t GDT::descriptor(GDT::SegmentMap i) const { return static_cast(reinterpret_cast(&segments[i]) - reinterpret_cast(&segments)); }