1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#include "gdt.h"
#include <stdlib.h>
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;
__attribute__((section(".constinit"))) static GDT::SegmentDescriptor segments[256]{
seg::make<null_sz>(0, {}),
seg::make<kseg_sz>(kseg_start, {.r_w = true, .exe = true, .segment = true, .present = true}),
seg::make<kseg_sz>(kseg_start, {.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
constexpr auto cs = GDT::descriptor(kcode);
constexpr auto ds = GDT::descriptor(kdata);
asm volatile(
"jmpl %0,$.reload_cs\n\t" // far jump: cs,location
".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),
"rm"(ds));
printk("GDT installed at ", uhex{gdtr.base}, '\n');
}
|