aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-03-06 16:01:29 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-03-06 16:01:37 +0200
commite40da55691ad2c36b349ace7cd368394976a1d6d (patch)
tree5ffe26ab4306d2f1fe6eb9ce08dc119189f92e9b
parentlibk: add int_t min max size constants (diff)
downloadkernel.cpp-e40da55691ad2c36b349ace7cd368394976a1d6d.tar.xz
GDT: flush segment registers on lgdt
-rw-r--r--src/gdt.cc36
-rw-r--r--src/gdt.h41
-rw-r--r--src/gdt/segmentdescriptor.cc10
-rw-r--r--src/idt.cc1
-rw-r--r--src/idt.h2
-rw-r--r--src/kernel.cc5
-rw-r--r--toolchain.makefile2
7 files changed, 62 insertions, 35 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));
}
diff --git a/src/gdt.h b/src/gdt.h
index bb7181b..6aeaa33 100644
--- a/src/gdt.h
+++ b/src/gdt.h
@@ -27,11 +27,6 @@
class GDT {
public:
- GDT();
- ~GDT() = default;
-
- uint16_t codeDescriptor() const;
-
struct Pointer {
uint16_t limit;
uint32_t base;
@@ -41,18 +36,24 @@ public:
public:
enum Ring : unsigned int { Ring0 = 0x0, Ring1 = 0x1, Ring2 = 0x2, Ring3 = 0x3 };
struct Access {
- bool accessed : 1 = false; // if 0, is set by processor when accessed
- bool r_w : 1 = false; // on code segment: read toggle
- // on data segment: write toggle
- bool direction_conforming : 1 = false; // TODO
- bool exe : 1 = false; // true for code segment, false for data segment
- bool segment : 1 = false; // segment bit: 1 for code/data segments
- // 0 for gates and tss
- Ring privilege : 2 = Ring0; // descriptor privilege level
- bool present : 1 = true; // must be 1 for every active segment
+ bool accessed : 1 = false; // if 0, is set by processor when accessed
+ bool r_w : 1 = false; // on code segment: read toggle
+ // on data segment: write toggle
+ bool direction : 1 = false; // TODO
+ bool exe : 1 = false; // true for code segment, false for data segment
+ bool segment : 1 = false; // segment bit: 1 for code/data segments
+ // 0 for gates and tss
+ Ring privilege : 2 = Ring0; // descriptor privilege level
+ bool present : 1 = false; // must be 1 for every active segment
+
+ constexpr operator uint8_t() const {
+ return static_cast<uint8_t>(accessed) | static_cast<uint8_t>(r_w << 1) | static_cast<uint8_t>(direction << 2) |
+ static_cast<uint8_t>(exe << 3) | static_cast<uint8_t>(segment << 4) |
+ static_cast<uint8_t>(privilege << 5) | static_cast<uint8_t>(present << 7);
+ }
} __attribute__((packed));
- SegmentDescriptor() { access.present = false; };
+ constexpr SegmentDescriptor() { access.present = false; };
template <uint32_t limit>
static SegmentDescriptor make(uint32_t base, Access type) {
@@ -94,11 +95,11 @@ public:
unsigned int base_31_24 : 8 = 0; // high bits of segment address
} __attribute__((packed));
+ enum SegmentMap { null0, kcode, kdata };
+
+ GDT();
+ ~GDT() = default;
-private:
- SegmentDescriptor segments[256];
+ uint16_t descriptor(SegmentMap) const;
};
-static_assert(sizeof(GDT::Pointer) == 6);
-static_assert(sizeof(GDT::SegmentDescriptor) == 8);
-static_assert(sizeof(GDT::SegmentDescriptor::Access) == 1);
diff --git a/src/gdt/segmentdescriptor.cc b/src/gdt/segmentdescriptor.cc
index baf4753..dadd65b 100644
--- a/src/gdt/segmentdescriptor.cc
+++ b/src/gdt/segmentdescriptor.cc
@@ -1,4 +1,12 @@
-#include "../gdt.h"
+#include "gdt.h"
+
+using seg = GDT::SegmentDescriptor;
+
+static_assert(sizeof(seg) == 8);
+static_assert(sizeof(seg::Access) == 1);
+static_assert((seg::Access{}) == 0x00);
+static_assert((seg::Access{.r_w = true, .exe = true, .segment = true, .present = true}) == 0x9a);
+static_assert((seg::Access{.r_w = true, .segment = true, .present = true}) == 0x92);
GDT::SegmentDescriptor::SegmentDescriptor(uint32_t base, uint32_t limit, GDT::SegmentDescriptor::Access type)
: access(type) {
diff --git a/src/idt.cc b/src/idt.cc
index 5be738a..5022f3e 100644
--- a/src/idt.cc
+++ b/src/idt.cc
@@ -6,6 +6,7 @@
static_assert(sizeof(IDT::Pointer) == 6);
constexpr uint8_t irq_base = 0x20;
+static IDT::Entry table[256];
static InterruptHandler* handlers[256] = {nullptr};
bool IDT::install(uint8_t irq, InterruptHandler* h) {
diff --git a/src/idt.h b/src/idt.h
index ce5209c..01662ad 100644
--- a/src/idt.h
+++ b/src/idt.h
@@ -48,8 +48,6 @@ public:
void enable() { asm volatile("sti"); }
private:
- Entry table[256];
-
static bool install(uint8_t, InterruptHandler*);
static bool uninstall(uint8_t, InterruptHandler*);
};
diff --git a/src/kernel.cc b/src/kernel.cc
index 85d4124..372b5bb 100644
--- a/src/kernel.cc
+++ b/src/kernel.cc
@@ -49,9 +49,8 @@ void kernel_main([[maybe_unused]] uint32_t mb_magic, [[maybe_unused]] uint32_t m
// dump_gdt();
GDT gdt;
- IDT idt{gdt.codeDescriptor()};
-
- Scheduler s{gdt.codeDescriptor()};
+ IDT idt{gdt.descriptor(GDT::kcode)};
+ Scheduler s{gdt.descriptor(GDT::kcode)};
Keyboard kb;
idt.enable();
diff --git a/toolchain.makefile b/toolchain.makefile
index ae791c1..aa13852 100644
--- a/toolchain.makefile
+++ b/toolchain.makefile
@@ -12,7 +12,7 @@ LD_FLAGS := -T linker.ld
CXX := clang++
TEST_CXX := clang++
-CXX_FLAGS := -std=c++20 \
+CXX_FLAGS := -std=c++20 -g \
-mkernel -ffreestanding -nostdlib -nostdinc -nostdinc++ \
-Wall -Wextra -Werror=pedantic -O2 \
-Werror=date-time \