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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
#include "arch/cpu/initialization.hpp"
#include "arch/cpu/global_descriptor_table.hpp"
#include "arch/cpu/segment_descriptor.hpp"
#include "arch/cpu/task_state_segment.hpp"
#include <kstd/print>
#include <bit>
#include <cstdint>
namespace arch::cpu
{
namespace
{
constexpr auto gdt_null_descriptor = segment_descriptor{};
constexpr auto gdt_kernel_code_descriptor = segment_descriptor{
.limit_low = 0xffff,
.base_low = 0,
.accessed = false,
.read_write = false,
.direction_or_conforming = false,
.executable = true,
.type = segment_type::code_or_data,
.privilege_level = 0,
.present = true,
.limit_high = 0xf,
.long_mode = true,
.protected_mode = false,
.granularity = segment_granularity::page,
.base_high = 0,
};
constexpr auto gdt_kernel_data_descriptor = segment_descriptor{
.limit_low = 0xffff,
.base_low = 0,
.accessed = false,
.read_write = true,
.direction_or_conforming = false,
.executable = false,
.type = segment_type::code_or_data,
.privilege_level = 0,
.present = true,
.limit_high = 0xf,
.long_mode = false,
.protected_mode = true,
.granularity = segment_granularity::page,
.base_high = 0,
};
constexpr auto gdt_user_code_descriptor = segment_descriptor{
.limit_low = 0xffff,
.base_low = 0,
.accessed = false,
.read_write = false,
.direction_or_conforming = false,
.executable = true,
.type = segment_type::code_or_data,
.privilege_level = 3,
.present = true,
.limit_high = 0xf,
.long_mode = true,
.protected_mode = false,
.granularity = segment_granularity::page,
.base_high = 0,
};
constexpr auto gdt_user_data_descriptor = segment_descriptor{
.limit_low = 0xffff,
.base_low = 0,
.accessed = false,
.read_write = true,
.direction_or_conforming = false,
.executable = false,
.type = segment_type::code_or_data,
.privilege_level = 3,
.present = true,
.limit_high = 0xf,
.long_mode = false,
.protected_mode = false,
.granularity = segment_granularity::page,
.base_high = 0,
};
} // namespace
auto initialize_descriptors() -> void
{
auto static tss = task_state_segment{};
auto static tss_descriptor = system_segment_descriptor{
{
.limit_low = (sizeof(tss) - 1) & 0xffff, // NOLINT(readability-magic-numbers)
.base_low = std::bit_cast<std::uintptr_t>(&tss) & 0xffffff, // NOLINT(readability-magic-numbers)
.accessed = false,
.read_write = false,
.direction_or_conforming = false,
.executable = false,
.type = segment_type::system,
.privilege_level = 0,
.present = true,
.limit_high = ((sizeof(tss) - 1) >> 16) & 0xf, // NOLINT(readability-magic-numbers)
.long_mode = false,
.protected_mode = false,
.granularity = segment_granularity::byte,
.base_high = (std::bit_cast<std::uintptr_t>(&tss) >> 24) & 0xff, // NOLINT(readability-magic-numbers)
},
(std::bit_cast<std::uintptr_t>(&tss) >> 32) & 0xffff'ffff, // NOLINT(readability-magic-numbers)
};
auto static gdt = global_descriptor_table{
gdt_null_descriptor, gdt_kernel_code_descriptor, gdt_kernel_data_descriptor,
gdt_user_code_descriptor, gdt_user_data_descriptor, tss_descriptor,
};
kstd::println("[x86_64:SYS] Reloading Global Descriptor Table.");
gdt.load(1, 2);
kstd::println("[x86_64:SYS] TODO: initialize Interrupt Descriptor Table.");
}
} // namespace arch::cpu
|