aboutsummaryrefslogtreecommitdiff
path: root/src/gdt.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/gdt.cc')
-rw-r--r--src/gdt.cc36
1 files changed, 28 insertions, 8 deletions
diff --git a/src/gdt.cc b/src/gdt.cc
index 9c86888..cb210a2 100644
--- a/src/gdt.cc
+++ b/src/gdt.cc
@@ -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));
}