| 1 | /*	$NetBSD: pmap.h,v 1.177 2023/10/12 11:33:37 skrll Exp $	*/ |
| 2 | |
| 3 | /* |
| 4 | * Copyright (c) 2002, 2003 Wasabi Systems, Inc. |
| 5 | * All rights reserved. |
| 6 | * |
| 7 | * Written by Jason R. Thorpe & Steve C. Woodford for Wasabi Systems, Inc. |
| 8 | * |
| 9 | * Redistribution and use in source and binary forms, with or without |
| 10 | * modification, are permitted provided that the following conditions |
| 11 | * are met: |
| 12 | * 1. Redistributions of source code must retain the above copyright |
| 13 | * notice, this list of conditions and the following disclaimer. |
| 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| 15 | * notice, this list of conditions and the following disclaimer in the |
| 16 | * documentation and/or other materials provided with the distribution. |
| 17 | * 3. All advertising materials mentioning features or use of this software |
| 18 | * must display the following acknowledgement: |
| 19 | *	This product includes software developed for the NetBSD Project by |
| 20 | *	Wasabi Systems, Inc. |
| 21 | * 4. The name of Wasabi Systems, Inc. may not be used to endorse |
| 22 | * or promote products derived from this software without specific prior |
| 23 | * written permission. |
| 24 | * |
| 25 | * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND |
| 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| 27 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 28 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC |
| 29 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 35 | * POSSIBILITY OF SUCH DAMAGE. |
| 36 | */ |
| 37 | |
| 38 | /* |
| 39 | * Copyright (c) 1994,1995 Mark Brinicombe. |
| 40 | * All rights reserved. |
| 41 | * |
| 42 | * Redistribution and use in source and binary forms, with or without |
| 43 | * modification, are permitted provided that the following conditions |
| 44 | * are met: |
| 45 | * 1. Redistributions of source code must retain the above copyright |
| 46 | * notice, this list of conditions and the following disclaimer. |
| 47 | * 2. Redistributions in binary form must reproduce the above copyright |
| 48 | * notice, this list of conditions and the following disclaimer in the |
| 49 | * documentation and/or other materials provided with the distribution. |
| 50 | * 3. All advertising materials mentioning features or use of this software |
| 51 | * must display the following acknowledgement: |
| 52 | *	This product includes software developed by Mark Brinicombe |
| 53 | * 4. The name of the author may not be used to endorse or promote products |
| 54 | * derived from this software without specific prior written permission. |
| 55 | * |
| 56 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 57 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 58 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 59 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 60 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 61 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 62 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 63 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 64 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 65 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 66 | */ |
| 67 | |
| 68 | #ifndef	_ARM32_PMAP_H_ |
| 69 | #define	_ARM32_PMAP_H_ |
| 70 | |
| 71 | #ifdef _KERNEL |
| 72 | |
| 73 | #include <arm/cpuconf.h> |
| 74 | #include <arm/arm32/pte.h> |
| 75 | #ifndef _LOCORE |
| 76 | #if defined(_KERNEL_OPT) |
| 77 | #include "opt_arm32_pmap.h" |
| 78 | #include "opt_multiprocessor.h" |
| 79 | #endif |
| 80 | #include <arm/cpufunc.h> |
| 81 | #include <arm/locore.h> |
| 82 | |
| 83 | #include <uvm/uvm_object.h> |
| 84 | |
| 85 | #include <uvm/pmap/pmap_devmap.h> |
| 86 | #include <uvm/pmap/pmap_pvt.h> |
| 87 | #endif |
| 88 | |
| 89 | #ifdef ARM_MMU_EXTENDED |
| 90 | #define	PMAP_HWPAGEWALKER		1 |
| 91 | #define	PMAP_TLB_MAX			1 |
| 92 | #if PMAP_TLB_MAX > 1 |
| 93 | #define	PMAP_TLB_NEED_SHOOTDOWN		1 |
| 94 | #endif |
| 95 | #define	PMAP_TLB_FLUSH_ASID_ON_RESET	arm_has_tlbiasid_p |
| 96 | #define	PMAP_TLB_NUM_PIDS		256 |
| 97 | |
| 98 | #define	pmap_md_tlb_asid_max()		(PMAP_TLB_NUM_PIDS - 1) |
| 99 | #include <uvm/pmap/tlb.h> |
| 100 | #include <uvm/pmap/pmap_tlb.h> |
| 101 | |
| 102 | /* |
| 103 | * If we have an EXTENDED MMU and the address space is split evenly between |
| 104 | * user and kernel, we can use the TTBR0/TTBR1 to have separate L1 tables for |
| 105 | * user and kernel address spaces. |
| 106 | */ |
| 107 | #if (KERNEL_BASE & 0x80000000) == 0 |
| 108 | #error ARMv6 or later systems must have a KERNEL_BASE >= 0x80000000 |
| 109 | #endif |
| 110 | #endif /* ARM_MMU_EXTENDED */ |
| 111 | |
| 112 | /* |
| 113 | * a pmap describes a processes' 4GB virtual address space. this |
| 114 | * virtual address space can be broken up into 4096 1MB regions which |
| 115 | * are described by L1 PTEs in the L1 table. |
| 116 | * |
| 117 | * There is a line drawn at KERNEL_BASE. Everything below that line |
| 118 | * changes when the VM context is switched. Everything above that line |
| 119 | * is the same no matter which VM context is running. This is achieved |
| 120 | * by making the L1 PTEs for those slots above KERNEL_BASE reference |
| 121 | * kernel L2 tables. |
| 122 | * |
| 123 | * The basic layout of the virtual address space thus looks like this: |
| 124 | * |
| 125 | *	0xffffffff |
| 126 | *	. |
| 127 | *	. |
| 128 | *	. |
| 129 | *	KERNEL_BASE |
| 130 | *	-------------------- |
| 131 | *	. |
| 132 | *	. |
| 133 | *	. |
| 134 | *	0x00000000 |
| 135 | */ |
| 136 | |
| 137 | /* |
| 138 | * The number of L2 descriptor tables which can be tracked by an l2_dtable. |
| 139 | * A bucket size of 16 provides for 16MB of contiguous virtual address |
| 140 | * space per l2_dtable. Most processes will, therefore, require only two or |
| 141 | * three of these to map their whole working set. |
| 142 | */ |
| 143 | #define	L2_BUCKET_XLOG2	(L1_S_SHIFT) |
| 144 | #define	L2_BUCKET_XSIZE	(1 << L2_BUCKET_XLOG2) |
| 145 | #define	L2_BUCKET_LOG2	4 |
| 146 | #define	L2_BUCKET_SIZE	(1 << L2_BUCKET_LOG2) |
| 147 | |
| 148 | /* |
| 149 | * Given the above "L2-descriptors-per-l2_dtable" constant, the number |
| 150 | * of l2_dtable structures required to track all possible page descriptors |
| 151 | * mappable by an L1 translation table is given by the following constants: |
| 152 | */ |
| 153 | #define	L2_LOG2		(32 - (L2_BUCKET_XLOG2 + L2_BUCKET_LOG2)) |
| 154 | #define	L2_SIZE		(1 << L2_LOG2) |
| 155 | |
| 156 | /* |
| 157 | * tell MI code that the cache is virtually-indexed. |
| 158 | * ARMv6 is physically-tagged but all others are virtually-tagged. |
| 159 | */ |
| 160 | #if (ARM_MMU_V6 + ARM_MMU_V7) > 0 |
| 161 | #define	PMAP_CACHE_VIPT |
| 162 | #else |
| 163 | #define	PMAP_CACHE_VIVT |
| 164 | #endif |
| 165 | |
| 166 | #ifndef _LOCORE |
| 167 | |
| 168 | #ifndef ARM_MMU_EXTENDED |
| 169 | struct l1_ttable; |
| 170 | struct l2_dtable; |
| 171 | |
| 172 | /* |
| 173 | * Track cache/tlb occupancy using the following structure |
| 174 | */ |
| 175 | union pmap_cache_state { |
| 176 | 	struct { |
| 177 | 		union { |
| 178 | 			uint8_t csu_cache_b[2]; |
| 179 | 			uint16_t csu_cache; |
| 180 | 		} cs_cache_u; |
| 181 | |
| 182 | 		union { |
| 183 | 			uint8_t csu_tlb_b[2]; |
| 184 | 			uint16_t csu_tlb; |
| 185 | 		} cs_tlb_u; |
| 186 | 	} cs_s; |
| 187 | 	uint32_t cs_all; |
| 188 | }; |
| 189 | #define	cs_cache_id	cs_s.cs_cache_u.csu_cache_b[0] |
| 190 | #define	cs_cache_d	cs_s.cs_cache_u.csu_cache_b[1] |
| 191 | #define	cs_cache	cs_s.cs_cache_u.csu_cache |
| 192 | #define	cs_tlb_id	cs_s.cs_tlb_u.csu_tlb_b[0] |
| 193 | #define	cs_tlb_d	cs_s.cs_tlb_u.csu_tlb_b[1] |
| 194 | #define	cs_tlb		cs_s.cs_tlb_u.csu_tlb |
| 195 | |
| 196 | /* |
| 197 | * Assigned to cs_all to force cacheops to work for a particular pmap |
| 198 | */ |
| 199 | #define	PMAP_CACHE_STATE_ALL	0xffffffffu |
| 200 | #endif /* !ARM_MMU_EXTENDED */ |
| 201 | |
| 202 | |
| 203 | #define	DEVMAP_ALIGN(a)	((a) & ~L1_S_OFFSET) |
| 204 | #define	DEVMAP_SIZE(s)	roundup2((s), L1_S_SIZE) |
| 205 | #define	DEVMAP_FLAGS	PMAP_DEV |
| 206 | |
| 207 | /* |
| 208 | * The pmap structure itself |
| 209 | */ |
| 210 | struct pmap { |
| 211 | 	kmutex_t		pm_lock; |
| 212 | 	u_int			pm_refs; |
| 213 | #ifndef ARM_HAS_VBAR |
| 214 | 	pd_entry_t		*pm_pl1vec; |
| 215 | 	pd_entry_t		pm_l1vec; |
| 216 | #endif |
| 217 | 	struct l2_dtable	*pm_l2[L2_SIZE]; |
| 218 | 	struct pmap_statistics	pm_stats; |
| 219 | 	LIST_ENTRY(pmap)	pm_list; |
| 220 | 	bool			pm_remove_all; |
| 221 | #ifdef ARM_MMU_EXTENDED |
| 222 | 	pd_entry_t		*pm_l1; |
| 223 | 	paddr_t			pm_l1_pa; |
| 224 | #ifdef MULTIPROCESSOR |
| 225 | 	kcpuset_t		*pm_onproc; |
| 226 | 	kcpuset_t		*pm_active; |
| 227 | #if PMAP_TLB_MAX > 1 |
| 228 | 	u_int			pm_shootdown_pending; |
| 229 | #endif |
| 230 | #endif |
| 231 | 	struct pmap_asid_info	pm_pai[PMAP_TLB_MAX]; |
| 232 | #else |
| 233 | 	struct l1_ttable	*pm_l1; |
| 234 | 	union pmap_cache_state	pm_cstate; |
| 235 | 	uint8_t			pm_domain; |
| 236 | 	bool			pm_activated; |
| 237 | #endif |
| 238 | }; |
| 239 | |
| 240 | struct pmap_kernel { |
| 241 | 	struct pmap		kernel_pmap; |
| 242 | }; |
| 243 | |
| 244 | /* |
| 245 | * Physical / virtual address structure. In a number of places (particularly |
| 246 | * during bootstrapping) we need to keep track of the physical and virtual |
| 247 | * addresses of various pages |
| 248 | */ |
| 249 | typedef struct pv_addr { |
| 250 | 	SLIST_ENTRY(pv_addr) pv_list; |
| 251 | 	paddr_t pv_pa; |
| 252 | 	vaddr_t pv_va; |
| 253 | 	vsize_t pv_size; |
| 254 | 	uint8_t pv_cache; |
| 255 | 	uint8_t pv_prot; |
| 256 | } pv_addr_t; |
| 257 | typedef SLIST_HEAD(, pv_addr) pv_addrqh_t; |
| 258 | |
| 259 | extern pv_addrqh_t pmap_freeq; |
| 260 | extern pv_addr_t kernelstack; |
| 261 | extern pv_addr_t abtstack; |
| 262 | extern pv_addr_t fiqstack; |
| 263 | extern pv_addr_t irqstack; |
| 264 | extern pv_addr_t undstack; |
| 265 | extern pv_addr_t idlestack; |
| 266 | extern pv_addr_t systempage; |
| 267 | extern pv_addr_t kernel_l1pt; |
| 268 | #if defined(EFI_RUNTIME) |
| 269 | extern pv_addr_t efirt_l1pt; |
| 270 | #endif |
| 271 | |
| 272 | #ifdef ARM_MMU_EXTENDED |
| 273 | extern bool arm_has_tlbiasid_p;	/* also in <arm/locore.h> */ |
| 274 | #endif |
| 275 | |
| 276 | /* |
| 277 | * Determine various modes for PTEs (user vs. kernel, cacheable |
| 278 | * vs. non-cacheable). |
| 279 | */ |
| 280 | #define	PTE_KERNEL	0 |
| 281 | #define	PTE_USER	1 |
| 282 | #define	PTE_NOCACHE	0 |
| 283 | #define	PTE_CACHE	1 |
| 284 | #define	PTE_PAGETABLE	2 |
| 285 | #define	PTE_DEV		3 |
| 286 | |
| 287 | /* |
| 288 | * Flags that indicate attributes of pages or mappings of pages. |
| 289 | * |
| 290 | * The PVF_MOD and PVF_REF flags are stored in the mdpage for each |
| 291 | * page. PVF_WIRED, PVF_WRITE, and PVF_NC are kept in individual |
| 292 | * pv_entry's for each page. They live in the same "namespace" so |
| 293 | * that we can clear multiple attributes at a time. |
| 294 | * |
| 295 | * Note the "non-cacheable" flag generally means the page has |
| 296 | * multiple mappings in a given address space. |
| 297 | */ |
| 298 | #define	PVF_MOD		0x01		/* page is modified */ |
| 299 | #define	PVF_REF		0x02		/* page is referenced */ |
| 300 | #define	PVF_WIRED	0x04		/* mapping is wired */ |
| 301 | #define	PVF_WRITE	0x08		/* mapping is writable */ |
| 302 | #define	PVF_EXEC	0x10		/* mapping is executable */ |
| 303 | #ifdef PMAP_CACHE_VIVT |
| 304 | #define	PVF_UNC		0x20		/* mapping is 'user' non-cacheable */ |
| 305 | #define	PVF_KNC		0x40		/* mapping is 'kernel' non-cacheable */ |
| 306 | #define	PVF_NC		(PVF_UNC|PVF_KNC) |
| 307 | #endif |
| 308 | #ifdef PMAP_CACHE_VIPT |
| 309 | #define	PVF_NC		0x20		/* mapping is 'kernel' non-cacheable */ |
| 310 | #define	PVF_MULTCLR	0x40		/* mapping is multi-colored */ |
| 311 | #endif |
| 312 | #define	PVF_COLORED	0x80		/* page has or had a color */ |
| 313 | #define	PVF_KENTRY	0x0100		/* page entered via pmap_kenter_pa */ |
| 314 | #define	PVF_KMPAGE	0x0200		/* page is used for kmem */ |
| 315 | #define	PVF_DIRTY	0x0400		/* page may have dirty cache lines */ |
| 316 | #define	PVF_KMOD	0x0800		/* unmanaged page is modified */ |
| 317 | #define	PVF_KWRITE	(PVF_KENTRY|PVF_WRITE) |
| 318 | #define	PVF_DMOD	(PVF_MOD|PVF_KMOD|PVF_KMPAGE) |
| 319 | |
| 320 | /* |
| 321 | * Commonly referenced structures |
| 322 | */ |
| 323 | extern int		arm_poolpage_vmfreelist; |
| 324 | |
| 325 | /* |
| 326 | * Macros that we need to export |
| 327 | */ |
| 328 | #define	pmap_resident_count(pmap)	((pmap)->pm_stats.resident_count) |
| 329 | #define	pmap_wired_count(pmap)		((pmap)->pm_stats.wired_count) |
| 330 | |
| 331 | #define	pmap_is_modified(pg)	\ |
| 332 | 	(((pg)->mdpage.pvh_attrs & PVF_MOD) != 0) |
| 333 | #define	pmap_is_referenced(pg)	\ |
| 334 | 	(((pg)->mdpage.pvh_attrs & PVF_REF) != 0) |
| 335 | #define	pmap_is_page_colored_p(md)	\ |
| 336 | 	(((md)->pvh_attrs & PVF_COLORED) != 0) |
| 337 | |
| 338 | #define	pmap_copy(dp, sp, da, l, sa)	/* nothing */ |
| 339 | |
| 340 | #define	pmap_phys_address(ppn)		(arm_ptob((ppn))) |
| 341 | u_int arm32_mmap_flags(paddr_t); |
| 342 | #define	ARM32_MMAP_WRITECOMBINE		0x40000000 |
| 343 | #define	ARM32_MMAP_CACHEABLE		0x20000000 |
| 344 | #define	ARM_MMAP_WRITECOMBINE		ARM32_MMAP_WRITECOMBINE |
| 345 | #define	ARM_MMAP_CACHEABLE		ARM32_MMAP_CACHEABLE |
| 346 | #define	pmap_mmap_flags(ppn)		arm32_mmap_flags(ppn) |
| 347 | |
| 348 | #define	PMAP_PTE			0x10000000 /* kenter_pa */ |
| 349 | #define	PMAP_DEV			0x20000000 /* kenter_pa */ |
| 350 | #define	PMAP_DEV_SO			0x40000000 /* kenter_pa */ |
| 351 | #define	PMAP_DEV_MASK			(PMAP_DEV | PMAP_DEV_SO) |
| 352 | |
| 353 | /* |
| 354 | * Functions that we need to export |
| 355 | */ |
| 356 | void	pmap_procwr(struct proc *, vaddr_t, int); |
| 357 | bool	pmap_remove_all(pmap_t); |
| 358 | bool	pmap_extract(pmap_t, vaddr_t, paddr_t *); |
| 359 | |
| 360 | #define	PMAP_NEED_PROCWR |
| 361 | #define	PMAP_GROWKERNEL		/* turn on pmap_growkernel interface */ |
| 362 | #define	PMAP_ENABLE_PMAP_KMPAGE	/* enable the PMAP_KMPAGE flag */ |
| 363 | |
| 364 | #if (ARM_MMU_V6 + ARM_MMU_V7) > 0 |
| 365 | #define	PMAP_PREFER(hint, vap, sz, td)	pmap_prefer((hint), (vap), (td)) |
| 366 | void	pmap_prefer(vaddr_t, vaddr_t *, int); |
| 367 | #endif |
| 368 | |
| 369 | #ifdef ARM_MMU_EXTENDED |
| 370 | int	pmap_maxproc_set(int); |
| 371 | struct pmap * |
| 372 | 	pmap_efirt(void); |
| 373 | #endif |
| 374 | |
| 375 | void	pmap_icache_sync_range(pmap_t, vaddr_t, vaddr_t); |
| 376 | |
| 377 | /* Functions we use internally. */ |
| 378 | #ifdef PMAP_STEAL_MEMORY |
| 379 | void	pmap_boot_pagealloc(psize_t, psize_t, psize_t, pv_addr_t *); |
| 380 | void	pmap_boot_pageadd(pv_addr_t *); |
| 381 | vaddr_t	pmap_steal_memory(vsize_t, vaddr_t *, vaddr_t *); |
| 382 | #endif |
| 383 | void	pmap_bootstrap(vaddr_t, vaddr_t); |
| 384 | |
| 385 | struct pmap * |
| 386 | 	pmap_efirt(void); |
| 387 | void	pmap_activate_efirt(void); |
| 388 | void	pmap_deactivate_efirt(void); |
| 389 | |
| 390 | void	pmap_do_remove(pmap_t, vaddr_t, vaddr_t, int); |
| 391 | int	pmap_fault_fixup(pmap_t, vaddr_t, vm_prot_t, int); |
| 392 | int	pmap_prefetchabt_fixup(void *); |
| 393 | bool	pmap_get_pde_pte(pmap_t, vaddr_t, pd_entry_t **, pt_entry_t **); |
| 394 | bool	pmap_get_pde(pmap_t, vaddr_t, pd_entry_t **); |
| 395 | bool	pmap_extract_coherency(pmap_t, vaddr_t, paddr_t *, bool *); |
| 396 | |
| 397 | void	pmap_postinit(void); |
| 398 | |
| 399 | void	vector_page_setprot(int); |
| 400 | |
| 401 | /* Bootstrapping routines. */ |
| 402 | void	pmap_map_section(vaddr_t, vaddr_t, paddr_t, int, int); |
| 403 | void	pmap_map_entry(vaddr_t, vaddr_t, paddr_t, int, int); |
| 404 | vsize_t	pmap_map_chunk(vaddr_t, vaddr_t, paddr_t, vsize_t, int, int); |
| 405 | void	pmap_unmap_chunk(vaddr_t, vaddr_t, vsize_t); |
| 406 | void	pmap_link_l2pt(vaddr_t, vaddr_t, pv_addr_t *); |
| 407 | |
| 408 | vsize_t pmap_kenter_range(vaddr_t, paddr_t, vsize_t, vm_prot_t, u_int); |
| 409 | |
| 410 | /* |
| 411 | * Special page zero routine for use by the idle loop (no cache cleans). |
| 412 | */ |
| 413 | bool	pmap_pageidlezero(paddr_t); |
| 414 | #define	PMAP_PAGEIDLEZERO(pa)	pmap_pageidlezero((pa)) |
| 415 | |
| 416 | #ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS |
| 417 | /* |
| 418 | * For the pmap, this is a more useful way to map a direct mapped page. |
| 419 | * It returns either the direct-mapped VA or the VA supplied if it can't |
| 420 | * be direct mapped. |
| 421 | */ |
| 422 | vaddr_t	pmap_direct_mapped_phys(paddr_t, bool *, vaddr_t); |
| 423 | #endif |
| 424 | |
| 425 | /* |
| 426 | * used by dumpsys to record the PA of the L1 table |
| 427 | */ |
| 428 | uint32_t pmap_kernel_L1_addr(void); |
| 429 | /* |
| 430 | * The current top of kernel VM |
| 431 | */ |
| 432 | extern vaddr_t	pmap_curmaxkvaddr; |
| 433 | |
| 434 | #if defined(ARM_MMU_EXTENDED) && defined(__HAVE_MM_MD_DIRECT_MAPPED_PHYS) |
| 435 | /* |
| 436 | * Ending VA of direct mapped memory (usually KERNEL_VM_BASE). |
| 437 | */ |
| 438 | extern vaddr_t pmap_directlimit; |
| 439 | #endif |
| 440 | |
| 441 | /* |
| 442 | * Useful macros and constants |
| 443 | */ |
| 444 | |
| 445 | /* Virtual address to page table entry */ |
| 446 | static inline pt_entry_t * |
| 447 | vtopte(vaddr_t va) |
| 448 | { |
| 449 | 	pd_entry_t *pdep; |
| 450 | 	pt_entry_t *ptep; |
| 451 | |
| 452 | 	KASSERT(trunc_page(va) == va); |
| 453 | |
| 454 | 	if (pmap_get_pde_pte(pmap_kernel(), va, &pdep, &ptep) == false) |
| 455 | 		return (NULL); |
| 456 | 	return (ptep); |
| 457 | } |
| 458 | |
| 459 | /* |
| 460 | * Virtual address to physical address |
| 461 | */ |
| 462 | static inline paddr_t |
| 463 | vtophys(vaddr_t va) |
| 464 | { |
| 465 | 	paddr_t pa; |
| 466 | |
| 467 | 	if (pmap_extract(pmap_kernel(), va, &pa) == false) |
| 468 | 		return (0);	/* XXXSCW: Panic? */ |
| 469 | |
| 470 | 	return (pa); |
| 471 | } |
| 472 | |
| 473 | /* |
| 474 | * The new pmap ensures that page-tables are always mapping Write-Thru. |
| 475 | * Thus, on some platforms we can run fast and loose and avoid syncing PTEs |
| 476 | * on every change. |
| 477 | * |
| 478 | * Unfortunately, not all CPUs have a write-through cache mode. So we |
| 479 | * define PMAP_NEEDS_PTE_SYNC for C code to conditionally do PTE syncs, |
| 480 | * and if there is the chance for PTE syncs to be needed, we define |
| 481 | * PMAP_INCLUDE_PTE_SYNC so e.g. assembly code can include (and run) |
| 482 | * the code. |
| 483 | */ |
| 484 | extern int pmap_needs_pte_sync; |
| 485 | #if defined(_KERNEL_OPT) |
| 486 | /* |
| 487 | * Perform compile time evaluation of PMAP_NEEDS_PTE_SYNC when only a |
| 488 | * single MMU type is selected. |
| 489 | * |
| 490 | * StrongARM SA-1 caches do not have a write-through mode. So, on these, |
| 491 | * we need to do PTE syncs. Additionally, V6 MMUs also need PTE syncs. |
| 492 | * Finally, MEMC, GENERIC and XSCALE MMUs do not need PTE syncs. |
| 493 | * |
| 494 | * Use run time evaluation for all other cases. |
| 495 | * |
| 496 | */ |
| 497 | #if (ARM_NMMUS == 1) |
| 498 | #if (ARM_MMU_SA1 + ARM_MMU_V6 != 0) |
| 499 | #define	PMAP_INCLUDE_PTE_SYNC |
| 500 | #define	PMAP_NEEDS_PTE_SYNC	1 |
| 501 | #elif (ARM_MMU_MEMC + ARM_MMU_GENERIC + ARM_MMU_XSCALE != 0) |
| 502 | #define	PMAP_NEEDS_PTE_SYNC	0 |
| 503 | #endif |
| 504 | #endif |
| 505 | #endif /* _KERNEL_OPT */ |
| 506 | |
| 507 | /* |
| 508 | * Provide a fallback in case we were not able to determine it at |
| 509 | * compile-time. |
| 510 | */ |
| 511 | #ifndef PMAP_NEEDS_PTE_SYNC |
| 512 | #define	PMAP_NEEDS_PTE_SYNC	pmap_needs_pte_sync |
| 513 | #define	PMAP_INCLUDE_PTE_SYNC |
| 514 | #endif |
| 515 | |
| 516 | static inline void |
| 517 | pmap_ptesync(pt_entry_t *ptep, size_t cnt) |
| 518 | { |
| 519 | 	if (PMAP_NEEDS_PTE_SYNC) { |
| 520 | 		cpu_dcache_wb_range((vaddr_t)ptep, cnt * sizeof(pt_entry_t)); |
| 521 | #ifdef SHEEVA_L2_CACHE |
| 522 | 		cpu_sdcache_wb_range((vaddr_t)ptep, -1, |
| 523 | 		 cnt * sizeof(pt_entry_t)); |
| 524 | #endif |
| 525 | 	} |
| 526 | 	dsb(sy); |
| 527 | } |
| 528 | |
| 529 | #define	PDE_SYNC(pdep)			pmap_ptesync((pdep), 1) |
| 530 | #define	PDE_SYNC_RANGE(pdep, cnt)	pmap_ptesync((pdep), (cnt)) |
| 531 | #define	PTE_SYNC(ptep)			pmap_ptesync((ptep), PAGE_SIZE / L2_S_SIZE) |
| 532 | #define	PTE_SYNC_RANGE(ptep, cnt)	pmap_ptesync((ptep), (cnt)) |
| 533 | |
| 534 | #define	l1pte_valid_p(pde)	((pde) != 0) |
| 535 | #define	l1pte_section_p(pde)	(((pde) & L1_TYPE_MASK) == L1_TYPE_S) |
| 536 | #define	l1pte_supersection_p(pde) (l1pte_section_p(pde)	\ |
| 537 | 				&& ((pde) & L1_S_V6_SUPER) != 0) |
| 538 | #define	l1pte_page_p(pde)	(((pde) & L1_TYPE_MASK) == L1_TYPE_C) |
| 539 | #define	l1pte_fpage_p(pde)	(((pde) & L1_TYPE_MASK) == L1_TYPE_F) |
| 540 | #define	l1pte_pa(pde)		((pde) & L1_C_ADDR_MASK) |
| 541 | #define	l1pte_index(v)		((vaddr_t)(v) >> L1_S_SHIFT) |
| 542 | |
| 543 | static inline void |
| 544 | l1pte_setone(pt_entry_t *pdep, pt_entry_t pde) |
| 545 | { |
| 546 | 	*pdep = pde; |
| 547 | } |
| 548 | |
| 549 | static inline void |
| 550 | l1pte_set(pt_entry_t *pdep, pt_entry_t pde) |
| 551 | { |
| 552 | 	*pdep = pde; |
| 553 | 	if (l1pte_page_p(pde)) { |
| 554 | 		KASSERTMSG((((uintptr_t)pdep / sizeof(pde)) & (PAGE_SIZE / L2_T_SIZE - 1)) == 0, "%p", pdep); |
| 555 | 		for (int k = 1; k < PAGE_SIZE / L2_T_SIZE; k++) { |
| 556 | 			pde += L2_T_SIZE; |
| 557 | 			pdep[k] = pde; |
| 558 | 		} |
| 559 | 	} else if (l1pte_supersection_p(pde)) { |
| 560 | 		KASSERTMSG((((uintptr_t)pdep / sizeof(pde)) & (L1_SS_SIZE / L1_S_SIZE - 1)) == 0, "%p", pdep); |
| 561 | 		for (int k = 1; k < L1_SS_SIZE / L1_S_SIZE; k++) { |
| 562 | 			pdep[k] = pde; |
| 563 | 		} |
| 564 | 	} |
| 565 | } |
| 566 | |
| 567 | #define	l2pte_index(v)		((((v) & L2_ADDR_BITS) >> PGSHIFT) << (PGSHIFT-L2_S_SHIFT)) |
| 568 | #define	l2pte_valid_p(pte)	(((pte) & L2_TYPE_MASK) != L2_TYPE_INV) |
| 569 | #define	l2pte_pa(pte)		((pte) & L2_S_FRAME) |
| 570 | #define	l1pte_lpage_p(pte)	(((pte) & L2_TYPE_MASK) == L2_TYPE_L) |
| 571 | #define	l2pte_minidata_p(pte)	(((pte) & \ |
| 572 | 				 (L2_B | L2_C | L2_XS_T_TEX(TEX_XSCALE_X)))\ |
| 573 | 				 == (L2_C | L2_XS_T_TEX(TEX_XSCALE_X))) |
| 574 | |
| 575 | static inline void |
| 576 | l2pte_set(pt_entry_t *ptep, pt_entry_t pte, pt_entry_t opte) |
| 577 | { |
| 578 | 	if (l1pte_lpage_p(pte)) { |
| 579 | 		KASSERTMSG((((uintptr_t)ptep / sizeof(pte)) & (L2_L_SIZE / L2_S_SIZE - 1)) == 0, "%p", ptep); |
| 580 | 		for (int k = 0; k < L2_L_SIZE / L2_S_SIZE; k++) { |
| 581 | 			*ptep++ = pte; |
| 582 | 		} |
| 583 | 	} else { |
| 584 | 		KASSERTMSG((((uintptr_t)ptep / sizeof(pte)) & (PAGE_SIZE / L2_S_SIZE - 1)) == 0, "%p", ptep); |
| 585 | 		for (int k = 0; k < PAGE_SIZE / L2_S_SIZE; k++) { |
| 586 | 			KASSERTMSG(*ptep == opte, "%#x [*%p] != %#x", *ptep, ptep, opte); |
| 587 | 			*ptep++ = pte; |
| 588 | 			pte += L2_S_SIZE; |
| 589 | 			if (opte) |
| 590 | 				opte += L2_S_SIZE; |
| 591 | 		} |
| 592 | 	} |
| 593 | } |
| 594 | |
| 595 | static inline void |
| 596 | l2pte_reset(pt_entry_t *ptep) |
| 597 | { |
| 598 | 	KASSERTMSG((((uintptr_t)ptep / sizeof(*ptep)) & (PAGE_SIZE / L2_S_SIZE - 1)) == 0, "%p", ptep); |
| 599 | 	*ptep = 0; |
| 600 | 	for (int k = 1; k < PAGE_SIZE / L2_S_SIZE; k++) { |
| 601 | 		ptep[k] = 0; |
| 602 | 	} |
| 603 | } |
| 604 | |
| 605 | /* L1 and L2 page table macros */ |
| 606 | #define	pmap_pde_v(pde)		l1pte_valid(*(pde)) |
| 607 | #define	pmap_pde_section(pde)	l1pte_section_p(*(pde)) |
| 608 | #define	pmap_pde_supersection(pde)	l1pte_supersection_p(*(pde)) |
| 609 | #define	pmap_pde_page(pde)	l1pte_page_p(*(pde)) |
| 610 | #define	pmap_pde_fpage(pde)	l1pte_fpage_p(*(pde)) |
| 611 | |
| 612 | #define	pmap_pte_v(pte)		l2pte_valid_p(*(pte)) |
| 613 | #define	pmap_pte_pa(pte)	l2pte_pa(*(pte)) |
| 614 | |
| 615 | static inline uint32_t |
| 616 | pte_value(pt_entry_t pte) |
| 617 | { |
| 618 | 	return pte; |
| 619 | } |
| 620 | |
| 621 | static inline bool |
| 622 | pte_valid_p(pt_entry_t pte) |
| 623 | { |
| 624 | |
| 625 | 	return l2pte_valid_p(pte); |
| 626 | } |
| 627 | |
| 628 | |
| 629 | /* Size of the kernel part of the L1 page table */ |
| 630 | #define	KERNEL_PD_SIZE	\ |
| 631 | 	(L1_TABLE_SIZE - (KERNEL_BASE >> L1_S_SHIFT) * sizeof(pd_entry_t)) |
| 632 | |
| 633 | void	bzero_page(vaddr_t); |
| 634 | void	bcopy_page(vaddr_t, vaddr_t); |
| 635 | |
| 636 | #ifdef FPU_VFP |
| 637 | void	bzero_page_vfp(vaddr_t); |
| 638 | void	bcopy_page_vfp(vaddr_t, vaddr_t); |
| 639 | #endif |
| 640 | |
| 641 | /************************* ARM MMU configuration *****************************/ |
| 642 | |
| 643 | #if (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6 + ARM_MMU_V7) != 0 |
| 644 | void	pmap_copy_page_generic(paddr_t, paddr_t); |
| 645 | void	pmap_zero_page_generic(paddr_t); |
| 646 | |
| 647 | void	pmap_pte_init_generic(void); |
| 648 | #if defined(CPU_ARM8) |
| 649 | void	pmap_pte_init_arm8(void); |
| 650 | #endif |
| 651 | #if defined(CPU_ARM9) |
| 652 | void	pmap_pte_init_arm9(void); |
| 653 | #endif /* CPU_ARM9 */ |
| 654 | #if defined(CPU_ARM10) |
| 655 | void	pmap_pte_init_arm10(void); |
| 656 | #endif /* CPU_ARM10 */ |
| 657 | #if defined(CPU_ARM11)	/* ARM_MMU_V6 */ |
| 658 | void	pmap_pte_init_arm11(void); |
| 659 | #endif /* CPU_ARM11 */ |
| 660 | #if defined(CPU_ARM11MPCORE)	/* ARM_MMU_V6 */ |
| 661 | void	pmap_pte_init_arm11mpcore(void); |
| 662 | #endif |
| 663 | #if ARM_MMU_V6 == 1 |
| 664 | void	pmap_pte_init_armv6(void); |
| 665 | #endif /* ARM_MMU_V6 */ |
| 666 | #if ARM_MMU_V7 == 1 |
| 667 | void	pmap_pte_init_armv7(void); |
| 668 | #endif /* ARM_MMU_V7 */ |
| 669 | #endif /* (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0 */ |
| 670 | |
| 671 | #if ARM_MMU_SA1 == 1 |
| 672 | void	pmap_pte_init_sa1(void); |
| 673 | #endif /* ARM_MMU_SA1 == 1 */ |
| 674 | |
| 675 | #if ARM_MMU_XSCALE == 1 |
| 676 | void	pmap_copy_page_xscale(paddr_t, paddr_t); |
| 677 | void	pmap_zero_page_xscale(paddr_t); |
| 678 | |
| 679 | void	pmap_pte_init_xscale(void); |
| 680 | |
| 681 | void	xscale_setup_minidata(vaddr_t, vaddr_t, paddr_t); |
| 682 | |
| 683 | #define	PMAP_UAREA(va)		pmap_uarea(va) |
| 684 | void	pmap_uarea(vaddr_t); |
| 685 | #endif /* ARM_MMU_XSCALE == 1 */ |
| 686 | |
| 687 | extern pt_entry_t		pte_l1_s_nocache_mode; |
| 688 | extern pt_entry_t		pte_l2_l_nocache_mode; |
| 689 | extern pt_entry_t		pte_l2_s_nocache_mode; |
| 690 | |
| 691 | extern pt_entry_t		pte_l1_s_cache_mode; |
| 692 | extern pt_entry_t		pte_l2_l_cache_mode; |
| 693 | extern pt_entry_t		pte_l2_s_cache_mode; |
| 694 | |
| 695 | extern pt_entry_t		pte_l1_s_cache_mode_pt; |
| 696 | extern pt_entry_t		pte_l2_l_cache_mode_pt; |
| 697 | extern pt_entry_t		pte_l2_s_cache_mode_pt; |
| 698 | |
| 699 | extern pt_entry_t		pte_l1_s_wc_mode; |
| 700 | extern pt_entry_t		pte_l2_l_wc_mode; |
| 701 | extern pt_entry_t		pte_l2_s_wc_mode; |
| 702 | |
| 703 | extern pt_entry_t		pte_l1_s_cache_mask; |
| 704 | extern pt_entry_t		pte_l2_l_cache_mask; |
| 705 | extern pt_entry_t		pte_l2_s_cache_mask; |
| 706 | |
| 707 | extern pt_entry_t		pte_l1_s_prot_u; |
| 708 | extern pt_entry_t		pte_l1_s_prot_w; |
| 709 | extern pt_entry_t		pte_l1_s_prot_ro; |
| 710 | extern pt_entry_t		pte_l1_s_prot_mask; |
| 711 | |
| 712 | extern pt_entry_t		pte_l2_s_prot_u; |
| 713 | extern pt_entry_t		pte_l2_s_prot_w; |
| 714 | extern pt_entry_t		pte_l2_s_prot_ro; |
| 715 | extern pt_entry_t		pte_l2_s_prot_mask; |
| 716 | |
| 717 | extern pt_entry_t		pte_l2_l_prot_u; |
| 718 | extern pt_entry_t		pte_l2_l_prot_w; |
| 719 | extern pt_entry_t		pte_l2_l_prot_ro; |
| 720 | extern pt_entry_t		pte_l2_l_prot_mask; |
| 721 | |
| 722 | extern pt_entry_t		pte_l1_ss_proto; |
| 723 | extern pt_entry_t		pte_l1_s_proto; |
| 724 | extern pt_entry_t		pte_l1_c_proto; |
| 725 | extern pt_entry_t		pte_l2_s_proto; |
| 726 | |
| 727 | extern void (*pmap_copy_page_func)(paddr_t, paddr_t); |
| 728 | extern void (*pmap_zero_page_func)(paddr_t); |
| 729 | |
| 730 | /* |
| 731 | * Global varaiables in cpufunc_asm_xscale.S supporting the Xscale |
| 732 | * cache clean/purge functions. |
| 733 | */ |
| 734 | extern vaddr_t xscale_minidata_clean_addr; |
| 735 | extern vsize_t xscale_minidata_clean_size; |
| 736 | extern vaddr_t xscale_cache_clean_addr; |
| 737 | extern vsize_t xscale_cache_clean_size; |
| 738 | |
| 739 | #endif /* !_LOCORE */ |
| 740 | |
| 741 | /*****************************************************************************/ |
| 742 | |
| 743 | #define	KERNEL_PID		0	/* The kernel uses ASID 0 */ |
| 744 | |
| 745 | /* |
| 746 | * Definitions for MMU domains |
| 747 | */ |
| 748 | #define	PMAP_DOMAINS		15	/* 15 'user' domains (1-15) */ |
| 749 | #define	PMAP_DOMAIN_KERNEL	0	/* The kernel pmap uses domain #0 */ |
| 750 | |
| 751 | #ifdef ARM_MMU_EXTENDED |
| 752 | #define	PMAP_DOMAIN_USER	1	/* User pmaps use domain #1 */ |
| 753 | #define	DOMAIN_DEFAULT		((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | (DOMAIN_CLIENT << (PMAP_DOMAIN_USER*2))) |
| 754 | #else |
| 755 | #define	DOMAIN_DEFAULT		((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2))) |
| 756 | #endif |
| 757 | |
| 758 | /* |
| 759 | * These macros define the various bit masks in the PTE. |
| 760 | * |
| 761 | * We use these macros since we use different bits on different processor |
| 762 | * models. |
| 763 | */ |
| 764 | #define	L1_S_PROT_U_generic	(L1_S_AP(AP_U)) |
| 765 | #define	L1_S_PROT_W_generic	(L1_S_AP(AP_W)) |
| 766 | #define	L1_S_PROT_RO_generic	(0) |
| 767 | #define	L1_S_PROT_MASK_generic	(L1_S_PROT_U|L1_S_PROT_W|L1_S_PROT_RO) |
| 768 | |
| 769 | #define	L1_S_PROT_U_xscale	(L1_S_AP(AP_U)) |
| 770 | #define	L1_S_PROT_W_xscale	(L1_S_AP(AP_W)) |
| 771 | #define	L1_S_PROT_RO_xscale	(0) |
| 772 | #define	L1_S_PROT_MASK_xscale	(L1_S_PROT_U|L1_S_PROT_W|L1_S_PROT_RO) |
| 773 | |
| 774 | #define	L1_S_PROT_U_armv6	(L1_S_AP(AP_R) | L1_S_AP(AP_U)) |
| 775 | #define	L1_S_PROT_W_armv6	(L1_S_AP(AP_W)) |
| 776 | #define	L1_S_PROT_RO_armv6	(L1_S_AP(AP_R) | L1_S_AP(AP_RO)) |
| 777 | #define	L1_S_PROT_MASK_armv6	(L1_S_PROT_U|L1_S_PROT_W|L1_S_PROT_RO) |
| 778 | |
| 779 | #define	L1_S_PROT_U_armv7	(L1_S_AP(AP_R) | L1_S_AP(AP_U)) |
| 780 | #define	L1_S_PROT_W_armv7	(L1_S_AP(AP_W)) |
| 781 | #define	L1_S_PROT_RO_armv7	(L1_S_AP(AP_R) | L1_S_AP(AP_RO)) |
| 782 | #define	L1_S_PROT_MASK_armv7	(L1_S_PROT_U|L1_S_PROT_W|L1_S_PROT_RO) |
| 783 | |
| 784 | #define	L1_S_CACHE_MASK_generic	(L1_S_B|L1_S_C) |
| 785 | #define	L1_S_CACHE_MASK_xscale	(L1_S_B|L1_S_C|L1_S_XS_TEX(TEX_XSCALE_X)) |
| 786 | #define	L1_S_CACHE_MASK_armv6	(L1_S_B|L1_S_C|L1_S_XS_TEX(TEX_ARMV6_TEX)) |
| 787 | #define	L1_S_CACHE_MASK_armv6n	(L1_S_B|L1_S_C|L1_S_XS_TEX(TEX_ARMV6_TEX)|L1_S_V6_S) |
| 788 | #define	L1_S_CACHE_MASK_armv7	(L1_S_B|L1_S_C|L1_S_XS_TEX(TEX_ARMV6_TEX)|L1_S_V6_S) |
| 789 | |
| 790 | #define	L2_L_PROT_U_generic	(L2_AP(AP_U)) |
| 791 | #define	L2_L_PROT_W_generic	(L2_AP(AP_W)) |
| 792 | #define	L2_L_PROT_RO_generic	(0) |
| 793 | #define	L2_L_PROT_MASK_generic	(L2_L_PROT_U|L2_L_PROT_W|L2_L_PROT_RO) |
| 794 | |
| 795 | #define	L2_L_PROT_U_xscale	(L2_AP(AP_U)) |
| 796 | #define	L2_L_PROT_W_xscale	(L2_AP(AP_W)) |
| 797 | #define	L2_L_PROT_RO_xscale	(0) |
| 798 | #define	L2_L_PROT_MASK_xscale	(L2_L_PROT_U|L2_L_PROT_W|L2_L_PROT_RO) |
| 799 | |
| 800 | #define	L2_L_PROT_U_armv6n	(L2_AP0(AP_R) | L2_AP0(AP_U)) |
| 801 | #define	L2_L_PROT_W_armv6n	(L2_AP0(AP_W)) |
| 802 | #define	L2_L_PROT_RO_armv6n	(L2_AP0(AP_R) | L2_AP0(AP_RO)) |
| 803 | #define	L2_L_PROT_MASK_armv6n	(L2_L_PROT_U|L2_L_PROT_W|L2_L_PROT_RO) |
| 804 | |
| 805 | #define	L2_L_PROT_U_armv7	(L2_AP0(AP_R) | L2_AP0(AP_U)) |
| 806 | #define	L2_L_PROT_W_armv7	(L2_AP0(AP_W)) |
| 807 | #define	L2_L_PROT_RO_armv7	(L2_AP0(AP_R) | L2_AP0(AP_RO)) |
| 808 | #define	L2_L_PROT_MASK_armv7	(L2_L_PROT_U|L2_L_PROT_W|L2_L_PROT_RO) |
| 809 | |
| 810 | #define	L2_L_CACHE_MASK_generic	(L2_B|L2_C) |
| 811 | #define	L2_L_CACHE_MASK_xscale	(L2_B|L2_C|L2_XS_L_TEX(TEX_XSCALE_X)) |
| 812 | #define	L2_L_CACHE_MASK_armv6	(L2_B|L2_C|L2_V6_L_TEX(TEX_ARMV6_TEX)) |
| 813 | #define	L2_L_CACHE_MASK_armv6n	(L2_B|L2_C|L2_V6_L_TEX(TEX_ARMV6_TEX)|L2_XS_S) |
| 814 | #define	L2_L_CACHE_MASK_armv7	(L2_B|L2_C|L2_V6_L_TEX(TEX_ARMV6_TEX)|L2_XS_S) |
| 815 | |
| 816 | #define	L2_S_PROT_U_generic	(L2_AP(AP_U)) |
| 817 | #define	L2_S_PROT_W_generic	(L2_AP(AP_W)) |
| 818 | #define	L2_S_PROT_RO_generic	(0) |
| 819 | #define	L2_S_PROT_MASK_generic	(L2_S_PROT_U|L2_S_PROT_W|L2_S_PROT_RO) |
| 820 | |
| 821 | #define	L2_S_PROT_U_xscale	(L2_AP0(AP_U)) |
| 822 | #define	L2_S_PROT_W_xscale	(L2_AP0(AP_W)) |
| 823 | #define	L2_S_PROT_RO_xscale	(0) |
| 824 | #define	L2_S_PROT_MASK_xscale	(L2_S_PROT_U|L2_S_PROT_W|L2_S_PROT_RO) |
| 825 | |
| 826 | #define	L2_S_PROT_U_armv6n	(L2_AP0(AP_R) | L2_AP0(AP_U)) |
| 827 | #define	L2_S_PROT_W_armv6n	(L2_AP0(AP_W)) |
| 828 | #define	L2_S_PROT_RO_armv6n	(L2_AP0(AP_R) | L2_AP0(AP_RO)) |
| 829 | #define	L2_S_PROT_MASK_armv6n	(L2_S_PROT_U|L2_S_PROT_W|L2_S_PROT_RO) |
| 830 | |
| 831 | #define	L2_S_PROT_U_armv7	(L2_AP0(AP_R) | L2_AP0(AP_U)) |
| 832 | #define	L2_S_PROT_W_armv7	(L2_AP0(AP_W)) |
| 833 | #define	L2_S_PROT_RO_armv7	(L2_AP0(AP_R) | L2_AP0(AP_RO)) |
| 834 | #define	L2_S_PROT_MASK_armv7	(L2_S_PROT_U|L2_S_PROT_W|L2_S_PROT_RO) |
| 835 | |
| 836 | #define	L2_S_CACHE_MASK_generic	(L2_B|L2_C) |
| 837 | #define	L2_S_CACHE_MASK_xscale	(L2_B|L2_C|L2_XS_T_TEX(TEX_XSCALE_X)) |
| 838 | #define	L2_XS_CACHE_MASK_armv6	(L2_B|L2_C|L2_V6_XS_TEX(TEX_ARMV6_TEX)) |
| 839 | #ifdef	ARMV6_EXTENDED_SMALL_PAGE |
| 840 | #define	L2_S_CACHE_MASK_armv6c	L2_XS_CACHE_MASK_armv6 |
| 841 | #else |
| 842 | #define	L2_S_CACHE_MASK_armv6c	L2_S_CACHE_MASK_generic |
| 843 | #endif |
| 844 | #define	L2_S_CACHE_MASK_armv6n	(L2_B|L2_C|L2_V6_XS_TEX(TEX_ARMV6_TEX)|L2_XS_S) |
| 845 | #define	L2_S_CACHE_MASK_armv7	(L2_B|L2_C|L2_V6_XS_TEX(TEX_ARMV6_TEX)|L2_XS_S) |
| 846 | |
| 847 | |
| 848 | #define	L1_S_PROTO_generic	(L1_TYPE_S | L1_S_IMP) |
| 849 | #define	L1_S_PROTO_xscale	(L1_TYPE_S) |
| 850 | #define	L1_S_PROTO_armv6	(L1_TYPE_S) |
| 851 | #define	L1_S_PROTO_armv7	(L1_TYPE_S) |
| 852 | |
| 853 | #define	L1_SS_PROTO_generic	0 |
| 854 | #define	L1_SS_PROTO_xscale	0 |
| 855 | #define	L1_SS_PROTO_armv6	(L1_TYPE_S | L1_S_V6_SS) |
| 856 | #define	L1_SS_PROTO_armv7	(L1_TYPE_S | L1_S_V6_SS) |
| 857 | |
| 858 | #define	L1_C_PROTO_generic	(L1_TYPE_C | L1_C_IMP2) |
| 859 | #define	L1_C_PROTO_xscale	(L1_TYPE_C) |
| 860 | #define	L1_C_PROTO_armv6	(L1_TYPE_C) |
| 861 | #define	L1_C_PROTO_armv7	(L1_TYPE_C) |
| 862 | |
| 863 | #define	L2_L_PROTO		(L2_TYPE_L) |
| 864 | |
| 865 | #define	L2_S_PROTO_generic	(L2_TYPE_S) |
| 866 | #define	L2_S_PROTO_xscale	(L2_TYPE_XS) |
| 867 | #ifdef	ARMV6_EXTENDED_SMALL_PAGE |
| 868 | #define	L2_S_PROTO_armv6c	(L2_TYPE_XS) /* XP=0, extended small page */ |
| 869 | #else |
| 870 | #define	L2_S_PROTO_armv6c	(L2_TYPE_S)	/* XP=0, subpage APs */ |
| 871 | #endif |
| 872 | #ifdef ARM_MMU_EXTENDED |
| 873 | #define	L2_S_PROTO_armv6n	(L2_TYPE_S|L2_XS_XN) |
| 874 | #else |
| 875 | #define	L2_S_PROTO_armv6n	(L2_TYPE_S)	/* with XP=1 */ |
| 876 | #endif |
| 877 | #ifdef ARM_MMU_EXTENDED |
| 878 | #define	L2_S_PROTO_armv7	(L2_TYPE_S|L2_XS_XN) |
| 879 | #else |
| 880 | #define	L2_S_PROTO_armv7	(L2_TYPE_S) |
| 881 | #endif |
| 882 | |
| 883 | /* |
| 884 | * User-visible names for the ones that vary with MMU class. |
| 885 | */ |
| 886 | |
| 887 | #if ARM_NMMUS > 1 |
| 888 | /* More than one MMU class configured; use variables. */ |
| 889 | #define	L1_S_PROT_U		pte_l1_s_prot_u |
| 890 | #define	L1_S_PROT_W		pte_l1_s_prot_w |
| 891 | #define	L1_S_PROT_RO		pte_l1_s_prot_ro |
| 892 | #define	L1_S_PROT_MASK		pte_l1_s_prot_mask |
| 893 | |
| 894 | #define	L2_S_PROT_U		pte_l2_s_prot_u |
| 895 | #define	L2_S_PROT_W		pte_l2_s_prot_w |
| 896 | #define	L2_S_PROT_RO		pte_l2_s_prot_ro |
| 897 | #define	L2_S_PROT_MASK		pte_l2_s_prot_mask |
| 898 | |
| 899 | #define	L2_L_PROT_U		pte_l2_l_prot_u |
| 900 | #define	L2_L_PROT_W		pte_l2_l_prot_w |
| 901 | #define	L2_L_PROT_RO		pte_l2_l_prot_ro |
| 902 | #define	L2_L_PROT_MASK		pte_l2_l_prot_mask |
| 903 | |
| 904 | #define	L1_S_CACHE_MASK		pte_l1_s_cache_mask |
| 905 | #define	L2_L_CACHE_MASK		pte_l2_l_cache_mask |
| 906 | #define	L2_S_CACHE_MASK		pte_l2_s_cache_mask |
| 907 | |
| 908 | #define	L1_SS_PROTO		pte_l1_ss_proto |
| 909 | #define	L1_S_PROTO		pte_l1_s_proto |
| 910 | #define	L1_C_PROTO		pte_l1_c_proto |
| 911 | #define	L2_S_PROTO		pte_l2_s_proto |
| 912 | |
| 913 | #define	pmap_copy_page(s, d)	(*pmap_copy_page_func)((s), (d)) |
| 914 | #define	pmap_zero_page(d)	(*pmap_zero_page_func)((d)) |
| 915 | #elif (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0 |
| 916 | #define	L1_S_PROT_U		L1_S_PROT_U_generic |
| 917 | #define	L1_S_PROT_W		L1_S_PROT_W_generic |
| 918 | #define	L1_S_PROT_RO		L1_S_PROT_RO_generic |
| 919 | #define	L1_S_PROT_MASK		L1_S_PROT_MASK_generic |
| 920 | |
| 921 | #define	L2_S_PROT_U		L2_S_PROT_U_generic |
| 922 | #define	L2_S_PROT_W		L2_S_PROT_W_generic |
| 923 | #define	L2_S_PROT_RO		L2_S_PROT_RO_generic |
| 924 | #define	L2_S_PROT_MASK		L2_S_PROT_MASK_generic |
| 925 | |
| 926 | #define	L2_L_PROT_U		L2_L_PROT_U_generic |
| 927 | #define	L2_L_PROT_W		L2_L_PROT_W_generic |
| 928 | #define	L2_L_PROT_RO		L2_L_PROT_RO_generic |
| 929 | #define	L2_L_PROT_MASK		L2_L_PROT_MASK_generic |
| 930 | |
| 931 | #define	L1_S_CACHE_MASK		L1_S_CACHE_MASK_generic |
| 932 | #define	L2_L_CACHE_MASK		L2_L_CACHE_MASK_generic |
| 933 | #define	L2_S_CACHE_MASK		L2_S_CACHE_MASK_generic |
| 934 | |
| 935 | #define	L1_SS_PROTO		L1_SS_PROTO_generic |
| 936 | #define	L1_S_PROTO		L1_S_PROTO_generic |
| 937 | #define	L1_C_PROTO		L1_C_PROTO_generic |
| 938 | #define	L2_S_PROTO		L2_S_PROTO_generic |
| 939 | |
| 940 | #define	pmap_copy_page(s, d)	pmap_copy_page_generic((s), (d)) |
| 941 | #define	pmap_zero_page(d)	pmap_zero_page_generic((d)) |
| 942 | #elif ARM_MMU_V6N != 0 |
| 943 | #define	L1_S_PROT_U		L1_S_PROT_U_armv6 |
| 944 | #define	L1_S_PROT_W		L1_S_PROT_W_armv6 |
| 945 | #define	L1_S_PROT_RO		L1_S_PROT_RO_armv6 |
| 946 | #define	L1_S_PROT_MASK		L1_S_PROT_MASK_armv6 |
| 947 | |
| 948 | #define	L2_S_PROT_U		L2_S_PROT_U_armv6n |
| 949 | #define	L2_S_PROT_W		L2_S_PROT_W_armv6n |
| 950 | #define	L2_S_PROT_RO		L2_S_PROT_RO_armv6n |
| 951 | #define	L2_S_PROT_MASK		L2_S_PROT_MASK_armv6n |
| 952 | |
| 953 | #define	L2_L_PROT_U		L2_L_PROT_U_armv6n |
| 954 | #define	L2_L_PROT_W		L2_L_PROT_W_armv6n |
| 955 | #define	L2_L_PROT_RO		L2_L_PROT_RO_armv6n |
| 956 | #define	L2_L_PROT_MASK		L2_L_PROT_MASK_armv6n |
| 957 | |
| 958 | #define	L1_S_CACHE_MASK		L1_S_CACHE_MASK_armv6n |
| 959 | #define	L2_L_CACHE_MASK		L2_L_CACHE_MASK_armv6n |
| 960 | #define	L2_S_CACHE_MASK		L2_S_CACHE_MASK_armv6n |
| 961 | |
| 962 | /* |
| 963 | * These prototypes make writeable mappings, while the other MMU types |
| 964 | * make read-only mappings. |
| 965 | */ |
| 966 | #define	L1_SS_PROTO		L1_SS_PROTO_armv6 |
| 967 | #define	L1_S_PROTO		L1_S_PROTO_armv6 |
| 968 | #define	L1_C_PROTO		L1_C_PROTO_armv6 |
| 969 | #define	L2_S_PROTO		L2_S_PROTO_armv6n |
| 970 | |
| 971 | #define	pmap_copy_page(s, d)	pmap_copy_page_generic((s), (d)) |
| 972 | #define	pmap_zero_page(d)	pmap_zero_page_generic((d)) |
| 973 | #elif ARM_MMU_V6C != 0 |
| 974 | #define	L1_S_PROT_U		L1_S_PROT_U_generic |
| 975 | #define	L1_S_PROT_W		L1_S_PROT_W_generic |
| 976 | #define	L1_S_PROT_RO		L1_S_PROT_RO_generic |
| 977 | #define	L1_S_PROT_MASK		L1_S_PROT_MASK_generic |
| 978 | |
| 979 | #define	L2_S_PROT_U		L2_S_PROT_U_generic |
| 980 | #define	L2_S_PROT_W		L2_S_PROT_W_generic |
| 981 | #define	L2_S_PROT_RO		L2_S_PROT_RO_generic |
| 982 | #define	L2_S_PROT_MASK		L2_S_PROT_MASK_generic |
| 983 | |
| 984 | #define	L2_L_PROT_U		L2_L_PROT_U_generic |
| 985 | #define	L2_L_PROT_W		L2_L_PROT_W_generic |
| 986 | #define	L2_L_PROT_RO		L2_L_PROT_RO_generic |
| 987 | #define	L2_L_PROT_MASK		L2_L_PROT_MASK_generic |
| 988 | |
| 989 | #define	L1_S_CACHE_MASK		L1_S_CACHE_MASK_generic |
| 990 | #define	L2_L_CACHE_MASK		L2_L_CACHE_MASK_generic |
| 991 | #define	L2_S_CACHE_MASK		L2_S_CACHE_MASK_generic |
| 992 | |
| 993 | #define	L1_SS_PROTO		L1_SS_PROTO_armv6 |
| 994 | #define	L1_S_PROTO		L1_S_PROTO_generic |
| 995 | #define	L1_C_PROTO		L1_C_PROTO_generic |
| 996 | #define	L2_S_PROTO		L2_S_PROTO_generic |
| 997 | |
| 998 | #define	pmap_copy_page(s, d)	pmap_copy_page_generic((s), (d)) |
| 999 | #define	pmap_zero_page(d)	pmap_zero_page_generic((d)) |
| 1000 | #elif ARM_MMU_XSCALE == 1 |
| 1001 | #define	L1_S_PROT_U		L1_S_PROT_U_generic |
| 1002 | #define	L1_S_PROT_W		L1_S_PROT_W_generic |
| 1003 | #define	L1_S_PROT_RO		L1_S_PROT_RO_generic |
| 1004 | #define	L1_S_PROT_MASK		L1_S_PROT_MASK_generic |
| 1005 | |
| 1006 | #define	L2_S_PROT_U		L2_S_PROT_U_xscale |
| 1007 | #define	L2_S_PROT_W		L2_S_PROT_W_xscale |
| 1008 | #define	L2_S_PROT_RO		L2_S_PROT_RO_xscale |
| 1009 | #define	L2_S_PROT_MASK		L2_S_PROT_MASK_xscale |
| 1010 | |
| 1011 | #define	L2_L_PROT_U		L2_L_PROT_U_generic |
| 1012 | #define	L2_L_PROT_W		L2_L_PROT_W_generic |
| 1013 | #define	L2_L_PROT_RO		L2_L_PROT_RO_generic |
| 1014 | #define	L2_L_PROT_MASK		L2_L_PROT_MASK_generic |
| 1015 | |
| 1016 | #define	L1_S_CACHE_MASK		L1_S_CACHE_MASK_xscale |
| 1017 | #define	L2_L_CACHE_MASK		L2_L_CACHE_MASK_xscale |
| 1018 | #define	L2_S_CACHE_MASK		L2_S_CACHE_MASK_xscale |
| 1019 | |
| 1020 | #define	L1_SS_PROTO		L1_SS_PROTO_xscale |
| 1021 | #define	L1_S_PROTO		L1_S_PROTO_xscale |
| 1022 | #define	L1_C_PROTO		L1_C_PROTO_xscale |
| 1023 | #define	L2_S_PROTO		L2_S_PROTO_xscale |
| 1024 | |
| 1025 | #define	pmap_copy_page(s, d)	pmap_copy_page_xscale((s), (d)) |
| 1026 | #define	pmap_zero_page(d)	pmap_zero_page_xscale((d)) |
| 1027 | #elif ARM_MMU_V7 == 1 |
| 1028 | #define	L1_S_PROT_U		L1_S_PROT_U_armv7 |
| 1029 | #define	L1_S_PROT_W		L1_S_PROT_W_armv7 |
| 1030 | #define	L1_S_PROT_RO		L1_S_PROT_RO_armv7 |
| 1031 | #define	L1_S_PROT_MASK		L1_S_PROT_MASK_armv7 |
| 1032 | |
| 1033 | #define	L2_S_PROT_U		L2_S_PROT_U_armv7 |
| 1034 | #define	L2_S_PROT_W		L2_S_PROT_W_armv7 |
| 1035 | #define	L2_S_PROT_RO		L2_S_PROT_RO_armv7 |
| 1036 | #define	L2_S_PROT_MASK		L2_S_PROT_MASK_armv7 |
| 1037 | |
| 1038 | #define	L2_L_PROT_U		L2_L_PROT_U_armv7 |
| 1039 | #define	L2_L_PROT_W		L2_L_PROT_W_armv7 |
| 1040 | #define	L2_L_PROT_RO		L2_L_PROT_RO_armv7 |
| 1041 | #define	L2_L_PROT_MASK		L2_L_PROT_MASK_armv7 |
| 1042 | |
| 1043 | #define	L1_S_CACHE_MASK		L1_S_CACHE_MASK_armv7 |
| 1044 | #define	L2_L_CACHE_MASK		L2_L_CACHE_MASK_armv7 |
| 1045 | #define	L2_S_CACHE_MASK		L2_S_CACHE_MASK_armv7 |
| 1046 | |
| 1047 | /* |
| 1048 | * These prototypes make writeable mappings, while the other MMU types |
| 1049 | * make read-only mappings. |
| 1050 | */ |
| 1051 | #define	L1_SS_PROTO		L1_SS_PROTO_armv7 |
| 1052 | #define	L1_S_PROTO		L1_S_PROTO_armv7 |
| 1053 | #define	L1_C_PROTO		L1_C_PROTO_armv7 |
| 1054 | #define	L2_S_PROTO		L2_S_PROTO_armv7 |
| 1055 | |
| 1056 | #define	pmap_copy_page(s, d)	pmap_copy_page_generic((s), (d)) |
| 1057 | #define	pmap_zero_page(d)	pmap_zero_page_generic((d)) |
| 1058 | #endif /* ARM_NMMUS > 1 */ |
| 1059 | |
| 1060 | /* |
| 1061 | * Macros to set and query the write permission on page descriptors. |
| 1062 | */ |
| 1063 | #define	l1pte_set_writable(pte)	(((pte) & ~L1_S_PROT_RO) | L1_S_PROT_W) |
| 1064 | #define	l1pte_set_readonly(pte)	(((pte) & ~L1_S_PROT_W) | L1_S_PROT_RO) |
| 1065 | |
| 1066 | #define	l2pte_set_writable(pte)	(((pte) & ~L2_S_PROT_RO) | L2_S_PROT_W) |
| 1067 | #define	l2pte_set_readonly(pte)	(((pte) & ~L2_S_PROT_W) | L2_S_PROT_RO) |
| 1068 | |
| 1069 | #define	l2pte_writable_p(pte)	(((pte) & L2_S_PROT_W) == L2_S_PROT_W && \ |
| 1070 | 				 (L2_S_PROT_RO == 0 || \ |
| 1071 | 				 ((pte) & L2_S_PROT_RO) != L2_S_PROT_RO)) |
| 1072 | |
| 1073 | /* |
| 1074 | * These macros return various bits based on kernel/user and protection. |
| 1075 | * Note that the compiler will usually fold these at compile time. |
| 1076 | */ |
| 1077 | |
| 1078 | #define	L1_S_PROT(ku, pr)	(					 \ |
| 1079 | 	(((ku) == PTE_USER) ? 						 \ |
| 1080 | 	 L1_S_PROT_U | (((pr) & VM_PROT_WRITE) ? L1_S_PROT_W : 0)	 \ |
| 1081 | 	: 								 \ |
| 1082 | 	 (((L1_S_PROT_RO && 						 \ |
| 1083 | 		((pr) & (VM_PROT_READ | VM_PROT_WRITE)) == VM_PROT_READ) ? \ |
| 1084 | 		 L1_S_PROT_RO : L1_S_PROT_W)))			 \ |
| 1085 | ) |
| 1086 | |
| 1087 | #define	L2_L_PROT(ku, pr)	(					 \ |
| 1088 | 	(((ku) == PTE_USER) ?						 \ |
| 1089 | 	 L2_L_PROT_U | (((pr) & VM_PROT_WRITE) ? L2_L_PROT_W : 0)	 \ |
| 1090 | 	:								 \ |
| 1091 | 	 (((L2_L_PROT_RO && 						 \ |
| 1092 | 		((pr) & (VM_PROT_READ | VM_PROT_WRITE)) == VM_PROT_READ) ? \ |
| 1093 | 		 L2_L_PROT_RO : L2_L_PROT_W)))			 \ |
| 1094 | ) |
| 1095 | |
| 1096 | #define	L2_S_PROT(ku, pr)	(					 \ |
| 1097 | 	(((ku) == PTE_USER) ?						 \ |
| 1098 | 	 L2_S_PROT_U | (((pr) & VM_PROT_WRITE) ? L2_S_PROT_W : 0)	 \ |
| 1099 | 	:								 \ |
| 1100 | 	 (((L2_S_PROT_RO &&						 \ |
| 1101 | 		((pr) & (VM_PROT_READ | VM_PROT_WRITE)) == VM_PROT_READ) ? \ |
| 1102 | 		 L2_S_PROT_RO : L2_S_PROT_W)))			 \ |
| 1103 | ) |
| 1104 | |
| 1105 | /* |
| 1106 | * Macros to test if a mapping is mappable with an L1 SuperSection, |
| 1107 | * L1 Section, or an L2 Large Page mapping. |
| 1108 | */ |
| 1109 | #define	L1_SS_MAPPABLE_P(va, pa, size)					\ |
| 1110 | 	((((va) | (pa)) & L1_SS_OFFSET) == 0 && (size) >= L1_SS_SIZE) |
| 1111 | |
| 1112 | #define	L1_S_MAPPABLE_P(va, pa, size)					\ |
| 1113 | 	((((va) | (pa)) & L1_S_OFFSET) == 0 && (size) >= L1_S_SIZE) |
| 1114 | |
| 1115 | #define	L2_L_MAPPABLE_P(va, pa, size)					\ |
| 1116 | 	((((va) | (pa)) & L2_L_OFFSET) == 0 && (size) >= L2_L_SIZE) |
| 1117 | |
| 1118 | #define	PMAP_MAPSIZE1	L2_L_SIZE |
| 1119 | #define	PMAP_MAPSIZE2	L1_S_SIZE |
| 1120 | #if (ARM_MMU_V6 + ARM_MMU_V7) > 0 |
| 1121 | #define	PMAP_MAPSIZE3	L1_SS_SIZE |
| 1122 | #endif |
| 1123 | |
| 1124 | #ifndef _LOCORE |
| 1125 | /* |
| 1126 | * Hooks for the pool allocator. |
| 1127 | */ |
| 1128 | #define	POOL_VTOPHYS(va)	vtophys((vaddr_t) (va)) |
| 1129 | extern paddr_t physical_start, physical_end; |
| 1130 | #ifdef PMAP_NEED_ALLOC_POOLPAGE |
| 1131 | struct vm_page *arm_pmap_alloc_poolpage(int); |
| 1132 | #define	PMAP_ALLOC_POOLPAGE	arm_pmap_alloc_poolpage |
| 1133 | #endif |
| 1134 | #if defined(PMAP_NEED_ALLOC_POOLPAGE) || defined(__HAVE_MM_MD_DIRECT_MAPPED_PHYS) |
| 1135 | vaddr_t	pmap_map_poolpage(paddr_t); |
| 1136 | paddr_t	pmap_unmap_poolpage(vaddr_t); |
| 1137 | #define	PMAP_MAP_POOLPAGE(pa)	pmap_map_poolpage(pa) |
| 1138 | #define	PMAP_UNMAP_POOLPAGE(va)	pmap_unmap_poolpage(va) |
| 1139 | #endif |
| 1140 | |
| 1141 | #define	__HAVE_PMAP_PV_TRACK	1 |
| 1142 | |
| 1143 | void pmap_pv_protect(paddr_t, vm_prot_t); |
| 1144 | |
| 1145 | struct pmap_page { |
| 1146 | 	SLIST_HEAD(,pv_entry) pvh_list;		/* pv_entry list */ |
| 1147 | 	int pvh_attrs;				/* page attributes */ |
| 1148 | 	u_int uro_mappings; |
| 1149 | 	u_int urw_mappings; |
| 1150 | 	union { |
| 1151 | 		u_short s_mappings[2];	/* Assume kernel count <= 65535 */ |
| 1152 | 		u_int i_mappings; |
| 1153 | 	} k_u; |
| 1154 | }; |
| 1155 | |
| 1156 | /* |
| 1157 | * pmap-specific data store in the vm_page structure. |
| 1158 | */ |
| 1159 | #define	__HAVE_VM_PAGE_MD |
| 1160 | struct vm_page_md { |
| 1161 | 	struct pmap_page pp; |
| 1162 | #define	pvh_list	pp.pvh_list |
| 1163 | #define	pvh_attrs	pp.pvh_attrs |
| 1164 | #define	uro_mappings	pp.uro_mappings |
| 1165 | #define	urw_mappings	pp.urw_mappings |
| 1166 | #define	kro_mappings	pp.k_u.s_mappings[0] |
| 1167 | #define	krw_mappings	pp.k_u.s_mappings[1] |
| 1168 | #define	k_mappings	pp.k_u.i_mappings |
| 1169 | }; |
| 1170 | |
| 1171 | #define	PMAP_PAGE_TO_MD(ppage) container_of((ppage), struct vm_page_md, pp) |
| 1172 | |
| 1173 | /* |
| 1174 | * Set the default color of each page. |
| 1175 | */ |
| 1176 | #if ARM_MMU_V6 > 0 |
| 1177 | #define	VM_MDPAGE_PVH_ATTRS_INIT(pg) \ |
| 1178 | 	(pg)->mdpage.pvh_attrs = VM_PAGE_TO_PHYS(pg) & arm_cache_prefer_mask |
| 1179 | #else |
| 1180 | #define	VM_MDPAGE_PVH_ATTRS_INIT(pg) \ |
| 1181 | 	(pg)->mdpage.pvh_attrs = 0 |
| 1182 | #endif |
| 1183 | |
| 1184 | #define	VM_MDPAGE_INIT(pg)						\ |
| 1185 | do {									\ |
| 1186 | 	SLIST_INIT(&(pg)->mdpage.pvh_list);				\ |
| 1187 | 	VM_MDPAGE_PVH_ATTRS_INIT(pg);					\ |
| 1188 | 	(pg)->mdpage.uro_mappings = 0;					\ |
| 1189 | 	(pg)->mdpage.urw_mappings = 0;					\ |
| 1190 | 	(pg)->mdpage.k_mappings = 0;					\ |
| 1191 | } while (/*CONSTCOND*/0) |
| 1192 | |
| 1193 | #ifndef	__BSD_PTENTRY_T__ |
| 1194 | #define	__BSD_PTENTRY_T__ |
| 1195 | typedef uint32_t pt_entry_t; |
| 1196 | #define	PRIxPTE		PRIx32 |
| 1197 | #endif |
| 1198 | |
| 1199 | #endif /* !_LOCORE */ |
| 1200 | |
| 1201 | #endif /* _KERNEL */ |
| 1202 | |
| 1203 | #endif	/* _ARM32_PMAP_H_ */ |