MOS Source Code
Loading...
Searching...
No Matches
paging.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos/mm/mm.hpp"
10#include "mos/x86/cpu/cpuid.hpp"
13
14#include <algorithm>
17#include <mos/types.hpp>
18#include <mos_stdlib.hpp>
19
20static void x86_setup_direct_map(pml4_t pml4)
21{
22 // map all memory to MOS_DIRECT_MAP_VADDR using 1 GiB, or 2 MiB pages
23 const bool gbpages = cpu_has_feature(CPU_FEATURE_PDPE1GB);
24
25 pr_dinfo2(x86_startup, "mapping all memory to " PTR_FMT " using %s pages", x86_platform.direct_map_base, gbpages ? "1 GB" : "2 MB");
26
27 const size_t STEP = (gbpages ? 1 GB : 2 MB) / MOS_PAGE_SIZE;
28 const size_t total_npages = std::max(ALIGN_UP(platform_info->max_pfn, STEP), 4 GB / MOS_PAGE_SIZE);
29
30 pfn_t pfn = 0;
31 while (pfn < total_npages)
32 {
33 const ptr_t vaddr = pfn_va(pfn);
34 pml4e_t *pml4e = pml4_entry(pml4, vaddr);
36
37 if (gbpages)
38 {
39 // GB pages are at pml3e level
40 const pml3_t pml3 = pml4e_get_or_create_pml3(pml4e);
41 pml3e_t *pml3e = pml3_entry(pml3, vaddr);
42 platform_pml3e_set_huge(pml3e, pfn);
44 }
45 else
46 {
47 // 2 MiB pages are at pml2e level
48 pml3e_t *pml3e = pml3_entry(pml4e_get_or_create_pml3(pml4e), vaddr);
50
51 const pml2_t pml2 = pml3e_get_or_create_pml2(pml3e);
52 pml2e_t *pml2e = pml2_entry(pml2, vaddr);
53 platform_pml2e_set_huge(pml2e, pfn);
55 }
56
57 pfn += STEP;
58 }
59}
60
62{
63 x86_setup_direct_map(platform_info->kernel_mm->pgd.max.next);
64}
65
67{
68 const x86_pte64_t *entry = cast<x86_pte64_t>(pml1e);
69 return entry->pfn;
70}
71
73{
74 x86_pte64_t *entry = cast<x86_pte64_t>(pml1e);
75 entry->present = true;
76 entry->pfn = pfn;
77}
78
80{
81 const x86_pte64_t *entry = cast<x86_pte64_t>(pml1e);
82 return entry->present;
83}
84
86{
87 x86_pte64_t *entry = cast<x86_pte64_t>(pml1e);
88 entry->writable = flags & VM_WRITE;
89 entry->usermode = flags & VM_USER;
90 entry->write_through = flags & VM_WRITE_THROUGH;
91 entry->cache_disabled = flags & VM_CACHE_DISABLED;
92 entry->global = flags & VM_GLOBAL;
93 entry->no_execute = !(flags & VM_EXEC);
94}
95
97{
98 const x86_pte64_t *entry = cast<x86_pte64_t>(pml1e);
99 vm_flags flags = VM_READ;
100 flags |= entry->writable ? VM_WRITE : VM_NONE;
101 flags |= entry->usermode ? VM_USER : VM_NONE;
102 flags |= entry->write_through ? VM_WRITE_THROUGH : VM_NONE;
103 flags |= entry->cache_disabled ? VM_CACHE_DISABLED : VM_NONE;
104 flags |= entry->global ? VM_GLOBAL : VM_NONE;
105 flags |= entry->no_execute ? VM_NONE : VM_EXEC;
106 return flags;
107}
108
109// PML2
110
111pml1_t platform_pml2e_get_pml1(const pml2e_t *pml2e)
112{
113 const x86_pde64_t *entry = cast<x86_pde64_t>(pml2e);
114 return { .table = (pml1e_t *) pfn_va(entry->page_table_paddr) };
115}
116
117void platform_pml2e_set_pml1(pml2e_t *pml2e, pml1_t pml1, pfn_t pml1_pfn)
118{
119 MOS_UNUSED(pml1);
120 x86_pde64_t *entry = cast<x86_pde64_t>(pml2e);
121 entry->present = true;
122 entry->page_table_paddr = pml1_pfn;
123}
124
125bool platform_pml2e_get_present(const pml2e_t *pml2e)
126{
127 const x86_pde64_t *entry = cast<x86_pde64_t>(pml2e);
128 return entry->present;
129}
130
131void platform_pml2e_set_flags(pml2e_t *pml2e, vm_flags flags)
132{
133 x86_pde64_t *entry = cast<x86_pde64_t>(pml2e);
134 entry->writable |= flags & VM_WRITE;
135 entry->usermode |= flags & VM_USER;
136 entry->write_through |= flags & VM_WRITE_THROUGH;
137 entry->cache_disabled |= flags & VM_CACHE_DISABLED;
138 if (flags & VM_EXEC)
139 entry->no_execute = false;
140
141 if (entry->page_size)
142 {
143 entry->no_execute = !(flags & VM_EXEC);
144 x86_pde64_huge_t *huge_entry = cast<x86_pde64_huge_t>(pml2e);
145 huge_entry->global = flags & VM_GLOBAL;
146 }
147}
148
150{
151 const x86_pde64_t *entry = cast<x86_pde64_t>(pml2e);
152 vm_flags flags = VM_READ;
153 flags |= entry->writable ? VM_WRITE : VM_NONE;
154 flags |= entry->usermode ? VM_USER : VM_NONE;
155 flags |= entry->write_through ? VM_WRITE_THROUGH : VM_NONE;
156 flags |= entry->cache_disabled ? VM_CACHE_DISABLED : VM_NONE;
157 flags |= entry->no_execute ? VM_NONE : VM_EXEC;
158 if (entry->page_size)
159 {
160 const x86_pde64_huge_t *huge_entry = cast<x86_pde64_huge_t>(pml2e);
161 flags |= huge_entry->global ? VM_GLOBAL : VM_NONE;
162 }
163
164 return flags;
165}
166
167bool platform_pml2e_is_huge(const pml2e_t *pml2e)
168{
169 const x86_pde64_t *entry = cast<x86_pde64_t>(pml2e);
170 return entry->page_size;
171}
172
173void platform_pml2e_set_huge(pml2e_t *pml2e, pfn_t pfn)
174{
175 pml2e->content = 0;
177 entry->present = true;
178 entry->page_size = true;
179 entry->pfn = pfn >> 1; // 1 bit PAT
180}
181
183{
184 const x86_pde64_huge_t *entry = cast<x86_pde64_huge_t>(pml2);
185 return entry->pfn << 1; // 1 bit PAT
186}
187
188// PML3
189
191{
192 const x86_pmde64_t *entry = cast<x86_pmde64_t>(pml3e);
193 return { .table = (pml2e_t *) pfn_va(entry->page_table_paddr) };
194}
195
196void platform_pml3e_set_pml2(pml3e_t *pml3e, pml2_t pml2, pfn_t pml2_pfn)
197{
198 MOS_UNUSED(pml2);
199 x86_pmde64_t *entry = cast<x86_pmde64_t>(pml3e);
200 entry->present = true;
201 entry->page_table_paddr = pml2_pfn;
202}
203
205{
206 const x86_pmde64_t *entry = cast<x86_pmde64_t>(pml3e);
207 return entry->present;
208}
209
211{
212 x86_pmde64_t *entry = cast<x86_pmde64_t>(pml3e);
213 entry->writable |= flags & VM_WRITE;
214 entry->usermode |= flags & VM_USER;
215 entry->write_through |= flags & VM_WRITE_THROUGH;
216 entry->cache_disabled |= flags & VM_CACHE_DISABLED;
217 if (flags & VM_EXEC)
218 entry->no_execute = false; // if not huge, set NX bit only if exec flag is set
219
220 if (entry->page_size)
221 {
222 entry->no_execute = !(flags & VM_EXEC); // if huge, set NX bit accordingly
223 x86_pmde64_huge_t *huge_entry = cast<x86_pmde64_huge_t>(pml3e);
224 huge_entry->global = flags & VM_GLOBAL;
225 }
226}
227
229{
230 const x86_pmde64_t *entry = cast<x86_pmde64_t>(pml3e);
231 vm_flags flags = VM_READ;
232 flags |= entry->writable ? VM_WRITE : VM_NONE;
233 flags |= entry->usermode ? VM_USER : VM_NONE;
234 flags |= entry->write_through ? VM_WRITE_THROUGH : VM_NONE;
235 flags |= entry->cache_disabled ? VM_CACHE_DISABLED : VM_NONE;
236 flags |= entry->no_execute ? VM_NONE : VM_EXEC;
237 if (entry->page_size)
238 {
239 const x86_pmde64_huge_t *huge_entry = cast<x86_pmde64_huge_t>(pml3e);
240 flags |= huge_entry->global ? VM_GLOBAL : VM_NONE;
241 }
242 return flags;
243}
244
246{
247 const x86_pmde64_t *entry = cast<x86_pmde64_t>(pml3e);
248 return entry->page_size;
249}
250
252{
253 pml3e->content = 0;
255 entry->present = true;
256 entry->page_size = true;
257 entry->pfn = pfn >> 1; // 1 bit PAT
258}
259
261{
262 const x86_pmde64_huge_t *entry = cast<x86_pmde64_huge_t>(pml3);
263 return entry->pfn << 1; // 1 bit PAT
264}
265
266// PML4
267
269{
270 const x86_pude64_t *entry = cast<x86_pude64_t>(pml4e);
271 return { .table = (pml3e_t *) pfn_va(entry->page_table_paddr) };
272}
273
274void platform_pml4e_set_pml3(pml4e_t *pml4e, pml3_t pml3, pfn_t pml3_pfn)
275{
276 MOS_UNUSED(pml3);
277 x86_pude64_t *entry = cast<x86_pude64_t>(pml4e);
278 entry->present = true;
279 entry->page_table_paddr = pml3_pfn;
280}
281
283{
284 const x86_pude64_t *entry = cast<x86_pude64_t>(pml4e);
285 return entry->present;
286}
287
289{
290 x86_pude64_t *entry = cast<x86_pude64_t>(pml4e);
291 entry->writable |= flags & VM_WRITE;
292 entry->usermode |= flags & VM_USER;
293 entry->write_through |= flags & VM_WRITE_THROUGH;
294 entry->cache_disabled |= flags & VM_CACHE_DISABLED;
295 if (flags & VM_EXEC)
296 entry->no_execute = false;
297}
298
300{
301 const x86_pude64_t *entry = cast<x86_pude64_t>(pml4e);
302 vm_flags flags = VM_READ;
303 if (entry->writable)
304 flags |= VM_WRITE;
305 flags |= entry->writable ? VM_WRITE : VM_NONE;
306 flags |= entry->usermode ? VM_USER : VM_NONE;
307 flags |= entry->write_through ? VM_WRITE_THROUGH : VM_NONE;
308 flags |= entry->cache_disabled ? VM_CACHE_DISABLED : VM_NONE;
309 flags |= entry->no_execute ? VM_NONE : VM_EXEC;
310 return flags;
311}
bool platform_pml3e_is_huge(const pml3e_t *pml3e)
Definition paging.cpp:245
void platform_pml2e_set_flags(pml2e_t *pml2e, vm_flags flags)
Definition paging.cpp:131
pml1_t platform_pml2e_get_pml1(const pml2e_t *pml2e)
Definition paging.cpp:111
void platform_pml4e_set_flags(pml4e_t *pml4e, vm_flags flags)
Definition paging.cpp:288
bool platform_pml3e_get_present(const pml3e_t *pml3e)
Definition paging.cpp:204
void platform_pml4e_set_pml3(pml4e_t *pml4e, pml3_t pml3, pfn_t pml3_pfn)
Definition paging.cpp:274
void platform_pml1e_set_flags(pml1e_t *pml1e, vm_flags flags)
Definition paging.cpp:85
pml3_t platform_pml4e_get_pml3(const pml4e_t *pml4e)
Definition paging.cpp:268
vm_flags platform_pml3e_get_flags(const pml3e_t *pml3e)
Definition paging.cpp:228
vm_flags platform_pml4e_get_flags(const pml4e_t *pml4e)
Definition paging.cpp:299
vm_flags platform_pml1e_get_flags(const pml1e_t *pml1e)
Definition paging.cpp:96
pfn_t platform_pml2e_get_huge_pfn(const pml2e_t *pml2)
Definition paging.cpp:182
pfn_t platform_pml1e_get_pfn(const pml1e_t *pml1e)
Definition paging.cpp:66
void platform_pml2e_set_huge(pml2e_t *pml2e, pfn_t pfn)
Definition paging.cpp:173
void platform_pml2e_set_pml1(pml2e_t *pml2e, pml1_t pml1, pfn_t pml1_pfn)
Definition paging.cpp:117
void platform_pml3e_set_pml2(pml3e_t *pml3e, pml2_t pml2, pfn_t pml2_pfn)
Definition paging.cpp:196
bool platform_pml2e_is_huge(const pml2e_t *pml2e)
Definition paging.cpp:167
void platform_pml1e_set_pfn(pml1e_t *pml1e, pfn_t pfn)
Definition paging.cpp:72
void platform_pml3e_set_flags(pml3e_t *pml3e, vm_flags flags)
Definition paging.cpp:210
bool platform_pml1e_get_present(const pml1e_t *pml1e)
Definition paging.cpp:79
bool platform_pml2e_get_present(const pml2e_t *pml2e)
Definition paging.cpp:125
void platform_pml3e_set_huge(pml3e_t *pml3e, pfn_t pfn)
Definition paging.cpp:251
pfn_t platform_pml3e_get_huge_pfn(const pml3e_t *pml3)
Definition paging.cpp:260
static void x86_setup_direct_map(pml4_t pml4)
Definition paging.cpp:20
bool platform_pml4e_get_present(const pml4e_t *pml4e)
Definition paging.cpp:282
vm_flags platform_pml2e_get_flags(const pml2e_t *pml2e)
Definition paging.cpp:149
void x86_paging_setup()
Definition paging.cpp:61
pml2_t platform_pml3e_get_pml2(const pml3e_t *pml3e)
Definition paging.cpp:190
#define MOS_PAGE_SIZE
Definition autoconf.h:6
#define CPU_FEATURE_PDPE1GB
Definition cpuid.hpp:61
#define cpu_has_feature(feat)
Definition cpuid.hpp:82
#define pfn_va(pfn)
Definition mm.hpp:77
#define GB
Definition mos_global.h:100
#define MOS_UNUSED(x)
Definition mos_global.h:65
#define MB
Definition mos_global.h:99
#define ALIGN_UP(addr, size)
Definition mos_global.h:74
struct x86_pde64_huge_t x86_pmde64_huge_t
struct x86_pde64_t x86_pude64_t
struct x86_pde64_t x86_pmde64_t
vm_flags
Definition platform.hpp:42
@ VM_GLOBAL
Definition platform.hpp:51
@ VM_CACHE_DISABLED
Definition platform.hpp:50
@ VM_READ
Definition platform.hpp:44
@ VM_NONE
Definition platform.hpp:43
@ VM_WRITE_THROUGH
Definition platform.hpp:49
@ VM_EXEC
Definition platform.hpp:46
@ VM_WRITE
Definition platform.hpp:45
@ VM_USER
Definition platform.hpp:48
pml2e_t * pml2_entry(pml2_t pml2, ptr_t vaddr)
Definition pml2.cpp:74
pml2_t pml3e_get_or_create_pml2(pml3e_t *pml3e)
pml3e_t * pml3_entry(pml3_t pml3, ptr_t vaddr)
Definition pml3.cpp:21
pml3_t pml4e_get_or_create_pml3(pml4e_t *pml4e)
pml4e_t * pml4_entry(pml4_t pml4, ptr_t vaddr)
Definition pml4.cpp:22
pml3e_t pml4e_t
Definition pml_types.hpp:72
pml2e_t pml3e_t
Definition pml_types.hpp:60
#define pr_dinfo2(feat, fmt,...)
Definition printk.hpp:27
mos_platform_info_t *const platform_info
pfn_t page_table_paddr
bool cache_disabled
bool cache_disabled
unsigned long long pfn_t
Definition types.h:37
#define PTR_FMT
Definition types.h:29
unsigned long ptr_t
Definition types.h:21
TOut * cast(TIn *value)
Definition types.hpp:34
mos_platform_info_t x86_platform