| 1 | /* $NetBSD: pmap.h,v 1.59 2023/08/02 15:57:21 skrll Exp $ */ |
| 2 | |
| 3 | /*- |
| 4 | * Copyright (c) 2014 The NetBSD Foundation, Inc. |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * This code is derived from software contributed to The NetBSD Foundation |
| 8 | * by Matt Thomas of 3am Software Foundry. |
| 9 | * |
| 10 | * Redistribution and use in source and binary forms, with or without |
| 11 | * modification, are permitted provided that the following conditions |
| 12 | * are met: |
| 13 | * 1. Redistributions of source code must retain the above copyright |
| 14 | * notice, this list of conditions and the following disclaimer. |
| 15 | * 2. Redistributions in binary form must reproduce the above copyright |
| 16 | * notice, this list of conditions and the following disclaimer in the |
| 17 | * documentation and/or other materials provided with the distribution. |
| 18 | * |
| 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
| 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
| 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 29 | * POSSIBILITY OF SUCH DAMAGE. |
| 30 | */ |
| 31 | |
| 32 | #ifndef _AARCH64_PMAP_H_ |
| 33 | #define _AARCH64_PMAP_H_ |
| 34 | |
| 35 | #ifdef __aarch64__ |
| 36 | |
| 37 | #ifdef _KERNEL |
| 38 | #ifdef _KERNEL_OPT |
| 39 | #include "opt_kasan.h" |
| 40 | #include "opt_pmap.h" |
| 41 | #endif |
| 42 | |
| 43 | #include <sys/types.h> |
| 44 | #include <sys/pool.h> |
| 45 | #include <sys/queue.h> |
| 46 | |
| 47 | #include <uvm/uvm_pglist.h> |
| 48 | |
| 49 | #include <aarch64/armreg.h> |
| 50 | #include <aarch64/pte.h> |
| 51 | |
| 52 | #define	PMAP_TLB_MAX			1 |
| 53 | #if PMAP_TLB_MAX > 1 |
| 54 | #define	PMAP_TLB_NEED_SHOOTDOWN		1 |
| 55 | #endif |
| 56 | |
| 57 | #define	PMAP_TLB_FLUSH_ASID_ON_RESET	true |
| 58 | |
| 59 | /* Maximum number of ASIDs. Some CPUs have less.*/ |
| 60 | #define	PMAP_TLB_NUM_PIDS		65536 |
| 61 | #define	PMAP_TLB_BITMAP_LENGTH		PMAP_TLB_NUM_PIDS |
| 62 | |
| 63 | static inline tlb_asid_t |
| 64 | pmap_md_tlb_asid_max(void) |
| 65 | { |
| 66 | 	switch (__SHIFTOUT(reg_id_aa64mmfr0_el1_read(), ID_AA64MMFR0_EL1_ASIDBITS)) { |
| 67 | 	case ID_AA64MMFR0_EL1_ASIDBITS_8BIT: |
| 68 | 		return (1U << 8) - 1; |
| 69 | 	case ID_AA64MMFR0_EL1_ASIDBITS_16BIT: |
| 70 | 		return (1U << 16) - 1; |
| 71 | 	default: |
| 72 | 		return 0; |
| 73 | 	} |
| 74 | } |
| 75 | |
| 76 | #include <uvm/pmap/tlb.h> |
| 77 | #include <uvm/pmap/pmap_devmap.h> |
| 78 | #include <uvm/pmap/pmap_tlb.h> |
| 79 | |
| 80 | #define KERNEL_PID		0	/* The kernel uses ASID 0 */ |
| 81 | |
| 82 | |
| 83 | /* memory attributes are configured MAIR_EL1 in locore */ |
| 84 | #define LX_BLKPAG_ATTR_NORMAL_WB	__SHIFTIN(0, LX_BLKPAG_ATTR_INDX) |
| 85 | #define LX_BLKPAG_ATTR_NORMAL_NC	__SHIFTIN(1, LX_BLKPAG_ATTR_INDX) |
| 86 | #define LX_BLKPAG_ATTR_NORMAL_WT	__SHIFTIN(2, LX_BLKPAG_ATTR_INDX) |
| 87 | #define LX_BLKPAG_ATTR_DEVICE_MEM	__SHIFTIN(3, LX_BLKPAG_ATTR_INDX) |
| 88 | #define LX_BLKPAG_ATTR_DEVICE_MEM_NP	__SHIFTIN(4, LX_BLKPAG_ATTR_INDX) |
| 89 | #define LX_BLKPAG_ATTR_MASK		LX_BLKPAG_ATTR_INDX |
| 90 | |
| 91 | #define lxpde_pa(pde)		((paddr_t)((pde) & LX_TBL_PA)) |
| 92 | #define lxpde_valid(pde)	(((pde) & LX_VALID) == LX_VALID) |
| 93 | #define l0pde_pa(pde)		lxpde_pa(pde) |
| 94 | #define l0pde_index(v)		(((vaddr_t)(v) & L0_ADDR_BITS) >> L0_SHIFT) |
| 95 | #define l0pde_valid(pde)	lxpde_valid(pde) |
| 96 | /* l0pte always contains table entries */ |
| 97 | |
| 98 | #define l1pde_pa(pde)		lxpde_pa(pde) |
| 99 | #define l1pde_index(v)		(((vaddr_t)(v) & L1_ADDR_BITS) >> L1_SHIFT) |
| 100 | #define l1pde_valid(pde)	lxpde_valid(pde) |
| 101 | #define l1pde_is_block(pde)	(((pde) & LX_TYPE) == LX_TYPE_BLK) |
| 102 | #define l1pde_is_table(pde)	(((pde) & LX_TYPE) == LX_TYPE_TBL) |
| 103 | |
| 104 | #define l2pde_pa(pde)		lxpde_pa(pde) |
| 105 | #define l2pde_index(v)		(((vaddr_t)(v) & L2_ADDR_BITS) >> L2_SHIFT) |
| 106 | #define l2pde_valid(pde)	lxpde_valid(pde) |
| 107 | #define l2pde_is_block(pde)	(((pde) & LX_TYPE) == LX_TYPE_BLK) |
| 108 | #define l2pde_is_table(pde)	(((pde) & LX_TYPE) == LX_TYPE_TBL) |
| 109 | |
| 110 | #define l3pte_pa(pde)		lxpde_pa(pde) |
| 111 | #define l3pte_executable(pde,user)	\ |
| 112 | (((pde) & ((user) ? LX_BLKPAG_UXN : LX_BLKPAG_PXN)) == 0) |
| 113 | #define l3pte_readable(pde)	((pde) & LX_BLKPAG_AF) |
| 114 | #define l3pte_writable(pde)	\ |
| 115 | (((pde) & (LX_BLKPAG_AF | LX_BLKPAG_AP)) == (LX_BLKPAG_AF | LX_BLKPAG_AP_RW)) |
| 116 | #define l3pte_index(v)		(((vaddr_t)(v) & L3_ADDR_BITS) >> L3_SHIFT) |
| 117 | #define l3pte_valid(pde)	lxpde_valid(pde) |
| 118 | #define l3pte_is_page(pde)	(((pde) & LX_TYPE) == L3_TYPE_PAG) |
| 119 | |
| 120 | pd_entry_t *pmap_l0table(struct pmap *); |
| 121 | void pmap_bootstrap(vaddr_t, vaddr_t); |
| 122 | bool pmap_fault_fixup(struct pmap *, vaddr_t, vm_prot_t, bool user); |
| 123 | |
| 124 | bool	pmap_extract_coherency(pmap_t, vaddr_t, paddr_t *, bool *); |
| 125 | |
| 126 | |
| 127 | /* change attribute of kernel segment */ |
| 128 | static inline pt_entry_t |
| 129 | pmap_kvattr(pt_entry_t *ptep, vm_prot_t prot) |
| 130 | { |
| 131 | 	pt_entry_t pte = *ptep; |
| 132 | 	const pt_entry_t opte = pte; |
| 133 | |
| 134 | 	pte &= ~(LX_BLKPAG_AF | LX_BLKPAG_AP); |
| 135 | 	switch (prot & (VM_PROT_READ | VM_PROT_WRITE)) { |
| 136 | 	case 0: |
| 137 | 		break; |
| 138 | 	case VM_PROT_READ: |
| 139 | 		pte |= LX_BLKPAG_AF | LX_BLKPAG_AP_RO; |
| 140 | 		break; |
| 141 | 	case VM_PROT_WRITE: |
| 142 | 	case VM_PROT_READ | VM_PROT_WRITE: |
| 143 | 		pte |= LX_BLKPAG_AF | LX_BLKPAG_AP_RW; |
| 144 | 		break; |
| 145 | 	} |
| 146 | |
| 147 | 	if ((prot & VM_PROT_EXECUTE) == 0) { |
| 148 | 		pte |= LX_BLKPAG_PXN; |
| 149 | 	} else { |
| 150 | 		pte |= LX_BLKPAG_AF; |
| 151 | 		pte &= ~LX_BLKPAG_PXN; |
| 152 | 	} |
| 153 | |
| 154 | 	*ptep = pte; |
| 155 | |
| 156 | 	return opte; |
| 157 | } |
| 158 | |
| 159 | #define L1_TRUNC_BLOCK(x)	((x) & L1_FRAME) |
| 160 | #define L1_ROUND_BLOCK(x)	L1_TRUNC_BLOCK((x) + L1_SIZE - 1) |
| 161 | #define L2_TRUNC_BLOCK(x)	((x) & L2_FRAME) |
| 162 | #define L2_ROUND_BLOCK(x)	L2_TRUNC_BLOCK((x) + L2_SIZE - 1) |
| 163 | #define L3_TRUNC_BLOCK(x)	((x) & L3_FRAME) |
| 164 | #define L3_ROUND_BLOCK(x)	L3_TRUNC_BLOCK((x) + L3_SIZE - 1) |
| 165 | |
| 166 | #define DEVMAP_ALIGN(x)		L3_TRUNC_BLOCK((x)) |
| 167 | #define DEVMAP_SIZE(x)		L3_ROUND_BLOCK((x)) |
| 168 | #define DEVMAP_FLAGS		PMAP_DEV |
| 169 | |
| 170 | /* Hooks for the pool allocator */ |
| 171 | paddr_t vtophys(vaddr_t); |
| 172 | |
| 173 | /* mmap cookie and flags */ |
| 174 | #define AARCH64_MMAP_FLAG_SHIFT		(64 - PGSHIFT) |
| 175 | #define AARCH64_MMAP_FLAG_MASK		0xf |
| 176 | #define AARCH64_MMAP_WRITEBACK		0UL |
| 177 | #define AARCH64_MMAP_NOCACHE		1UL |
| 178 | #define AARCH64_MMAP_WRITECOMBINE	2UL |
| 179 | #define AARCH64_MMAP_DEVICE		3UL |
| 180 | |
| 181 | #define ARM_MMAP_MASK			__BITS(63, AARCH64_MMAP_FLAG_SHIFT) |
| 182 | #define ARM_MMAP_WRITECOMBINE		__SHIFTIN(AARCH64_MMAP_WRITECOMBINE, ARM_MMAP_MASK) |
| 183 | #define ARM_MMAP_WRITEBACK		__SHIFTIN(AARCH64_MMAP_WRITEBACK, ARM_MMAP_MASK) |
| 184 | #define ARM_MMAP_NOCACHE		__SHIFTIN(AARCH64_MMAP_NOCACHE, ARM_MMAP_MASK) |
| 185 | #define ARM_MMAP_DEVICE			__SHIFTIN(AARCH64_MMAP_DEVICE, ARM_MMAP_MASK) |
| 186 | |
| 187 | #define	PMAP_PTE			0x10000000 /* kenter_pa */ |
| 188 | #define	PMAP_DEV			0x20000000 /* kenter_pa */ |
| 189 | #define	PMAP_DEV_NP			0x40000000 /* kenter_pa */ |
| 190 | #define	PMAP_DEV_MASK			(PMAP_DEV | PMAP_DEV_NP) |
| 191 | |
| 192 | static inline u_int |
| 193 | aarch64_mmap_flags(paddr_t mdpgno) |
| 194 | { |
| 195 | 	u_int nflag, pflag; |
| 196 | |
| 197 | 	/* |
| 198 | 	 * aarch64 arch has 5 memory attributes defined: |
| 199 | 	 * |
| 200 | 	 * WriteBack - write back cache |
| 201 | 	 * WriteThru - write through cache |
| 202 | 	 * NoCache - no cache |
| 203 | 	 * Device(nGnRE) - no Gathering, no Reordering, Early write ack |
| 204 | 	 * Device(nGnRnE) - no Gathering, no Reordering, no Early write ack |
| 205 | 	 * |
| 206 | 	 * but pmap has PMAP_{NOCACHE,WRITE_COMBINE,WRITE_BACK} flags. |
| 207 | 	 */ |
| 208 | |
| 209 | 	nflag = (mdpgno >> AARCH64_MMAP_FLAG_SHIFT) & AARCH64_MMAP_FLAG_MASK; |
| 210 | 	switch (nflag) { |
| 211 | 	case AARCH64_MMAP_DEVICE: |
| 212 | 		pflag = PMAP_DEV; |
| 213 | 		break; |
| 214 | 	case AARCH64_MMAP_WRITECOMBINE: |
| 215 | 		pflag = PMAP_WRITE_COMBINE; |
| 216 | 		break; |
| 217 | 	case AARCH64_MMAP_WRITEBACK: |
| 218 | 		pflag = PMAP_WRITE_BACK; |
| 219 | 		break; |
| 220 | 	case AARCH64_MMAP_NOCACHE: |
| 221 | 	default: |
| 222 | 		pflag = PMAP_NOCACHE; |
| 223 | 		break; |
| 224 | 	} |
| 225 | 	return pflag; |
| 226 | } |
| 227 | |
| 228 | #define pmap_phys_address(pa)		aarch64_ptob((pa)) |
| 229 | #define pmap_mmap_flags(ppn)		aarch64_mmap_flags((ppn)) |
| 230 | |
| 231 | void pmap_bootstrap(vaddr_t, vaddr_t); |
| 232 | bool pmap_fault_fixup(struct pmap *, vaddr_t, vm_prot_t, bool user); |
| 233 | |
| 234 | pd_entry_t *pmapboot_pagealloc(void); |
| 235 | void pmapboot_enter(vaddr_t, paddr_t, psize_t, psize_t, pt_entry_t, |
| 236 | void (*pr)(const char *, ...) __printflike(1, 2)); |
| 237 | void pmapboot_enter_range(vaddr_t, paddr_t, psize_t, pt_entry_t, |
| 238 | void (*)(const char *, ...) __printflike(1, 2)); |
| 239 | int pmapboot_protect(vaddr_t, vaddr_t, vm_prot_t); |
| 240 | |
| 241 | vsize_t pmap_map_chunk(vaddr_t, vaddr_t, paddr_t, vsize_t, vm_prot_t, u_int); |
| 242 | |
| 243 | #if defined(DDB) |
| 244 | void pmap_db_pte_print(pt_entry_t, int, void (*)(const char *, ...) __printflike(1, 2)); |
| 245 | void pmap_db_pteinfo(vaddr_t, void (*)(const char *, ...) __printflike(1, 2)); |
| 246 | void pmap_db_ttbrdump(bool, vaddr_t, void (*)(const char *, ...) __printflike(1, 2)); |
| 247 | #endif |
| 248 | |
| 249 | #define LX_BLKPAG_OS_WIRED		LX_BLKPAG_OS_2 |
| 250 | #define LX_BLKPAG_OS_BOOT		LX_BLKPAG_OS_3 |
| 251 | |
| 252 | #define PMAP_PTE_OS2	"wired" |
| 253 | #define PMAP_PTE_OS3	"boot" |
| 254 | |
| 255 | #if defined(PMAP_MI) |
| 256 | #include <aarch64/pmap_machdep.h> |
| 257 | #else |
| 258 | |
| 259 | #define PMAP_NEED_PROCWR |
| 260 | #define PMAP_GROWKERNEL |
| 261 | #define PMAP_STEAL_MEMORY |
| 262 | |
| 263 | #define __HAVE_VM_PAGE_MD |
| 264 | #define __HAVE_PMAP_PV_TRACK	1 |
| 265 | |
| 266 | struct pmap { |
| 267 | 	kmutex_t pm_lock; |
| 268 | 	struct pool *pm_pvpool; |
| 269 | 	pd_entry_t *pm_l0table;			/* L0 table: 512G*512 */ |
| 270 | 	paddr_t pm_l0table_pa; |
| 271 | |
| 272 | 	LIST_HEAD(, vm_page) pm_vmlist;		/* for L[0123] tables */ |
| 273 | 	LIST_HEAD(, pv_entry) pm_pvlist;	/* all pv of this process */ |
| 274 | |
| 275 | 	struct pmap_statistics pm_stats; |
| 276 | 	unsigned int pm_refcnt; |
| 277 | 	unsigned int pm_idlepdp; |
| 278 | |
| 279 | 	kcpuset_t *pm_onproc; |
| 280 | 	kcpuset_t *pm_active; |
| 281 | |
| 282 | 	struct pmap_asid_info pm_pai[PMAP_TLB_MAX]; |
| 283 | 	bool pm_activated; |
| 284 | }; |
| 285 | |
| 286 | static inline paddr_t |
| 287 | pmap_l0pa(struct pmap *pm) |
| 288 | { |
| 289 | 	return pm->pm_l0table_pa; |
| 290 | } |
| 291 | |
| 292 | |
| 293 | /* |
| 294 | * should be kept <=32 bytes sized to reduce memory consumption & cache misses, |
| 295 | * but it doesn't... |
| 296 | */ |
| 297 | struct pv_entry { |
| 298 | 	struct pv_entry *pv_next; |
| 299 | 	struct pmap *pv_pmap; |
| 300 | 	vaddr_t pv_va;	/* for embedded entry (pp_pv) also includes flags */ |
| 301 | 	void *pv_ptep;	/* pointer for fast pte lookup */ |
| 302 | 	LIST_ENTRY(pv_entry) pv_proc;	/* belonging to the process */ |
| 303 | }; |
| 304 | |
| 305 | struct pmap_page { |
| 306 | 	kmutex_t pp_pvlock; |
| 307 | 	struct pv_entry pp_pv; |
| 308 | }; |
| 309 | |
| 310 | /* try to keep vm_page at or under 128 bytes to reduce cache misses */ |
| 311 | struct vm_page_md { |
| 312 | 	struct pmap_page mdpg_pp; |
| 313 | }; |
| 314 | /* for page descriptor page only */ |
| 315 | #define	mdpg_ptep_parent	mdpg_pp.pp_pv.pv_ptep |
| 316 | |
| 317 | #define VM_MDPAGE_INIT(pg)					\ |
| 318 | 	do {							\ |
| 319 | 		PMAP_PAGE_INIT(&(pg)->mdpage.mdpg_pp);		\ |
| 320 | 	} while (/*CONSTCOND*/ 0) |
| 321 | |
| 322 | #define PMAP_PAGE_INIT(pp)						\ |
| 323 | 	do {								\ |
| 324 | 		mutex_init(&(pp)->pp_pvlock, MUTEX_NODEBUG, IPL_NONE);	\ |
| 325 | 		(pp)->pp_pv.pv_next = NULL;				\ |
| 326 | 		(pp)->pp_pv.pv_pmap = NULL;				\ |
| 327 | 		(pp)->pp_pv.pv_va = 0;					\ |
| 328 | 		(pp)->pp_pv.pv_ptep = NULL;				\ |
| 329 | 	} while (/*CONSTCOND*/ 0) |
| 330 | |
| 331 | /* saved permission bit for referenced/modified emulation */ |
| 332 | #define LX_BLKPAG_OS_READ		LX_BLKPAG_OS_0 |
| 333 | #define LX_BLKPAG_OS_WRITE		LX_BLKPAG_OS_1 |
| 334 | #define LX_BLKPAG_OS_RWMASK		(LX_BLKPAG_OS_WRITE | LX_BLKPAG_OS_READ) |
| 335 | |
| 336 | #define PMAP_PTE_OS0	"read" |
| 337 | #define PMAP_PTE_OS1	"write" |
| 338 | |
| 339 | #define VTOPHYS_FAILED			((paddr_t)-1L)	/* POOL_PADDR_INVALID */ |
| 340 | #define POOL_VTOPHYS(va)		vtophys((vaddr_t) (va)) |
| 341 | |
| 342 | #ifndef KASAN |
| 343 | #define PMAP_MAP_POOLPAGE(pa)		AARCH64_PA_TO_KVA(pa) |
| 344 | #define PMAP_UNMAP_POOLPAGE(va)		AARCH64_KVA_TO_PA(va) |
| 345 | |
| 346 | #define PMAP_DIRECT |
| 347 | static __inline int |
| 348 | pmap_direct_process(paddr_t pa, voff_t pgoff, size_t len, |
| 349 | int (*process)(void *, size_t, void *), void *arg) |
| 350 | { |
| 351 | 	vaddr_t va = AARCH64_PA_TO_KVA(pa); |
| 352 | |
| 353 | 	return process((void *)(va + pgoff), len, arg); |
| 354 | } |
| 355 | #endif |
| 356 | |
| 357 | /* l3pte contains always page entries */ |
| 358 | static inline uint64_t |
| 359 | pte_value(pt_entry_t pte) |
| 360 | { |
| 361 | 	return pte; |
| 362 | } |
| 363 | |
| 364 | static inline bool |
| 365 | pte_valid_p(pt_entry_t pte) |
| 366 | { |
| 367 | 	return l3pte_valid(pte); |
| 368 | } |
| 369 | |
| 370 | pt_entry_t *kvtopte(vaddr_t); |
| 371 | |
| 372 | #define pmap_update(pmap)		((void)0) |
| 373 | #define pmap_copy(dp,sp,d,l,s)		((void)0) |
| 374 | #define pmap_wired_count(pmap)		((pmap)->pm_stats.wired_count) |
| 375 | #define pmap_resident_count(pmap)	((pmap)->pm_stats.resident_count) |
| 376 | |
| 377 | struct pmap * |
| 378 | 	pmap_efirt(void); |
| 379 | void	pmap_activate_efirt(void); |
| 380 | void	pmap_deactivate_efirt(void); |
| 381 | |
| 382 | void	pmap_procwr(struct proc *, vaddr_t, int); |
| 383 | void	pmap_icache_sync_range(pmap_t, vaddr_t, vaddr_t); |
| 384 | |
| 385 | void	pmap_pv_init(void); |
| 386 | void	pmap_pv_track(paddr_t, psize_t); |
| 387 | void	pmap_pv_untrack(paddr_t, psize_t); |
| 388 | void	pmap_pv_protect(paddr_t, vm_prot_t); |
| 389 | |
| 390 | vsize_t	pmap_kenter_range(vaddr_t, paddr_t, vsize_t, vm_prot_t, u_int); |
| 391 | |
| 392 | #define	PMAP_MAPSIZE1	L2_SIZE |
| 393 | |
| 394 | /* for ddb */ |
| 395 | void pmap_db_pmap_print(struct pmap *, void (*)(const char *, ...) __printflike(1, 2)); |
| 396 | void pmap_db_mdpg_print(struct vm_page *, void (*)(const char *, ...) __printflike(1, 2)); |
| 397 | |
| 398 | #endif	/* !PMAP_MI */ |
| 399 | |
| 400 | #endif /* _KERNEL */ |
| 401 | |
| 402 | #elif defined(__arm__) |
| 403 | |
| 404 | #include <arm/pmap.h> |
| 405 | |
| 406 | #endif /* __arm__/__aarch64__ */ |
| 407 | |
| 408 | #endif /* !_AARCH64_PMAP_ */ |