MOS Source Code
Loading...
Searching...
No Matches
mm.c
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos/mm/mm.h"
4
6
7#include <mos/mos_global.h>
8#include <mos/types.h>
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 = 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_to(pml1e, pml1e_t *, sv48_pte_t *)->ppn;
81}
82
83void platform_pml1e_set_pfn(pml1e_t *pml1, pfn_t pfn) // -- which can be a pfn for either a page or another page table
84{
85 pml1->content = 0;
86 sv48_pte_t *pte = cast_to(pml1, pml1e_t *, sv48_pte_t *);
87 pte_set_ppn_stem(pte, pfn);
88}
89
90bool platform_pml1e_get_present(const pml1e_t *pml1) // returns if an entry in this page table is present
91{
92 return cast_to(pml1, pml1e_t *, sv48_pte_t *)->valid;
93}
94
95void platform_pml1e_set_flags(pml1e_t *pml1, vm_flags flags) // set bits in the flags field of the pmlx entry
96{
97 sv48_pte_t *pte = cast_to(pml1, pml1e_t *, sv48_pte_t *);
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_to(pml1e, pml1e_t *, sv48_pte_t *);
104 return pte_get_flags(pte);
105}
106
107pml1_t platform_pml2e_get_pml1(const pml2e_t *pml2)
108{
109 return (pml1_t){ .table = (pml1e_t *) pfn_va(cast_to(pml2, pml2e_t *, sv48_pte_t *)->ppn) };
110}
111
112void platform_pml2e_set_pml1(pml2e_t *pml2, pml1_t pml1, pfn_t pml1_pfn)
113{
114 MOS_UNUSED(pml1);
115 pml2->content = 0;
116 sv48_pte_t *pte = cast_to(pml2, pml2e_t *, sv48_pte_t *);
117 pte_set_ppn_stem(pte, pml1_pfn);
118}
119
120bool platform_pml2e_get_present(const pml2e_t *pml2)
121{
122 return cast_to(pml2, pml2e_t *, sv48_pte_t *)->valid;
123}
124
125void platform_pml2e_set_flags(pml2e_t *pml2, vm_flags flags)
126{
127 sv48_pte_t *pte = cast_to(pml2, pml2e_t *, sv48_pte_t *);
128 pmle_set_flags(2, pte, flags);
129}
130
132{
133 const sv48_pte_t *pte = cast_to(pml2e, pml2e_t *, sv48_pte_t *);
134 return pte_get_flags(pte);
135}
136
137#if MOS_CONFIG(PML2_HUGE_CAPABLE)
138bool platform_pml2e_is_huge(const pml2e_t *pml2)
139{
140 const sv48_pte_t *pte = cast_to(pml2, pml2e_t *, sv48_pte_t *);
141 return pte_is_huge(pte);
142}
143
144void platform_pml2e_set_huge(pml2e_t *pml2, pfn_t pfn)
145{
146 pml2->content = 0;
147 sv48_pte_t *pte = cast_to(pml2, pml2e_t *, sv48_pte_t *);
148 pte_set_ppn_huge(pte, pfn);
149}
150
151pfn_t platform_pml2e_get_huge_pfn(const pml2e_t *pml2)
152{
153 return cast_to(pml2, pml2e_t *, sv48_pte_t *)->ppn;
154}
155#endif
156
158{
159 return (pml2_t){ .table = (pml2e_t *) pfn_va(cast_to(pml3, pml3e_t *, sv48_pte_t *)->ppn) };
160}
161
162void platform_pml3e_set_pml2(pml3e_t *pml3, pml2_t pml2, pfn_t pml2_pfn)
163{
164 MOS_UNUSED(pml2);
165 pml3->content = 0;
166 sv48_pte_t *pte = cast_to(pml3, pml3e_t *, sv48_pte_t *);
167 pte_set_ppn_stem(pte, pml2_pfn);
168}
169
171{
172 return cast_to(pml3, pml3e_t *, sv48_pte_t *)->valid;
173}
174
176{
177 sv48_pte_t *pte = cast_to(pml3, pml3e_t *, sv48_pte_t *);
178 pmle_set_flags(3, pte, flags);
179}
180
182{
183 const sv48_pte_t *pte = cast_to(pml3e, pml3e_t *, sv48_pte_t *);
184 return pte_get_flags(pte);
185}
186
187#if MOS_CONFIG(PML3_HUGE_CAPABLE)
188bool platform_pml3e_is_huge(const pml3e_t *pml3)
189{
190 const sv48_pte_t *pte = cast_to(pml3, pml3e_t *, sv48_pte_t *);
191 return pte_is_huge(pte);
192}
193
195{
196 pml3->content = 0;
197 sv48_pte_t *pte = cast_to(pml3, pml3e_t *, sv48_pte_t *);
198 pte_set_ppn_huge(pte, pfn);
199}
200
202{
203 return cast_to(pml3, pml3e_t *, sv48_pte_t *)->ppn;
204}
205#endif
206
208{
209 return (pml3_t){ .table = (pml3e_t *) pfn_va(cast_to(pml4, pml4e_t *, sv48_pte_t *)->ppn) };
210}
211
212void platform_pml4e_set_pml3(pml4e_t *pml4, pml3_t pml3, pfn_t pml3_pfn)
213{
214 MOS_UNUSED(pml3);
215 pml4->content = 0;
216 sv48_pte_t *pte = cast_to(pml4, pml4e_t *, sv48_pte_t *);
217 pte_set_ppn_stem(pte, pml3_pfn);
218}
219
221{
222 return cast_to(pml4, pml4e_t *, sv48_pte_t *)->valid;
223}
224
226{
227 sv48_pte_t *pte = cast_to(pml4, pml4e_t *, sv48_pte_t *);
228 pmle_set_flags(4, pte, flags);
229}
230
232{
233 const sv48_pte_t *pte = cast_to(pml4e, pml4e_t *, sv48_pte_t *);
234 return pte_get_flags(pte);
235}
236
237#if MOS_CONFIG(PML4_HUGE_CAPABLE)
238bool platform_pml4e_is_huge(const pml4e_t *pml4)
239{
240 const sv48_pte_t *pte = cast_to(pml4, pml4e_t *, sv48_pte_t *);
241 return pte_is_huge(pte);
242}
243
244void platform_pml4e_set_huge(pml4e_t *pml4, pfn_t pfn)
245{
246 pml4->content = 0;
247 sv48_pte_t *pte = cast_to(pml4, pml4e_t *, sv48_pte_t *);
248 pte_set_ppn_huge(pte, pfn);
249}
250
251pfn_t platform_pml4e_get_huge_pfn(const pml4e_t *pml4)
252{
253 return cast_to(pml4, pml4e_t *, sv48_pte_t *)->ppn;
254}
255#endif
void platform_pml3e_set_pml2(pml3e_t *pml3, pml2_t pml2, pfn_t pml2_pfn)
Definition mm.c:162
void platform_pml2e_set_flags(pml2e_t *pml2, vm_flags flags)
Definition mm.c:125
#define pte_set_ppn_stem(pte, _ppn)
Definition mm.c:36
void platform_pml4e_set_flags(pml4e_t *pml4, vm_flags flags)
Definition mm.c:225
bool platform_pml4e_get_present(const pml4e_t *pml4)
Definition mm.c:220
void platform_pml1e_set_pfn(pml1e_t *pml1, pfn_t pfn)
Definition mm.c:83
vm_flags platform_pml3e_get_flags(const pml3e_t *pml3e)
Definition mm.c:181
bool platform_pml3e_get_present(const pml3e_t *pml3)
Definition mm.c:170
#define pte_set_ppn_huge(pte, _ppn)
Definition mm.c:37
vm_flags platform_pml4e_get_flags(const pml4e_t *pml4e)
Definition mm.c:231
should_inline void pmle_set_flags(int level, sv48_pte_t *pte, vm_flags flags)
Definition mm.c:39
vm_flags platform_pml1e_get_flags(const pml1e_t *pml1e)
Definition mm.c:101
pml1_t platform_pml2e_get_pml1(const pml2e_t *pml2)
Definition mm.c:107
bool platform_pml2e_get_present(const pml2e_t *pml2)
Definition mm.c:120
void platform_pml2e_set_pml1(pml2e_t *pml2, pml1_t pml1, pfn_t pml1_pfn)
Definition mm.c:112
#define pte_is_stem(pte)
Definition mm.c:33
pfn_t platform_pml1e_get_pfn(const pml1e_t *pml1e)
Definition mm.c:78
void platform_invalidate_tlb(ptr_t vaddr)
Definition mm.c:72
#define pte_is_huge(pte)
Definition mm.c:34
void platform_pml1e_set_flags(pml1e_t *pml1, vm_flags flags)
Definition mm.c:95
bool platform_pml1e_get_present(const pml1e_t *pml1)
Definition mm.c:90
should_inline vm_flags pte_get_flags(const sv48_pte_t *pte)
Definition mm.c:53
void platform_halt_cpu(void)
Definition mm.c:65
void platform_pml3e_set_flags(pml3e_t *pml3, vm_flags flags)
Definition mm.c:175
vm_flags platform_pml2e_get_flags(const pml2e_t *pml2e)
Definition mm.c:131
void platform_pml4e_set_pml3(pml4e_t *pml4, pml3_t pml3, pfn_t pml3_pfn)
Definition mm.c:212
pml3_t platform_pml4e_get_pml3(const pml4e_t *pml4)
Definition mm.c:207
pml2_t platform_pml3e_get_pml2(const pml3e_t *pml3)
Definition mm.c:157
bool platform_pml3e_is_huge(const pml3e_t *pml3e)
Definition paging.c:244
pfn_t platform_pml2e_get_huge_pfn(const pml2e_t *pml2)
Definition paging.c:181
void platform_pml2e_set_huge(pml2e_t *pml2e, pfn_t pfn)
Definition paging.c:172
bool platform_pml2e_is_huge(const pml2e_t *pml2e)
Definition paging.c:166
void platform_pml3e_set_huge(pml3e_t *pml3e, pfn_t pfn)
Definition paging.c:250
pfn_t platform_pml3e_get_huge_pfn(const pml3e_t *pml3)
Definition paging.c:259
#define pfn_va(pfn)
Definition mm.h:76
#define __packed
Definition mos_global.h:29
#define should_inline
Definition mos_global.h:37
#define MOS_UNUSED(x)
Definition mos_global.h:64
#define cast_to(value, valtype, desttype)
Definition mos_global.h:53
#define MOS_STATIC_ASSERT
Definition mos_global.h:14
vm_flags
Definition platform.h:40
@ VM_GLOBAL
Definition platform.h:48
@ VM_READ
Definition platform.h:41
@ VM_EXEC
Definition platform.h:43
@ VM_WRITE
Definition platform.h:42
@ VM_USER
Definition platform.h:45
pml3e_t pml4e_t
Definition pml_types.h:72
pml2e_t pml3e_t
Definition pml_types.h:60
pte_content_t content
Definition pml_types.h:35
u8 _2
Definition mm.c:26
bool accessed
Definition mm.c:22
bool valid
Definition mm.c:12
u8 _1
Definition mm.c:24
bool n
Definition mm.c:28
bool global
Definition mm.c:21
bool user
Definition mm.c:20
bool r
Definition mm.c:16
bool x
Definition mm.c:18
u64 ppn
Definition mm.c:25
u8 pbmt
Definition mm.c:27
bool w
Definition mm.c:17
bool dirty
Definition mm.c:23
unsigned long long pfn_t
Definition types.h:41
unsigned long ptr_t
Definition types.h:25
long pte_content_t
Definition types.h:86
unsigned long long u64
Definition types.h:23
unsigned char u8
Definition types.h:19