pmap_machdep.h revision 1.10 1 1.10 skrll /* $NetBSD: pmap_machdep.h,v 1.10 2025/10/09 06:18:38 skrll Exp $ */
2 1.1 skrll
3 1.1 skrll /*-
4 1.1 skrll * Copyright (c) 2022 The NetBSD Foundation, Inc.
5 1.1 skrll * All rights reserved.
6 1.1 skrll *
7 1.1 skrll * This code is derived from software contributed to The NetBSD Foundation
8 1.1 skrll * by Nick Hudson
9 1.1 skrll *
10 1.1 skrll * Redistribution and use in source and binary forms, with or without
11 1.1 skrll * modification, are permitted provided that the following conditions
12 1.1 skrll * are met:
13 1.1 skrll * 1. Redistributions of source code must retain the above copyright
14 1.1 skrll * notice, this list of conditions and the following disclaimer.
15 1.1 skrll * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 skrll * notice, this list of conditions and the following disclaimer in the
17 1.1 skrll * documentation and/or other materials provided with the distribution.
18 1.1 skrll *
19 1.1 skrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 skrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 skrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 skrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 skrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 skrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 skrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 skrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 skrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 skrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 skrll * POSSIBILITY OF SUCH DAMAGE.
30 1.1 skrll */
31 1.1 skrll
32 1.1 skrll #ifndef _AARCH64_PMAP_MACHDEP_H_
33 1.1 skrll #define _AARCH64_PMAP_MACHDEP_H_
34 1.1 skrll
35 1.1 skrll #include <arm/cpufunc.h>
36 1.1 skrll
37 1.1 skrll #define PMAP_HWPAGEWALKER 1
38 1.1 skrll
39 1.1 skrll #define PMAP_PDETABSIZE (PAGE_SIZE / sizeof(pd_entry_t))
40 1.1 skrll #define PMAP_SEGTABSIZE NSEGPG
41 1.1 skrll
42 1.1 skrll #define PMAP_INVALID_PDETAB_ADDRESS ((pmap_pdetab_t *)(VM_MIN_KERNEL_ADDRESS - PAGE_SIZE))
43 1.1 skrll #define PMAP_INVALID_SEGTAB_ADDRESS ((pmap_segtab_t *)(VM_MIN_KERNEL_ADDRESS - PAGE_SIZE))
44 1.1 skrll
45 1.1 skrll #define NPTEPG (PAGE_SIZE / sizeof(pt_entry_t))
46 1.1 skrll #define NPDEPG (PAGE_SIZE / sizeof(pd_entry_t))
47 1.1 skrll
48 1.1 skrll #define PTPSHIFT 3
49 1.1 skrll #define PTPLENGTH (PGSHIFT - PTPSHIFT)
50 1.1 skrll #define SEGSHIFT (PGSHIFT + PTPLENGTH) /* LOG2(NBSEG) */
51 1.1 skrll
52 1.1 skrll #define NBSEG (1 << SEGSHIFT) /* bytes/segment */
53 1.1 skrll #define SEGOFSET (NBSEG - 1) /* byte offset into segment */
54 1.1 skrll
55 1.1 skrll #define SEGLENGTH (PGSHIFT - 3)
56 1.1 skrll
57 1.1 skrll #define XSEGSHIFT (SEGSHIFT + SEGLENGTH + SEGLENGTH)
58 1.1 skrll /* LOG2(NBXSEG) */
59 1.1 skrll
60 1.1 skrll #define NBXSEG (1UL << XSEGSHIFT) /* bytes/xsegment */
61 1.1 skrll #define XSEGOFSET (NBXSEG - 1) /* byte offset into xsegment */
62 1.1 skrll #define XSEGLENGTH (PGSHIFT - 3)
63 1.1 skrll #define NXSEGPG (1 << XSEGLENGTH)
64 1.1 skrll #define NSEGPG (1 << SEGLENGTH)
65 1.1 skrll
66 1.1 skrll
67 1.4 skrll #ifndef __BSD_PTENTRY_T__
68 1.1 skrll #define __BSD_PTENTRY_T__
69 1.4 skrll #define PRIxPTE PRIx64
70 1.1 skrll #endif /* __BSD_PTENTRY_T__ */
71 1.1 skrll
72 1.1 skrll #define KERNEL_PID 0
73 1.1 skrll
74 1.1 skrll #define __HAVE_PMAP_PV_TRACK
75 1.1 skrll #define __HAVE_PMAP_MD
76 1.1 skrll
77 1.1 skrll /* XXX temporary */
78 1.1 skrll #define __HAVE_UNLOCKED_PMAP
79 1.1 skrll
80 1.1 skrll #define PMAP_PAGE_INIT(pp) \
81 1.1 skrll do { \
82 1.1 skrll (pp)->pp_md.mdpg_first.pv_next = NULL; \
83 1.1 skrll (pp)->pp_md.mdpg_first.pv_pmap = NULL; \
84 1.1 skrll (pp)->pp_md.mdpg_first.pv_va = 0; \
85 1.1 skrll (pp)->pp_md.mdpg_attrs = 0; \
86 1.1 skrll VM_PAGEMD_PVLIST_LOCK_INIT(&(pp)->pp_md); \
87 1.1 skrll } while (/* CONSTCOND */ 0)
88 1.1 skrll
89 1.1 skrll struct pmap_md {
90 1.1 skrll paddr_t pmd_l0_pa;
91 1.1 skrll };
92 1.1 skrll
93 1.1 skrll #define pm_l0_pa pm_md.pmd_l0_pa
94 1.1 skrll
95 1.4 skrll void pmap_md_pdetab_init(struct pmap *);
96 1.4 skrll void pmap_md_pdetab_fini(struct pmap *);
97 1.1 skrll
98 1.4 skrll vaddr_t pmap_md_map_poolpage(paddr_t, size_t);
99 1.4 skrll paddr_t pmap_md_unmap_poolpage(vaddr_t, size_t);
100 1.4 skrll
101 1.4 skrll struct vm_page *
102 1.4 skrll pmap_md_alloc_poolpage(int);
103 1.1 skrll
104 1.1 skrll bool pmap_md_direct_mapped_vaddr_p(vaddr_t);
105 1.1 skrll paddr_t pmap_md_direct_mapped_vaddr_to_paddr(vaddr_t);
106 1.1 skrll vaddr_t pmap_md_direct_map_paddr(paddr_t);
107 1.1 skrll bool pmap_md_io_vaddr_p(vaddr_t);
108 1.1 skrll
109 1.1 skrll void pmap_md_activate_efirt(void);
110 1.1 skrll void pmap_md_deactivate_efirt(void);
111 1.1 skrll
112 1.1 skrll void pmap_icache_sync_range(pmap_t, vaddr_t, vaddr_t);
113 1.1 skrll
114 1.3 skrll vsize_t pmap_kenter_range(vaddr_t, paddr_t, vsize_t, vm_prot_t, u_int flags);
115 1.3 skrll
116 1.1 skrll #include <uvm/pmap/vmpagemd.h>
117 1.1 skrll #include <uvm/pmap/pmap.h>
118 1.1 skrll #include <uvm/pmap/pmap_pvt.h>
119 1.1 skrll #include <uvm/pmap/pmap_tlb.h>
120 1.1 skrll #include <uvm/pmap/pmap_synci.h>
121 1.1 skrll #include <uvm/pmap/tlb.h>
122 1.1 skrll
123 1.1 skrll #include <uvm/uvm_page.h>
124 1.1 skrll
125 1.1 skrll #define POOL_VTOPHYS(va) vtophys((vaddr_t)(va))
126 1.1 skrll
127 1.1 skrll struct pmap_page {
128 1.1 skrll struct vm_page_md pp_md;
129 1.1 skrll };
130 1.1 skrll
131 1.1 skrll #define PMAP_PAGE_TO_MD(ppage) (&((ppage)->pp_md))
132 1.1 skrll
133 1.1 skrll #define PVLIST_EMPTY_P(pg) VM_PAGEMD_PVLIST_EMPTY_P(VM_PAGE_TO_MD(pg))
134 1.1 skrll
135 1.1 skrll #define LX_BLKPAG_OS_MODIFIED LX_BLKPAG_OS_0
136 1.1 skrll
137 1.1 skrll #define PMAP_PTE_OS0 "modified"
138 1.1 skrll #define PMAP_PTE_OS1 "(unk)"
139 1.1 skrll
140 1.1 skrll static inline paddr_t
141 1.1 skrll pmap_l0pa(struct pmap *pm)
142 1.1 skrll {
143 1.4 skrll return pm->pm_l0_pa;
144 1.1 skrll }
145 1.1 skrll
146 1.1 skrll #if defined(__PMAP_PRIVATE)
147 1.1 skrll
148 1.1 skrll #include <uvm/uvm_physseg.h>
149 1.1 skrll struct vm_page_md;
150 1.1 skrll
151 1.1 skrll void pmap_md_icache_sync_all(void);
152 1.1 skrll void pmap_md_icache_sync_range_index(vaddr_t, vsize_t);
153 1.1 skrll void pmap_md_page_syncicache(struct vm_page_md *, const kcpuset_t *);
154 1.1 skrll bool pmap_md_vca_add(struct vm_page_md *, vaddr_t, pt_entry_t *);
155 1.1 skrll void pmap_md_vca_clean(struct vm_page_md *, int);
156 1.1 skrll void pmap_md_vca_remove(struct vm_page_md *, vaddr_t, bool, bool);
157 1.1 skrll bool pmap_md_ok_to_steal_p(const uvm_physseg_t, size_t);
158 1.1 skrll
159 1.1 skrll void pmap_md_xtab_activate(pmap_t, struct lwp *);
160 1.1 skrll void pmap_md_xtab_deactivate(pmap_t);
161 1.1 skrll
162 1.4 skrll vaddr_t pmap_md_direct_map_paddr(paddr_t);
163 1.1 skrll
164 1.1 skrll
165 1.1 skrll #ifdef MULTIPROCESSOR
166 1.1 skrll #define PMAP_NO_PV_UNCACHED
167 1.1 skrll #endif
168 1.1 skrll
169 1.1 skrll static inline void
170 1.1 skrll pmap_md_init(void)
171 1.1 skrll {
172 1.1 skrll // nothing
173 1.1 skrll }
174 1.1 skrll
175 1.1 skrll
176 1.1 skrll static inline bool
177 1.1 skrll pmap_md_tlb_check_entry(void *ctx, vaddr_t va, tlb_asid_t asid, pt_entry_t pte)
178 1.1 skrll {
179 1.1 skrll // TLB not walked and so not called.
180 1.1 skrll return false;
181 1.1 skrll }
182 1.1 skrll
183 1.1 skrll
184 1.1 skrll static inline bool
185 1.1 skrll pmap_md_virtual_cache_aliasing_p(void)
186 1.1 skrll {
187 1.1 skrll return false;
188 1.1 skrll }
189 1.1 skrll
190 1.1 skrll
191 1.1 skrll static inline vsize_t
192 1.1 skrll pmap_md_cache_prefer_mask(void)
193 1.1 skrll {
194 1.1 skrll return 0;
195 1.1 skrll }
196 1.1 skrll
197 1.1 skrll
198 1.1 skrll static inline pt_entry_t *
199 1.1 skrll pmap_md_nptep(pt_entry_t *ptep)
200 1.1 skrll {
201 1.1 skrll
202 1.1 skrll return ptep + 1;
203 1.1 skrll }
204 1.1 skrll
205 1.1 skrll
206 1.1 skrll static __inline paddr_t
207 1.1 skrll pte_to_paddr(pt_entry_t pte)
208 1.1 skrll {
209 1.1 skrll
210 1.1 skrll return l3pte_pa(pte);
211 1.1 skrll }
212 1.1 skrll
213 1.1 skrll
214 1.1 skrll static inline bool
215 1.1 skrll pte_valid_p(pt_entry_t pte)
216 1.1 skrll {
217 1.1 skrll
218 1.1 skrll return l3pte_valid(pte);
219 1.1 skrll }
220 1.1 skrll
221 1.1 skrll
222 1.1 skrll static inline void
223 1.1 skrll pmap_md_clean_page(struct vm_page_md *md, bool is_src)
224 1.1 skrll {
225 1.1 skrll }
226 1.1 skrll
227 1.1 skrll
228 1.1 skrll static inline bool
229 1.1 skrll pte_modified_p(pt_entry_t pte)
230 1.1 skrll {
231 1.1 skrll
232 1.1 skrll return (pte & LX_BLKPAG_OS_MODIFIED) != 0;
233 1.1 skrll }
234 1.1 skrll
235 1.1 skrll
236 1.1 skrll static inline bool
237 1.1 skrll pte_wired_p(pt_entry_t pte)
238 1.1 skrll {
239 1.1 skrll
240 1.4 skrll return (pte & LX_BLKPAG_OS_WIRED) != 0;
241 1.1 skrll }
242 1.1 skrll
243 1.1 skrll
244 1.1 skrll static inline pt_entry_t
245 1.1 skrll pte_wire_entry(pt_entry_t pte)
246 1.1 skrll {
247 1.1 skrll
248 1.4 skrll return pte | LX_BLKPAG_OS_WIRED;
249 1.1 skrll }
250 1.1 skrll
251 1.1 skrll
252 1.1 skrll static inline pt_entry_t
253 1.1 skrll pte_unwire_entry(pt_entry_t pte)
254 1.1 skrll {
255 1.1 skrll
256 1.4 skrll return pte & ~LX_BLKPAG_OS_WIRED;
257 1.1 skrll }
258 1.1 skrll
259 1.1 skrll
260 1.1 skrll static inline uint64_t
261 1.1 skrll pte_value(pt_entry_t pte)
262 1.1 skrll {
263 1.1 skrll
264 1.1 skrll return pte;
265 1.1 skrll }
266 1.1 skrll
267 1.1 skrll static inline bool
268 1.1 skrll pte_cached_p(pt_entry_t pte)
269 1.1 skrll {
270 1.1 skrll
271 1.1 skrll return ((pte & LX_BLKPAG_ATTR_MASK) == LX_BLKPAG_ATTR_NORMAL_WB);
272 1.1 skrll }
273 1.1 skrll
274 1.1 skrll static inline bool
275 1.1 skrll pte_deferred_exec_p(pt_entry_t pte)
276 1.1 skrll {
277 1.1 skrll
278 1.1 skrll return false;
279 1.1 skrll }
280 1.1 skrll
281 1.1 skrll static inline pt_entry_t
282 1.1 skrll pte_nv_entry(bool kernel_p)
283 1.1 skrll {
284 1.1 skrll
285 1.1 skrll /* Not valid entry */
286 1.1 skrll return kernel_p ? 0 : 0;
287 1.1 skrll }
288 1.1 skrll
289 1.1 skrll static inline pt_entry_t
290 1.1 skrll pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot)
291 1.1 skrll {
292 1.1 skrll
293 1.1 skrll return (pte & ~LX_BLKPAG_AP)
294 1.1 skrll | (((prot) & (VM_PROT_READ | VM_PROT_WRITE)) == VM_PROT_READ ? LX_BLKPAG_AP_RO : LX_BLKPAG_AP_RW);
295 1.1 skrll }
296 1.1 skrll
297 1.1 skrll static inline pt_entry_t
298 1.1 skrll pte_prot_nowrite(pt_entry_t pte)
299 1.1 skrll {
300 1.1 skrll
301 1.1 skrll return pte & ~LX_BLKPAG_AF;
302 1.1 skrll }
303 1.1 skrll
304 1.1 skrll static inline pt_entry_t
305 1.1 skrll pte_cached_change(pt_entry_t pte, bool cached)
306 1.1 skrll {
307 1.1 skrll pte &= ~LX_BLKPAG_ATTR_MASK;
308 1.1 skrll pte |= (cached ? LX_BLKPAG_ATTR_NORMAL_WB : LX_BLKPAG_ATTR_NORMAL_NC);
309 1.1 skrll
310 1.1 skrll return pte;
311 1.1 skrll }
312 1.1 skrll
313 1.1 skrll static inline void
314 1.1 skrll pte_set(pt_entry_t *ptep, pt_entry_t pte)
315 1.1 skrll {
316 1.1 skrll
317 1.1 skrll *ptep = pte;
318 1.1 skrll dsb(ishst);
319 1.1 skrll /*
320 1.5 skrll * if this mapping is going to be used by userland then the eret *can*
321 1.5 skrll * act as the isb, but might not (apple m1).
322 1.1 skrll *
323 1.5 skrll * if this mapping is kernel then the isb is always needed (for some
324 1.5 skrll * micro-architectures)
325 1.1 skrll */
326 1.1 skrll
327 1.1 skrll isb();
328 1.1 skrll }
329 1.1 skrll
330 1.1 skrll static inline pd_entry_t
331 1.1 skrll pte_invalid_pde(void)
332 1.1 skrll {
333 1.1 skrll
334 1.1 skrll return 0;
335 1.1 skrll }
336 1.1 skrll
337 1.1 skrll
338 1.1 skrll static inline pd_entry_t
339 1.1 skrll pte_pde_pdetab(paddr_t pa, bool kernel_p)
340 1.1 skrll {
341 1.1 skrll
342 1.1 skrll return LX_VALID | LX_TYPE_TBL | (kernel_p ? 0 : LX_BLKPAG_NG) | pa;
343 1.1 skrll }
344 1.1 skrll
345 1.1 skrll
346 1.1 skrll static inline pd_entry_t
347 1.1 skrll pte_pde_ptpage(paddr_t pa, bool kernel_p)
348 1.1 skrll {
349 1.1 skrll
350 1.1 skrll return LX_VALID | LX_TYPE_TBL | (kernel_p ? 0 : LX_BLKPAG_NG) | pa;
351 1.1 skrll }
352 1.1 skrll
353 1.1 skrll
354 1.1 skrll static inline bool
355 1.1 skrll pte_pde_valid_p(pd_entry_t pde)
356 1.1 skrll {
357 1.1 skrll
358 1.1 skrll return lxpde_valid(pde);
359 1.1 skrll }
360 1.1 skrll
361 1.1 skrll
362 1.1 skrll static inline paddr_t
363 1.1 skrll pte_pde_to_paddr(pd_entry_t pde)
364 1.1 skrll {
365 1.1 skrll
366 1.1 skrll return lxpde_pa(pde);
367 1.1 skrll }
368 1.1 skrll
369 1.1 skrll
370 1.1 skrll static inline pd_entry_t
371 1.1 skrll pte_pde_cas(pd_entry_t *pdep, pd_entry_t opde, pt_entry_t npde)
372 1.1 skrll {
373 1.1 skrll #ifdef MULTIPROCESSOR
374 1.1 skrll opde = atomic_cas_64(pdep, opde, npde);
375 1.1 skrll #else
376 1.1 skrll *pdep = npde;
377 1.1 skrll #endif
378 1.1 skrll return opde;
379 1.1 skrll }
380 1.1 skrll
381 1.1 skrll
382 1.1 skrll static inline void
383 1.1 skrll pte_pde_set(pd_entry_t *pdep, pd_entry_t npde)
384 1.1 skrll {
385 1.1 skrll
386 1.1 skrll *pdep = npde;
387 1.1 skrll }
388 1.1 skrll
389 1.1 skrll
390 1.1 skrll static inline pt_entry_t
391 1.1 skrll pte_memattr(u_int flags)
392 1.1 skrll {
393 1.1 skrll
394 1.1 skrll switch (flags & (PMAP_DEV_MASK | PMAP_CACHE_MASK)) {
395 1.1 skrll case PMAP_DEV_NP ... PMAP_DEV_NP | PMAP_CACHE_MASK:
396 1.1 skrll /* Device-nGnRnE */
397 1.1 skrll return LX_BLKPAG_ATTR_DEVICE_MEM_NP;
398 1.1 skrll case PMAP_DEV ... PMAP_DEV | PMAP_CACHE_MASK:
399 1.1 skrll /* Device-nGnRE */
400 1.1 skrll return LX_BLKPAG_ATTR_DEVICE_MEM;
401 1.1 skrll case PMAP_NOCACHE:
402 1.1 skrll case PMAP_NOCACHE_OVR:
403 1.1 skrll case PMAP_WRITE_COMBINE:
404 1.1 skrll /* only no-cache */
405 1.1 skrll return LX_BLKPAG_ATTR_NORMAL_NC;
406 1.1 skrll case PMAP_WRITE_BACK:
407 1.1 skrll case 0:
408 1.1 skrll default:
409 1.1 skrll return LX_BLKPAG_ATTR_NORMAL_WB;
410 1.1 skrll }
411 1.1 skrll }
412 1.1 skrll
413 1.1 skrll
414 1.1 skrll static inline pt_entry_t
415 1.1 skrll pte_make_kenter_pa(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
416 1.1 skrll u_int flags)
417 1.1 skrll {
418 1.1 skrll KASSERTMSG((pa & ~L3_PAG_OA) == 0, "pa %" PRIxPADDR, pa);
419 1.1 skrll
420 1.1 skrll pt_entry_t pte = pa
421 1.1 skrll | LX_VALID
422 1.1 skrll #ifdef MULTIPROCESSOR
423 1.1 skrll | LX_BLKPAG_SH_IS
424 1.1 skrll #endif
425 1.1 skrll | L3_TYPE_PAG
426 1.1 skrll | LX_BLKPAG_AF
427 1.1 skrll | LX_BLKPAG_UXN | LX_BLKPAG_PXN
428 1.1 skrll | (((prot) & (VM_PROT_READ | VM_PROT_WRITE)) == VM_PROT_READ ? LX_BLKPAG_AP_RO : LX_BLKPAG_AP_RW)
429 1.1 skrll | LX_BLKPAG_OS_WIRED;
430 1.1 skrll
431 1.1 skrll if (prot & VM_PROT_EXECUTE)
432 1.1 skrll pte &= ~LX_BLKPAG_PXN;
433 1.1 skrll
434 1.1 skrll pte &= ~LX_BLKPAG_ATTR_MASK;
435 1.1 skrll pte |= pte_memattr(flags);
436 1.1 skrll
437 1.1 skrll return pte;
438 1.1 skrll }
439 1.1 skrll
440 1.8 skrll
441 1.9 martin #if defined(EFI_RUNTIME)
442 1.1 skrll static inline pt_entry_t
443 1.1 skrll pte_make_enter_efirt(paddr_t pa, vm_prot_t prot, u_int flags)
444 1.1 skrll {
445 1.1 skrll KASSERTMSG((pa & ~L3_PAG_OA) == 0, "pa %" PRIxPADDR, pa);
446 1.1 skrll
447 1.1 skrll pt_entry_t npte = pa
448 1.1 skrll | LX_VALID
449 1.1 skrll #ifdef MULTIPROCESSOR
450 1.1 skrll | LX_BLKPAG_SH_IS
451 1.1 skrll #endif
452 1.1 skrll | L3_TYPE_PAG
453 1.1 skrll | LX_BLKPAG_AF
454 1.1 skrll | LX_BLKPAG_NG /* | LX_BLKPAG_APUSER */
455 1.1 skrll | LX_BLKPAG_UXN | LX_BLKPAG_PXN
456 1.1 skrll | (((prot) & (VM_PROT_READ | VM_PROT_WRITE)) == VM_PROT_READ ? LX_BLKPAG_AP_RO : LX_BLKPAG_AP_RW);
457 1.1 skrll
458 1.1 skrll if (prot & VM_PROT_EXECUTE)
459 1.1 skrll npte &= ~LX_BLKPAG_PXN;
460 1.1 skrll
461 1.1 skrll npte &= ~LX_BLKPAG_ATTR_MASK;
462 1.1 skrll npte |= pte_memattr(flags);
463 1.1 skrll
464 1.1 skrll return npte;
465 1.1 skrll }
466 1.9 martin #endif
467 1.1 skrll
468 1.8 skrll
469 1.1 skrll static inline pt_entry_t
470 1.1 skrll pte_make_enter(paddr_t pa, const struct vm_page_md *mdpg, vm_prot_t prot,
471 1.1 skrll u_int flags, bool is_kernel_pmap_p)
472 1.1 skrll {
473 1.1 skrll KASSERTMSG((pa & ~L3_PAG_OA) == 0, "pa %" PRIxPADDR, pa);
474 1.1 skrll
475 1.1 skrll pt_entry_t npte = pa
476 1.1 skrll | LX_VALID
477 1.1 skrll #ifdef MULTIPROCESSOR
478 1.1 skrll | LX_BLKPAG_SH_IS
479 1.1 skrll #endif
480 1.1 skrll | L3_TYPE_PAG
481 1.1 skrll | LX_BLKPAG_UXN | LX_BLKPAG_PXN
482 1.1 skrll | (((prot) & (VM_PROT_READ | VM_PROT_WRITE)) == VM_PROT_READ ? LX_BLKPAG_AP_RO : LX_BLKPAG_AP_RW);
483 1.1 skrll
484 1.1 skrll if ((prot & VM_PROT_WRITE) != 0 &&
485 1.1 skrll ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) {
486 1.1 skrll /*
487 1.1 skrll * This is a writable mapping, and the page's mod state
488 1.1 skrll * indicates it has already been modified. No need for
489 1.1 skrll * modified emulation.
490 1.1 skrll */
491 1.1 skrll npte |= LX_BLKPAG_AF;
492 1.1 skrll } else if ((flags & VM_PROT_ALL) || VM_PAGEMD_REFERENCED_P(mdpg)) {
493 1.1 skrll /*
494 1.1 skrll * - The access type indicates that we don't need to do
495 1.1 skrll * referenced emulation.
496 1.1 skrll * OR
497 1.1 skrll * - The physical page has already been referenced so no need
498 1.1 skrll * to re-do referenced emulation here.
499 1.1 skrll */
500 1.1 skrll npte |= LX_BLKPAG_AF;
501 1.1 skrll }
502 1.1 skrll
503 1.1 skrll if (prot & VM_PROT_EXECUTE)
504 1.1 skrll npte &= (is_kernel_pmap_p ? ~LX_BLKPAG_PXN : ~LX_BLKPAG_UXN);
505 1.1 skrll
506 1.1 skrll npte &= ~LX_BLKPAG_ATTR_MASK;
507 1.1 skrll npte |= pte_memattr(flags);
508 1.1 skrll
509 1.1 skrll /*
510 1.1 skrll * Make sure userland mappings get the right permissions
511 1.1 skrll */
512 1.1 skrll if (!is_kernel_pmap_p) {
513 1.1 skrll npte |= LX_BLKPAG_NG | LX_BLKPAG_APUSER;
514 1.1 skrll }
515 1.1 skrll
516 1.1 skrll return npte;
517 1.1 skrll }
518 1.1 skrll #endif /* __PMAP_PRIVATE */
519 1.1 skrll
520 1.1 skrll #endif /* _AARCH64_PMAP_MACHDEP_H_ */
521 1.1 skrll
522