diff options
author | Aqua-sama <aqua@iserlohn-fortress.net> | 2021-03-06 16:01:29 +0200 |
---|---|---|
committer | Aqua-sama <aqua@iserlohn-fortress.net> | 2021-03-06 16:01:37 +0200 |
commit | e40da55691ad2c36b349ace7cd368394976a1d6d (patch) | |
tree | 5ffe26ab4306d2f1fe6eb9ce08dc119189f92e9b /src/gdt.cc | |
parent | libk: add int_t min max size constants (diff) | |
download | kernel.cpp-e40da55691ad2c36b349ace7cd368394976a1d6d.tar.xz |
GDT: flush segment registers on lgdt
Diffstat (limited to 'src/gdt.cc')
-rw-r--r-- | src/gdt.cc | 36 |
1 files changed, 28 insertions, 8 deletions
@@ -3,19 +3,39 @@ using seg = GDT::SegmentDescriptor; -GDT::GDT() - : segments{seg::make<0>(0, {.present = false}), // null segment - seg::make<0>(0, {.present = false}), // unused segment ??? - seg::make<0xffffffff>(0, {.r_w = true, .exe = true, .segment = true}), // code segment - seg::make<0xffffffff>(0, {.r_w = true, .segment = true})} // data segment -{ +static_assert(sizeof(GDT::Pointer) == 6); + +constexpr uint32_t null_sz = 0; +constexpr uint32_t kseg_sz = 64 * 1024 * 1024 + 0xfff; + +static GDT::SegmentDescriptor segments[256]{ + [GDT::null0] = seg::make<null_sz>(0, {}), + [GDT::kcode] = seg::make<kseg_sz>(0, {.r_w = true, .exe = true, .segment = true, .present = true}), + [GDT::kdata] = seg::make<kseg_sz>(0, {.r_w = true, .segment = true, .present = true}), +}; + +GDT::GDT() { Pointer gdtr{.limit = sizeof(segments) - 1, .base = reinterpret_cast<uint32_t>(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::codeDescriptor() const { - return static_cast<uint16_t>(reinterpret_cast<const uint32_t>(&segments[2]) - +uint16_t GDT::descriptor(GDT::SegmentMap i) const { + return static_cast<uint16_t>(reinterpret_cast<const uint32_t>(&segments[i]) - reinterpret_cast<const uint32_t>(&segments)); } |