blob: 99a6da2dbe74d22db86609dee4cf89589cb12502 (
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
#pragma once
#include <types.h>
/* From OSDev wiki:
*
* Segment
* a logically contiguous chunk of memory with consistent properties (CPU's speaking)
*
* Segment Register
* a register of your CPU that refers to a segment for a special use (e.g. SS, CS, DS ...)
*
* Selector
* a reference to a descriptor you can load into a segment register; the selector is an offset of a descriptor table
* entry. These entries are 8 bytes long. Therefore, bits 3 and up only declare the descriptor table entry offset, while
* bit 2 specifies if this selector is a GDT or LDT selector (LDT - bit set, GDT - bit cleared), and bits 0 - 1 declare
* the ring level that needs to correspond to the descriptor table entry's DPL field. If it doesn't, a General
* Protection Fault occurs; if it does correspond then the CPL level of the selector used is changed accordingly.
*
* Descriptor
* a memory structure (part of a table) that tells the CPU the attributes of a given segment
*/
class GDT {
public:
GDT();
~GDT() = default;
struct Pointer {
uint16_t limit;
uint32_t base;
} __attribute((packed));
class SegmentDescriptor {
public:
SegmentDescriptor(uint32_t base = 0, uint32_t limit = 0, uint8_t type = 0);
[[nodiscard]] uint32_t base() const;
[[nodiscard]] uint32_t limit() const;
private:
/*
* |31| | | | | | |24|23|22| |20|19| | |16|15| | |12|11| | | 8| 7| | | | | | | 0|
* | base (24~31) | G|DB| | A| lim(16~19)| P| DPL | S| Type | base (16~23) |
* | base (0~15) | limit (0~15) |
* |31| | | | | | | | | | | | | | |16|15| | | | | | | | | | | | | | | 0|
*
* limit size of segment - 1, either in bytes or in 4KiB chunks (check flags)
* base address of segment
* access
* flags defines the segment chunks and 16/32 bit
*/
uint16_t limit_low;
uint16_t base_low;
uint8_t base_high;
uint8_t type;
uint8_t flags_limit_high;
uint8_t base_vhigh;
} __attribute__((packed));
private:
SegmentDescriptor segments[256];
};
static_assert(sizeof(GDT::Pointer) == 6);
static_assert(sizeof(GDT::SegmentDescriptor) == 8);
|