MOS Source Code
Loading...
Searching...
No Matches
mm.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos/mm/mm.hpp"
4
5#include "mos/mm/mm_types.hpp"
7
8#include <mos/mos_global.h>
9#include <mos/types.hpp>
10
11typedef struct _sv48_pte
12{
13 bool valid : 1; // Valid
14
15 // When all three are zero, the PTE is a pointer to the next level of the page table;
16 // Otherwise, it's a leaf PTE.
17 bool r : 1; // Readable
18 bool w : 1; // Writable, also must be readable
19 bool x : 1; // Executable
20
21 bool user : 1;
22 bool global : 1; // Global, For non-leaf PTEs, the global setting implies that all mappings in the subsequent levels of the page table are global.
23 bool accessed : 1;
24 bool dirty : 1;
25 u8 _1 : 2;
26 u64 ppn : 44; // Physical page number
27 u8 _2 : 7;
28 u8 pbmt : 2; // Svpbmt
29 bool n : 1; // Svnapot
31
33
34#define pte_is_stem(pte) ((pte)->r == 0 && (pte)->w == 0 && (pte)->x == 0 && (pte)->valid)
35#define pte_is_huge(pte) (((pte)->r || (pte)->w || (pte)->x) && (pte)->valid)
36
37#define pte_set_ppn_stem(pte, _ppn) ((pte)->valid = 1, (pte)->ppn = _ppn, (pte)->r = 0, (pte)->w = 0, (pte)->x = 0)
38#define pte_set_ppn_huge(pte, _ppn) ((pte)->valid = 1, (pte)->ppn = _ppn, (pte)->r = 1, (pte)->w = 0, (pte)->x = 0)
39
40should_inline void pmle_set_flags(int level, sv48_pte_t *pte, VMFlags flags)
41{
42 if (!pte_is_stem(pte) || level == 1)
43 {
44 // only set these for leaf ptes, or for huge pages
45 pte->r = flags & VM_READ;
46 pte->w = flags & VM_WRITE;
47 pte->x = flags & VM_EXEC;
48 pte->user = flags & VM_USER;
49 }
50
51 pte->global = flags & VM_GLOBAL;
52}
53
55{
56 VMFlags flags;
57 flags |= pte->r ? VM_READ : VM_NONE;
58 flags |= pte->w ? VM_WRITE : VM_NONE;
59 flags |= pte->x ? VM_EXEC : VM_NONE;
60 flags |= pte->user ? VM_USER : VM_NONE;
61 flags |= pte->global ? VM_GLOBAL : VM_NONE;
62 return flags;
63}
64
65// Platform CPU APIs
66[[noreturn]] void platform_halt_cpu(void)
67{
68 while (true)
69 __asm__ volatile("wfi"); // wait for interrupt
70 __builtin_unreachable();
71}
72
74{
75 __asm__ volatile("sfence.vma %0" : : "r"(vaddr) : "memory");
76}
77
78// Platform Page Table APIs
79pfn_t platform_pml1e_get_pfn(const pml1e_t *pml1e) // returns the physical address contained in the pmlx entry,
80{
81 return cast<sv48_pte_t>(pml1e)->ppn;
82}
83
84void platform_pml1e_set_pfn(pml1e_t *pml1e, pfn_t pfn) // -- which can be a pfn for either a page or another page table
85{
86 pml1e->content = 0;
87 sv48_pte_t *pte = cast<sv48_pte_t>(pml1e);
88 pte_set_ppn_stem(pte, pfn);
89}
90
91bool platform_pml1e_get_present(const pml1e_t *pml1e) // returns if an entry in this page table is present
92{
93 return cast<sv48_pte_t>(pml1e)->valid;
94}
95
96void platform_pml1e_set_flags(pml1e_t *pml1e, VMFlags flags) // set bits in the flags field of the pmlx entry
97{
98 sv48_pte_t *pte = cast<sv48_pte_t>(pml1e);
99 pmle_set_flags(1, pte, flags);
100}
101
102VMFlags platform_pml1e_get_flags(const pml1e_t *pml1e) // get bits in the flags field of the pmlx entry
103{
104 const sv48_pte_t *pte = cast<sv48_pte_t>(pml1e);
105 return pte_get_flags(pte);
106}
107
108pml1_t platform_pml2e_get_pml1(const pml2e_t *pml2e)
109{
110 return { .table = (pml1e_t *) pfn_va(cast<sv48_pte_t>(pml2e)->ppn) };
111}
112
113void platform_pml2e_set_pml1(pml2e_t *pml2e, pml1_t pml1, pfn_t pml1_pfn)
114{
115 MOS_UNUSED(pml1);
116 pml2e->content = 0;
117 sv48_pte_t *pte = cast<sv48_pte_t>(pml2e);
118 pte_set_ppn_stem(pte, pml1_pfn);
119}
120
121bool platform_pml2e_get_present(const pml2e_t *pml2e)
122{
123 return cast<sv48_pte_t>(pml2e)->valid;
124}
125
126void platform_pml2e_set_flags(pml2e_t *pml2e, VMFlags flags)
127{
128 sv48_pte_t *pte = cast<sv48_pte_t>(pml2e);
129 pmle_set_flags(2, pte, flags);
130}
131
132VMFlags platform_pml2e_get_flags(const pml2e_t *pml2e)
133{
134 const sv48_pte_t *pte = cast<sv48_pte_t>(pml2e);
135 return pte_get_flags(pte);
136}
137
138#if MOS_CONFIG(PML2_HUGE_CAPABLE)
139bool platform_pml2e_is_huge(const pml2e_t *pml2e)
140{
141 const sv48_pte_t *pte = cast<sv48_pte_t>(pml2e);
142 return pte_is_huge(pte);
143}
144
145void platform_pml2e_set_huge(pml2e_t *pml2e, pfn_t pfn)
146{
147 pml2e->content = 0;
148 sv48_pte_t *pte = cast<sv48_pte_t>(pml2e);
149 pte_set_ppn_huge(pte, pfn);
150}
151
152pfn_t platform_pml2e_get_huge_pfn(const pml2e_t *pml2e)
153{
154 return cast<sv48_pte_t>(pml2e)->ppn;
155}
156#endif
157
159{
160 return { .table = (pml2e_t *) pfn_va(cast<sv48_pte_t>(pml3e)->ppn) };
161}
162
163void platform_pml3e_set_pml2(pml3e_t *pml3e, pml2_t pml2, pfn_t pml2_pfn)
164{
165 MOS_UNUSED(pml2);
166 pml3e->content = 0;
167 sv48_pte_t *pte = cast<sv48_pte_t>(pml3e);
168 pte_set_ppn_stem(pte, pml2_pfn);
169}
170
172{
173 return cast<sv48_pte_t>(pml3e)->valid;
174}
175
176void platform_pml3e_set_flags(pml3e_t *pml3e, VMFlags flags)
177{
178 sv48_pte_t *pte = cast<sv48_pte_t>(pml3e);
179 pmle_set_flags(3, pte, flags);
180}
181
183{
184 const sv48_pte_t *pte = cast<sv48_pte_t>(pml3e);
185 return pte_get_flags(pte);
186}
187
188#if MOS_CONFIG(PML3_HUGE_CAPABLE)
189bool platform_pml3e_is_huge(const pml3e_t *pml3e)
190{
191 const sv48_pte_t *pte = cast<sv48_pte_t>(pml3e);
192 return pte_is_huge(pte);
193}
194
195void platform_pml3e_set_huge(pml3e_t *pml3e, pfn_t pfn)
196{
197 pml3e->content = 0;
198 sv48_pte_t *pte = cast<sv48_pte_t>(pml3e);
199 pte_set_ppn_huge(pte, pfn);
200}
201
203{
204 return cast<sv48_pte_t>(pml3e)->ppn;
205}
206#endif
207
209{
210 return { .table = (pml3e_t *) pfn_va(cast<sv48_pte_t>(pml4e)->ppn) };
211}
212
213void platform_pml4e_set_pml3(pml4e_t *pml4e, pml3_t pml3, pfn_t pml3_pfn)
214{
215 MOS_UNUSED(pml3);
216 pml4e->content = 0;
217 sv48_pte_t *pte = cast<sv48_pte_t>(pml4e);
218 pte_set_ppn_stem(pte, pml3_pfn);
219}
220
222{
223 return cast<sv48_pte_t>(pml4e)->valid;
224}
225
226void platform_pml4e_set_flags(pml4e_t *pml4e, VMFlags flags)
227{
228 sv48_pte_t *pte = cast<sv48_pte_t>(pml4e);
229 pmle_set_flags(4, pte, flags);
230}
231
233{
234 const sv48_pte_t *pte = cast<sv48_pte_t>(pml4e);
235 return pte_get_flags(pte);
236}
237
238#if MOS_CONFIG(PML4_HUGE_CAPABLE)
239bool platform_pml4e_is_huge(const pml4e_t *pml4e)
240{
241 const sv48_pte_t *pte = cast<sv48_pte_t>(pml4e);
242 return pte_is_huge(pte);
243}
244
245void platform_pml4e_set_huge(pml4e_t *pml4e, pfn_t pfn)
246{
247 pml4e->content = 0;
248 sv48_pte_t *pte = cast<sv48_pte_t>(pml4e);
249 pte_set_ppn_huge(pte, pfn);
250}
251
252pfn_t platform_pml4e_get_huge_pfn(const pml4e_t *pml4e)
253{
254 return cast<sv48_pte_t>(pml4e)->ppn;
255}
256#endif
pml1_t platform_pml2e_get_pml1(const pml2e_t *pml2e)
Definition mm.cpp:108
bool platform_pml3e_get_present(const pml3e_t *pml3e)
Definition mm.cpp:171
should_inline void pmle_set_flags(int level, sv48_pte_t *pte, VMFlags flags)
Definition mm.cpp:40
void platform_pml4e_set_pml3(pml4e_t *pml4e, pml3_t pml3, pfn_t pml3_pfn)
Definition mm.cpp:213
#define pte_set_ppn_stem(pte, _ppn)
Definition mm.cpp:37
pml3_t platform_pml4e_get_pml3(const pml4e_t *pml4e)
Definition mm.cpp:208
void platform_pml3e_set_flags(pml3e_t *pml3e, VMFlags flags)
Definition mm.cpp:176
#define pte_set_ppn_huge(pte, _ppn)
Definition mm.cpp:38
void platform_pml1e_set_flags(pml1e_t *pml1e, VMFlags flags)
Definition mm.cpp:96
VMFlags platform_pml1e_get_flags(const pml1e_t *pml1e)
Definition mm.cpp:102
#define pte_is_stem(pte)
Definition mm.cpp:34
pfn_t platform_pml1e_get_pfn(const pml1e_t *pml1e)
Definition mm.cpp:79
VMFlags platform_pml3e_get_flags(const pml3e_t *pml3e)
Definition mm.cpp:182
void platform_pml2e_set_pml1(pml2e_t *pml2e, pml1_t pml1, pfn_t pml1_pfn)
Definition mm.cpp:113
void platform_invalidate_tlb(ptr_t vaddr)
Definition mm.cpp:73
void platform_pml4e_set_flags(pml4e_t *pml4e, VMFlags flags)
Definition mm.cpp:226
VMFlags platform_pml2e_get_flags(const pml2e_t *pml2e)
Definition mm.cpp:132
should_inline VMFlags pte_get_flags(const sv48_pte_t *pte)
Definition mm.cpp:54
#define pte_is_huge(pte)
Definition mm.cpp:35
void platform_pml2e_set_flags(pml2e_t *pml2e, VMFlags flags)
Definition mm.cpp:126
void platform_pml3e_set_pml2(pml3e_t *pml3e, pml2_t pml2, pfn_t pml2_pfn)
Definition mm.cpp:163
void platform_pml1e_set_pfn(pml1e_t *pml1e, pfn_t pfn)
Definition mm.cpp:84
bool platform_pml1e_get_present(const pml1e_t *pml1e)
Definition mm.cpp:91
bool platform_pml2e_get_present(const pml2e_t *pml2e)
Definition mm.cpp:121
VMFlags platform_pml4e_get_flags(const pml4e_t *pml4e)
Definition mm.cpp:232
void platform_halt_cpu(void)
Definition mm.cpp:66
bool platform_pml4e_get_present(const pml4e_t *pml4e)
Definition mm.cpp:221
pml2_t platform_pml3e_get_pml2(const pml3e_t *pml3e)
Definition mm.cpp:158
bool platform_pml3e_is_huge(const pml3e_t *pml3e)
Definition paging.cpp:245
pfn_t platform_pml2e_get_huge_pfn(const pml2e_t *pml2)
Definition paging.cpp:182
void platform_pml2e_set_huge(pml2e_t *pml2e, pfn_t pfn)
Definition paging.cpp:173
bool platform_pml2e_is_huge(const pml2e_t *pml2e)
Definition paging.cpp:167
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
#define pfn_va(pfn)
Definition mm.hpp:83
@ VM_GLOBAL
Definition mm_types.hpp:20
@ VM_READ
Definition mm_types.hpp:13
@ VM_NONE
Definition mm_types.hpp:12
@ VM_EXEC
Definition mm_types.hpp:15
@ VM_WRITE
Definition mm_types.hpp:14
@ VM_USER
Definition mm_types.hpp:17
#define __packed
Definition mos_global.h:29
#define should_inline
Definition mos_global.h:37
#define MOS_UNUSED(x)
Definition mos_global.h:65
#define MOS_STATIC_ASSERT
Definition mos_global.h:14
pml3e_t pml4e_t
Definition pml_types.hpp:72
pml2e_t pml3e_t
Definition pml_types.hpp:60
pte_content_t content
Definition pml_types.hpp:35
u8 _2
Definition mm.cpp:27
bool accessed
Definition mm.cpp:23
bool valid
Definition mm.cpp:13
u8 _1
Definition mm.cpp:25
bool n
Definition mm.cpp:29
bool global
Definition mm.cpp:22
bool user
Definition mm.cpp:21
bool r
Definition mm.cpp:17
bool x
Definition mm.cpp:19
u64 ppn
Definition mm.cpp:26
u8 pbmt
Definition mm.cpp:28
bool w
Definition mm.cpp:18
bool dirty
Definition mm.cpp:24
unsigned long long pfn_t
Definition types.h:37
unsigned long ptr_t
Definition types.h:21
long pte_content_t
Definition types.h:82
unsigned long long u64
Definition types.h:19
unsigned char u8
Definition types.h:15
TOut * cast(TIn *value)
Definition types.hpp:36