MOS Source Code
Loading...
Searching...
No Matches
table_ops.c
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
2
4
5#include "mos/mm/mm.h"
6#include "mos/mm/mmstat.h"
19#include "mos/syslog/printk.h"
20
21#include <mos/types.h>
22
23void mm_do_map(pgd_t pgd, ptr_t vaddr, pfn_t pfn, size_t n_pages, vm_flags flags, bool do_refcount)
24{
25 struct pagetable_do_map_data data = { .pfn = pfn, .flags = flags, .do_refcount = do_refcount };
26 pml5_traverse(pgd.max, &vaddr, &n_pages, pagetable_do_map_callbacks, &data);
27}
28
29void mm_do_flag(pgd_t max, ptr_t vaddr, size_t n_pages, vm_flags flags)
30{
31 struct pagetable_do_flag_data data = { .flags = flags };
32 pml5_traverse(max.max, &vaddr, &n_pages, pagetable_do_flag_callbacks, &data);
33}
34
35void mm_do_unmap(pgd_t max, ptr_t vaddr, size_t n_pages, bool do_unref)
36{
37 pr_dinfo2(vmm, "mm_do_unmap: vaddr=" PTR_FMT ", n_pages=%zu, do_unref=%d", vaddr, n_pages, do_unref);
38 ptr_t vaddr1 = vaddr;
39 size_t n_pages1 = n_pages;
40
41 const ptr_t vaddr2 = vaddr;
42 const size_t n_pages2 = n_pages;
43
44 struct pagetable_do_unmap_data data = { .do_unref = do_unref };
45 pml5_traverse(max.max, &vaddr, &n_pages, pagetable_do_unmap_callbacks, &data);
46 bool pml5_destroyed = pml5_destroy_range(max.max, &vaddr1, &n_pages1);
47 if (pml5_destroyed)
48 pr_warn("mm_do_unmap: pml5 destroyed: vaddr=" PTR_RANGE ", n_pages=%zu", vaddr2, vaddr2 + n_pages2 * MOS_PAGE_SIZE, n_pages2);
49}
50
51void mm_do_mask_flags(pgd_t max, ptr_t vaddr, size_t n_pages, vm_flags mask)
52{
53 struct pagetable_do_mask_data data = { .mask = mask };
54 pml5_traverse(max.max, &vaddr, &n_pages, pagetable_do_mask_callbacks, &data);
55}
56
57void mm_do_copy(pgd_t src, pgd_t dst, ptr_t vaddr, size_t n_pages)
58{
59 struct pagetable_do_copy_data data = {
60 .dest_pml5 = dst.max,
61 .dest_pml5e = pml5_entry(dst.max, vaddr),
62 .dest_pml4 = pml5e_get_or_create_pml4(data.dest_pml5e),
63 };
64 pml5_traverse(src.max, &vaddr, &n_pages, pagetable_do_copy_callbacks, &data);
65}
66
68{
69 vaddr = ALIGN_DOWN_TO_PAGE(vaddr);
70 pml5e_t *pml5e = pml5_entry(max.max, vaddr);
71 if (!pml5e_is_present(pml5e))
72 return 0;
73
74 const pml4_t pml4 = pml5e_get_or_create_pml4(pml5e);
75 pml4e_t *pml4e = pml4_entry(pml4, vaddr);
76 if (!pml4e_is_present(pml4e))
77 return 0;
78
79#if MOS_CONFIG(PML4_HUGE_CAPABLE)
80 if (platform_pml4e_is_huge(pml4e))
81 return platform_pml4e_get_huge_pfn(pml4e) + (vaddr & PML4_HUGE_MASK) / MOS_PAGE_SIZE;
82#endif
83
84 const pml3_t pml3 = pml4e_get_or_create_pml3(pml4e);
85 pml3e_t *pml3e = pml3_entry(pml3, vaddr);
86 if (!pml3e_is_present(pml3e))
87 return 0;
88
89#if MOS_CONFIG(PML3_HUGE_CAPABLE)
90 if (platform_pml3e_is_huge(pml3e))
91 return platform_pml3e_get_huge_pfn(pml3e) + (vaddr & PML3_HUGE_MASK) / MOS_PAGE_SIZE;
92#endif
93
94 const pml2_t pml2 = pml3e_get_or_create_pml2(pml3e);
95 pml2e_t *pml2e = pml2_entry(pml2, vaddr);
96 if (!pml2e_is_present(pml2e))
97 return 0;
98
99#if MOS_CONFIG(PML2_HUGE_CAPABLE)
100 if (platform_pml2e_is_huge(pml2e))
101 return platform_pml2e_get_huge_pfn(pml2e) + (vaddr & PML2_HUGE_MASK) / MOS_PAGE_SIZE;
102#endif
103
104 const pml1_t pml1 = pml2e_get_or_create_pml1(pml2e);
105 const pml1e_t *pml1e = pml1_entry(pml1, vaddr);
106 if (!pml1e_is_present(pml1e))
107 return 0;
108
109 return pml1e_get_pfn(pml1e);
110}
111
113{
114 vm_flags flags = ~0;
115 vaddr = ALIGN_DOWN_TO_PAGE(vaddr);
116 pml5e_t *pml5e = pml5_entry(max.max, vaddr);
117 if (!pml5e_is_present(pml5e))
118 return 0;
119
120 const pml4_t pml4 = pml5e_get_or_create_pml4(pml5e);
121 pml4e_t *pml4e = pml4_entry(pml4, vaddr);
122 if (!pml4e_is_present(pml4e))
123 return 0;
124
125#if MOS_CONFIG(PML4_HUGE_CAPABLE)
126 if (platform_pml4e_is_huge(pml4e))
127 return platform_pml4e_get_flags(pml4e);
128 else
129 flags &= platform_pml4e_get_flags(pml4e);
130#else
131 flags &= platform_pml4e_get_flags(pml4e);
132#endif
133
134 const pml3_t pml3 = pml4e_get_or_create_pml3(pml4e);
135 pml3e_t *pml3e = pml3_entry(pml3, vaddr);
136 if (!pml3e_is_present(pml3e))
137 return 0;
138
139#if MOS_CONFIG(PML3_HUGE_CAPABLE)
140 if (platform_pml3e_is_huge(pml3e))
141 return platform_pml3e_get_flags(pml3e);
142 else
143 flags &= platform_pml3e_get_flags(pml3e);
144#else
145 flags &= platform_pml3e_get_flags(pml3e);
146#endif
147
148 const pml2_t pml2 = pml3e_get_or_create_pml2(pml3e);
149 pml2e_t *pml2e = pml2_entry(pml2, vaddr);
150 if (!pml2e_is_present(pml2e))
151 return 0;
152
153#if MOS_CONFIG(PML2_HUGE_CAPABLE)
154 if (platform_pml2e_is_huge(pml2e))
155 return platform_pml2e_get_flags(pml2e);
156 else
157 flags &= platform_pml2e_get_flags(pml2e);
158#else
159 flags &= platform_pml2e_get_flags(pml2e);
160#endif
161
162 const pml1_t pml1 = pml2e_get_or_create_pml1(pml2e);
163 const pml1e_t *pml1e = pml1_entry(pml1, vaddr);
164 if (!pml1e_is_present(pml1e))
165 return 0;
166
167 flags &= platform_pml1e_get_flags(pml1e);
168 return flags;
169}
170
172{
173 vaddr = ALIGN_DOWN_TO_PAGE(vaddr);
174 pml5e_t *pml5e = pml5_entry(max.max, vaddr);
175 if (!pml5e_is_present(pml5e))
176 return false;
177
178 const pml4_t pml4 = pml5e_get_or_create_pml4(pml5e);
179 pml4e_t *pml4e = pml4_entry(pml4, vaddr);
180 if (!pml4e_is_present(pml4e))
181 return false;
182
183 const pml3_t pml3 = pml4e_get_or_create_pml3(pml4e);
184 pml3e_t *pml3e = pml3_entry(pml3, vaddr);
185 if (!pml3e_is_present(pml3e))
186 return false;
187
188 const pml2_t pml2 = pml3e_get_or_create_pml2(pml3e);
189 pml2e_t *pml2e = pml2_entry(pml2, vaddr);
190 if (!pml2e_is_present(pml2e))
191 return false;
192
193 const pml1_t pml1 = pml2e_get_or_create_pml1(pml2e);
194 const pml1e_t *pml1e = pml1_entry(pml1, vaddr);
195 return pml1e_is_present(pml1e);
196}
197
199{
201 return (void *) phyframe_va(mm_get_free_page());
202}
203
204void __destroy_page_table(void *table)
205{
207 pr_dinfo2(vmm, "__destroy_page_table: table=" PTR_FMT, (ptr_t) table);
209}
vm_flags platform_pml3e_get_flags(const pml3e_t *pml3e)
Definition mm.c:181
vm_flags platform_pml4e_get_flags(const pml4e_t *pml4e)
Definition mm.c:231
vm_flags platform_pml1e_get_flags(const pml1e_t *pml1e)
Definition mm.c:101
vm_flags platform_pml2e_get_flags(const pml2e_t *pml2e)
Definition mm.c:131
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
bool platform_pml2e_is_huge(const pml2e_t *pml2e)
Definition paging.c:166
pfn_t platform_pml3e_get_huge_pfn(const pml3e_t *pml3)
Definition paging.c:259
#define MOS_PAGE_SIZE
Definition autoconf.h:6
const pagetable_walk_options_t pagetable_do_copy_callbacks
Definition do_copy.c:67
const pagetable_walk_options_t pagetable_do_flag_callbacks
Definition do_flag.c:41
const pagetable_walk_options_t pagetable_do_map_callbacks
Definition do_map.c:44
const pagetable_walk_options_t pagetable_do_mask_callbacks
Definition do_mask.c:21
const pagetable_walk_options_t pagetable_do_unmap_callbacks
Definition do_unmap.c:48
__BEGIN_DECLS phyframe_t * mm_get_free_page(void)
Definition mm.c:46
#define va_phyframe(va)
Definition mm.h:78
#define phyframe_va(frame)
Definition mm.h:79
#define mm_free_page(frame)
Definition mm.h:88
#define mmstat_dec1(type)
Definition mmstat.h:35
#define mmstat_inc1(type)
Definition mmstat.h:26
@ MEM_PAGETABLE
Definition mmstat.h:8
#define ALIGN_DOWN_TO_PAGE(addr)
Definition mos_global.h:76
vm_flags
Definition platform.h:40
pfn_t pml1e_get_pfn(const pml1e_t *pml1e)
Definition pml1.c:55
bool pml1e_is_present(const pml1e_t *pml1e)
Definition pml1.c:50
pml1e_t * pml1_entry(pml1_t pml1, ptr_t vaddr)
Definition pml1.c:45
pml1_t pml2e_get_or_create_pml1(pml2e_t *pml2e)
Definition pml2.c:83
bool pml2e_is_present(const pml2e_t *pml2e)
Definition pml2.c:78
pml2e_t * pml2_entry(pml2_t pml2, ptr_t vaddr)
Definition pml2.c:73
pml2_t pml3e_get_or_create_pml2(pml3e_t *pml3e)
bool pml3e_is_present(const pml3e_t *pml3e)
Definition pml3.c:26
pml3e_t * pml3_entry(pml3_t pml3, ptr_t vaddr)
Definition pml3.c:20
pml3_t pml4e_get_or_create_pml3(pml4e_t *pml4e)
pml4e_t * pml4_entry(pml4_t pml4, ptr_t vaddr)
Definition pml4.c:21
bool pml4e_is_present(const pml4e_t *pml4e)
Definition pml4.c:27
pml5e_t * pml5_entry(pml5_t pml5, ptr_t vaddr)
Definition pml5.c:23
bool pml5e_is_present(const pml5e_t *pml5e)
Definition pml5.c:29
pml4_t pml5e_get_or_create_pml4(pml5e_t *pml5e)
Definition pml5.c:35
void pml5_traverse(pml5_t pml5, ptr_t *vaddr, size_t *n_pages, pagetable_walk_options_t callback, void *data)
Definition pml5.c:12
__nodiscard bool pml5_destroy_range(pml5_t pml5, ptr_t *vaddr, size_t *n_pages)
Definition pml5.c:17
pml3e_t pml4e_t
Definition pml_types.h:72
pml4e_t pml5e_t
Definition pml_types.h:79
pml2e_t pml3e_t
Definition pml_types.h:60
#define pr_warn(fmt,...)
Definition printk.h:38
#define pr_dinfo2(feat, fmt,...)
Definition printk.h:27
pml5e_t * dest_pml5e
Definition do_copy.h:10
vm_flags mm_do_get_flags(pgd_t max, ptr_t vaddr)
Definition table_ops.c:112
void __destroy_page_table(void *table)
Definition table_ops.c:204
void * __create_page_table(void)
Definition table_ops.c:198
void mm_do_map(pgd_t pgd, ptr_t vaddr, pfn_t pfn, size_t n_pages, vm_flags flags, bool do_refcount)
Definition table_ops.c:23
bool mm_do_get_present(pgd_t max, ptr_t vaddr)
Definition table_ops.c:171
void mm_do_copy(pgd_t src, pgd_t dst, ptr_t vaddr, size_t n_pages)
Definition table_ops.c:57
void mm_do_mask_flags(pgd_t max, ptr_t vaddr, size_t n_pages, vm_flags mask)
Definition table_ops.c:51
void mm_do_flag(pgd_t max, ptr_t vaddr, size_t n_pages, vm_flags flags)
Definition table_ops.c:29
pfn_t mm_do_get_pfn(pgd_t max, ptr_t vaddr)
Definition table_ops.c:67
void mm_do_unmap(pgd_t max, ptr_t vaddr, size_t n_pages, bool do_unref)
Definition table_ops.c:35
unsigned long long pfn_t
Definition types.h:41
#define PTR_RANGE
Definition types.h:36
#define PTR_FMT
Definition types.h:33
unsigned long ptr_t
Definition types.h:25