MOS Source Code
Loading...
Searching...
No Matches
iterator.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
4
5#include "mos/assert.hpp"
11
12#include <mos_string.hpp>
13
14static void pagetable_iterator_start_current_range(pagetable_iter_t *it, pml5_t *pml5, pml4_t *pml4, pml3_t *pml3, pml2_t *pml2, pml1_t *pml1)
15{
16 it->range = (pagetable_iter_range_t) { 0 };
17 it->range.vaddr = it->vaddr;
18 *pml5 = it->pgd.max;
19
20 *pml4 = pml5->next;
21 const pml4e_t *pml4e = pml4_entry(*pml4, it->vaddr);
22 if (!pml4e_is_present(pml4e))
23 return;
24
25#if MOS_CONFIG(PML4_HUGE_CAPABLE)
26 if (platform_pml4e_is_huge(pml4e))
27 {
28 it->range.present = true;
30 it->range.pfn = platform_pml4e_get_huge_pfn(pml4e);
31 it->vaddr += PML4E_NPAGES * MOS_PAGE_SIZE;
32 it->range.pfn_end = it->range.pfn + PML4E_NPAGES - 1;
33 return;
34 }
35#endif
36
37 *pml3 = platform_pml4e_get_pml3(pml4e);
38 const pml3e_t *pml3e = pml3_entry(*pml3, it->vaddr);
39 if (!pml3e_is_present(pml3e))
40 return;
41
42#if MOS_CONFIG(PML3_HUGE_CAPABLE)
43 if (platform_pml3e_is_huge(pml3e))
44 {
45 it->range.present = true;
48 it->vaddr += PML3E_NPAGES * MOS_PAGE_SIZE;
49 it->range.pfn_end = it->range.pfn + PML3E_NPAGES - 1;
50 return;
51 }
52#endif
53
54 *pml2 = platform_pml3e_get_pml2(pml3e);
55 const pml2e_t *pml2e = pml2_entry(*pml2, it->vaddr);
56 if (!pml2e_is_present(pml2e))
57 return;
58
59#if MOS_CONFIG(PML2_HUGE_CAPABLE)
60 if (platform_pml2e_is_huge(pml2e))
61 {
62 it->range.present = true;
65 it->vaddr += PML2E_NPAGES * MOS_PAGE_SIZE;
66 it->range.pfn_end = it->range.pfn + PML2E_NPAGES - 1;
67 return;
68 }
69#endif
70
71 *pml1 = platform_pml2e_get_pml1(pml2e);
72 const pml1e_t *pml1e = pml1_entry(*pml1, it->vaddr);
74 if (!it->range.present)
75 return;
76
78 it->range.pfn = platform_pml1e_get_pfn(pml1e);
80 it->range.pfn_end = it->range.pfn + PML1E_NPAGES - 1;
81}
82
84{
85 memzero(it, sizeof(*it));
86 it->pgd = pgd;
87 it->vaddr = it->start = vaddr;
88 it->end = end;
89}
90
91#define yield_range() \
92 do \
93 { \
94 it->range.vaddr_end = it->vaddr - 1; \
95 return &it->range; \
96 } while (0)
97
99{
100#define _IS_IN_RANGE MOS_IN_RANGE(it->vaddr, it->start, it->end)
101 if (!_IS_IN_RANGE)
102 return NULL;
103
104 pml5_t pml5 = { 0 };
105 pml4_t pml4 = { 0 };
106 pml3_t pml3 = { 0 };
107 pml2_t pml2 = { 0 };
108 pml1_t pml1 = { 0 };
109
110 pagetable_iterator_start_current_range(it, &pml5, &pml4, &pml3, &pml2, &pml1);
111
112 if (!pml_null(pml1))
113 goto iterate_pml1;
114 else if (!pml_null(pml2))
115 goto iterate_pml2;
116 else if (!pml_null(pml3))
117 goto iterate_pml3;
118 else if (!pml_null(pml4))
119 goto iterate_pml4;
120 else
122
123 __builtin_unreachable();
124
125iterate_pml1:
126 for (u32 i = pml1_index(it->vaddr); i < PML1_ENTRIES && _IS_IN_RANGE; i++)
127 {
128 const pml1e_t *pml1e = &pml1.table[i];
129 const bool present = platform_pml1e_get_present(pml1e);
130
131 if (!present && present != it->range.present)
132 {
133 it->range.vaddr_end = it->vaddr - 1;
134 return &it->range;
135 }
136
137 if (!present)
138 {
140 continue;
141 }
142
143 const vm_flags new_flags = platform_pml1e_get_flags(pml1e);
144 const pfn_t new_pfn = platform_pml1e_get_pfn(pml1e);
145
146 bool changed = false;
147 changed |= new_flags != it->range.flags; // flags changed
148 changed |= new_pfn != it->range.pfn_end + 1; // pfn changed
149
150 if (changed)
151 yield_range();
152
153 it->vaddr += PML1E_NPAGES * MOS_PAGE_SIZE; // next time, we start from the next page
154 it->range.pfn_end = new_pfn + PML1E_NPAGES - 1;
155 }
156
157iterate_pml2:
158 for (u32 i = pml2_index(it->vaddr); i < PML2_ENTRIES && _IS_IN_RANGE; i++)
159 {
160 const pml2e_t *pml2e = &pml2.table[i];
161 const bool present = pml2e_is_present(pml2e);
162
163 if (!present && present != it->range.present)
164 yield_range();
165
166 if (!present)
167 {
168 it->vaddr += PML2E_NPAGES * MOS_PAGE_SIZE;
169 continue;
170 }
171
172#if MOS_CONFIG(PML2_HUGE_CAPABLE)
173 if (platform_pml2e_is_huge(pml2e))
174 {
175 const vm_flags new_flags = platform_pml2e_get_flags(pml2e);
176 const pfn_t new_pfn = platform_pml2e_get_huge_pfn(pml2e);
177
178 bool changed = false;
179 changed |= new_flags != it->range.flags; // flags changed
180 changed |= new_pfn != it->range.pfn_end + 1; // pfn changed
181
182 if (changed)
183 yield_range();
184
185 it->vaddr += PML2E_NPAGES * MOS_PAGE_SIZE;
186 it->range.pfn_end = new_pfn + PML2E_NPAGES - 1;
187 }
188 else
189#endif
190 {
191 pml1 = platform_pml2e_get_pml1(pml2e);
192 goto iterate_pml1; // iterate pml1
193 }
194 }
195
196iterate_pml3:
197 for (u32 i = pml3_index(it->vaddr); i < PML3_ENTRIES && _IS_IN_RANGE; i++)
198 {
199 const pml3e_t *pml3e = pml3_entry(pml3, it->vaddr);
200 const bool present = pml3e_is_present(pml3e);
201
202 if (!present && present != it->range.present)
203 yield_range();
204
205 if (!present)
206 {
207 it->vaddr += PML3E_NPAGES * MOS_PAGE_SIZE;
208 continue;
209 }
210
211#if MOS_CONFIG(PML3_HUGE_CAPABLE)
212 if (platform_pml3e_is_huge(pml3e))
213 {
214 const vm_flags new_flags = platform_pml3e_get_flags(pml3e);
215 const pfn_t new_pfn = platform_pml3e_get_huge_pfn(pml3e);
216
217 bool changed = false;
218 changed |= new_flags != it->range.flags; // flags changed
219 changed |= new_pfn != it->range.pfn_end + 1; // pfn changed
220
221 if (changed)
222 yield_range();
223
224 it->vaddr += PML3E_NPAGES * MOS_PAGE_SIZE;
225 it->range.pfn_end = new_pfn + PML3E_NPAGES - 1;
226 }
227 else
228#endif
229 {
230 pml2 = platform_pml3e_get_pml2(pml3e);
231 goto iterate_pml2; // iterate pml2
232 }
233 }
234
235iterate_pml4:
236 for (u32 i = pml4_index(it->vaddr); i < PML4_ENTRIES && _IS_IN_RANGE; i++)
237 {
238 const pml4e_t *pml4e = pml4_entry(pml4, it->vaddr);
239 const bool present = pml4e_is_present(pml4e);
240
241 if (!present && present != it->range.present)
242 yield_range();
243
244 if (!present)
245 {
246 it->vaddr += PML4E_NPAGES * MOS_PAGE_SIZE;
247 continue;
248 }
249
250 pml3 = platform_pml4e_get_pml3(pml4e);
251 goto iterate_pml3; // iterate pml3
252 }
253
254 yield_range();
255}
pml1_t platform_pml2e_get_pml1(const pml2e_t *pml2e)
Definition mm.cpp:107
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
vm_flags platform_pml4e_get_flags(const pml4e_t *pml4e)
Definition mm.cpp:231
vm_flags platform_pml1e_get_flags(const pml1e_t *pml1e)
Definition mm.cpp:101
pfn_t platform_pml1e_get_pfn(const pml1e_t *pml1e)
Definition mm.cpp:78
bool platform_pml1e_get_present(const pml1e_t *pml1e)
Definition mm.cpp:90
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
bool platform_pml2e_is_huge(const pml2e_t *pml2e)
Definition paging.cpp:167
pfn_t platform_pml3e_get_huge_pfn(const pml3e_t *pml3)
Definition paging.cpp:260
#define MOS_UNREACHABLE()
Definition assert.hpp:11
#define MOS_PAGE_SIZE
Definition autoconf.h:6
void pagetable_iter_init(pagetable_iter_t *it, pgd_t pgd, ptr_t vaddr, ptr_t end)
Initialize a pagetable iterator.
Definition iterator.cpp:83
pagetable_iter_range_t * pagetable_iter_next(pagetable_iter_t *it)
Get the next page table range.
Definition iterator.cpp:98
#define _IS_IN_RANGE
static void pagetable_iterator_start_current_range(pagetable_iter_t *it, pml5_t *pml5, pml4_t *pml4, pml3_t *pml3, pml2_t *pml2, pml1_t *pml1)
Definition iterator.cpp:14
#define yield_range()
Definition iterator.cpp:91
#define NULL
Definition pb_syshdr.h:46
vm_flags
Definition platform.hpp:42
pml1e_t * pml1_entry(pml1_t pml1, ptr_t vaddr)
Definition pml1.cpp:47
bool pml2e_is_present(const pml2e_t *pml2e)
Definition pml2.cpp:79
pml2e_t * pml2_entry(pml2_t pml2, ptr_t vaddr)
Definition pml2.cpp:74
bool pml3e_is_present(const pml3e_t *pml3e)
Definition pml3.cpp:27
pml3e_t * pml3_entry(pml3_t pml3, ptr_t vaddr)
Definition pml3.cpp:21
pml4e_t * pml4_entry(pml4_t pml4, ptr_t vaddr)
Definition pml4.cpp:22
bool pml4e_is_present(const pml4e_t *pml4e)
Definition pml4.cpp:28
#define pml_null(pmln)
Definition pml_types.hpp:32
pml3e_t pml4e_t
Definition pml_types.hpp:72
pml2e_t pml3e_t
Definition pml_types.hpp:60
#define pml1_index(vaddr)
Definition pml_types.hpp:37
#define PML1E_NPAGES
Definition pml_types.hpp:38
#define PML3_ENTRIES
#define PML1_ENTRIES
#define PML2_ENTRIES
#define PML4_ENTRIES
#define memzero(ptr, size)
pagetable_iter_range_t range
Definition iterator.hpp:23
pml1e_t * table
Definition pml_types.hpp:35
unsigned int u32
Definition types.h:17
unsigned long long pfn_t
Definition types.h:37
unsigned long ptr_t
Definition types.h:21