blob: dadd65b1a22d87d46367de8c61f16e8c2f47826c (
plain)
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
43
44
45
46
47
48
|
#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) {
// store base
base_15_0 = base & 0xffff;
base_23_16 = (base >> 16) & 0xff;
base_31_24 = (base >> 24) & 0xff;
// store limit
if (limit <= 0xffffu) { // 16-bit address space
limit_15_0 = limit & 0xffff;
limit_19_16 = 0;
} else {
db = 1;
// limit is uint32_t, which we need to store in limit_19_16 and limit_15_0, a total of 20 bits
limit = limit >> 12;
limit_15_0 = limit & 0xffff;
limit_19_16 = (limit >> 16) & 0xf;
}
granularity = 1;
}
uint32_t GDT::SegmentDescriptor::base() const {
uint32_t base = base_31_24;
base = (base << 8) + base_23_16;
base = (base << 16) + base_15_0;
return base;
}
uint32_t GDT::SegmentDescriptor::limit() const {
uint32_t limit = 0;
if (db == 1) {
limit = limit_19_16;
limit = limit << 16;
}
limit += limit_15_0;
return 0;
}
|