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