| 1 | /*	$NetBSD: pmap.h,v 1.98 2024/03/23 18:48:31 andvar Exp $ */ |
| 2 | |
| 3 | /* |
| 4 | * Copyright (c) 1996 |
| 5 | * 	The President and Fellows of Harvard College. All rights reserved. |
| 6 | * Copyright (c) 1992, 1993 |
| 7 | *	The Regents of the University of California. All rights reserved. |
| 8 | * |
| 9 | * This software was developed by the Computer Systems Engineering group |
| 10 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and |
| 11 | * contributed to Berkeley. |
| 12 | * |
| 13 | * All advertising materials mentioning features or use of this software |
| 14 | * must display the following acknowledgement: |
| 15 | *	This product includes software developed by Aaron Brown and |
| 16 | *	Harvard University. |
| 17 | *	This product includes software developed by the University of |
| 18 | *	California, Lawrence Berkeley Laboratory. |
| 19 | * |
| 20 | * @InsertRedistribution@ |
| 21 | * 3. All advertising materials mentioning features or use of this software |
| 22 | * must display the following acknowledgement: |
| 23 | *	This product includes software developed by Aaron Brown and |
| 24 | *	Harvard University. |
| 25 | *	This product includes software developed by the University of |
| 26 | *	California, Berkeley and its contributors. |
| 27 | * 4. Neither the name of the University nor the names of its contributors |
| 28 | * may be used to endorse or promote products derived from this software |
| 29 | * without specific prior written permission. |
| 30 | * |
| 31 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 32 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 33 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 34 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 35 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 39 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 40 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 41 | * SUCH DAMAGE. |
| 42 | * |
| 43 | *	@(#)pmap.h	8.1 (Berkeley) 6/11/93 |
| 44 | */ |
| 45 | |
| 46 | #ifndef	_SPARC_PMAP_H_ |
| 47 | #define _SPARC_PMAP_H_ |
| 48 | |
| 49 | #if defined(_KERNEL_OPT) |
| 50 | #include "opt_sparc_arch.h" |
| 51 | #endif |
| 52 | |
| 53 | struct vm_page; |
| 54 | |
| 55 | #include <uvm/uvm_prot.h> |
| 56 | #include <uvm/uvm_pmap.h> |
| 57 | |
| 58 | #include <sparc/pte.h> |
| 59 | |
| 60 | /* |
| 61 | * Pmap structure. |
| 62 | * |
| 63 | * The pmap structure really comes in two variants, one---a single |
| 64 | * instance---for kernel virtual memory and the other---up to nproc |
| 65 | * instances---for user virtual memory. Unfortunately, we have to mash |
| 66 | * both into the same structure. Fortunately, they are almost the same. |
| 67 | * |
| 68 | * The kernel begins at 0xf8000000 and runs to 0xffffffff (although |
| 69 | * some of this is not actually used). Kernel space, including DVMA |
| 70 | * space (for now?), is mapped identically into all user contexts. |
| 71 | * There is no point in duplicating this mapping in each user process |
| 72 | * so they do not appear in the user structures. |
| 73 | * |
| 74 | * User space begins at 0x00000000 and runs through 0x1fffffff, |
| 75 | * then has a `hole', then resumes at 0xe0000000 and runs until it |
| 76 | * hits the kernel space at 0xf8000000. This can be mapped |
| 77 | * contiguously by ignoring the top two bits and pretending the |
| 78 | * space goes from 0 to 37ffffff. Typically the lower range is |
| 79 | * used for text+data and the upper for stack, but the code here |
| 80 | * makes no such distinction. |
| 81 | * |
| 82 | * Since each virtual segment covers 256 kbytes, the user space |
| 83 | * requires 3584 segments, while the kernel (including DVMA) requires |
| 84 | * only 512 segments. |
| 85 | * |
| 86 | * |
| 87 | ** FOR THE SUN4/SUN4C |
| 88 | * |
| 89 | * The segment map entry for virtual segment vseg is offset in |
| 90 | * pmap->pm_rsegmap by 0 if pmap is not the kernel pmap, or by |
| 91 | * NUSEG if it is. We keep a pointer called pmap->pm_segmap |
| 92 | * pre-offset by this value. pmap->pm_segmap thus contains the |
| 93 | * values to be loaded into the user portion of the hardware segment |
| 94 | * map so as to reach the proper PMEGs within the MMU. The kernel |
| 95 | * mappings are `set early' and are always valid in every context |
| 96 | * (every change is always propagated immediately). |
| 97 | * |
| 98 | * The PMEGs within the MMU are loaded `on demand'; when a PMEG is |
| 99 | * taken away from context `c', the pmap for context c has its |
| 100 | * corresponding pm_segmap[vseg] entry marked invalid (the MMU segment |
| 101 | * map entry is also made invalid at the same time). Thus |
| 102 | * pm_segmap[vseg] is the `invalid pmeg' number (127 or 511) whenever |
| 103 | * the corresponding PTEs are not actually in the MMU. On the other |
| 104 | * hand, pm_pte[vseg] is NULL only if no pages in that virtual segment |
| 105 | * are in core; otherwise it points to a copy of the 32 or 64 PTEs that |
| 106 | * must be loaded in the MMU in order to reach those pages. |
| 107 | * pm_npte[vseg] counts the number of valid pages in each vseg. |
| 108 | * |
| 109 | * XXX performance: faster to count valid bits? |
| 110 | * |
| 111 | * The kernel pmap cannot malloc() PTEs since malloc() will sometimes |
| 112 | * allocate a new virtual segment. Since kernel mappings are never |
| 113 | * `stolen' out of the MMU, we just keep all its PTEs there, and have |
| 114 | * no software copies. Its mmu entries are nonetheless kept on lists |
| 115 | * so that the code that fiddles with mmu lists has something to fiddle. |
| 116 | * |
| 117 | ** FOR THE SUN4M/SUN4D |
| 118 | * |
| 119 | * On this architecture, the virtual-to-physical translation (page) tables |
| 120 | * are *not* stored within the MMU as they are in the earlier Sun architect- |
| 121 | * ures; instead, they are maintained entirely within physical memory (there |
| 122 | * is a TLB cache to prevent the high performance hit from keeping all page |
| 123 | * tables in core). Thus there is no need to dynamically allocate PMEGs or |
| 124 | * SMEGs; only contexts must be shared. |
| 125 | * |
| 126 | * We maintain two parallel sets of tables: one is the actual MMU-edible |
| 127 | * hierarchy of page tables in allocated kernel memory; these tables refer |
| 128 | * to each other by physical address pointers in SRMMU format (thus they |
| 129 | * are not very useful to the kernel's management routines). The other set |
| 130 | * of tables is similar to those used for the Sun4/100's 3-level MMU; it |
| 131 | * is a hierarchy of regmap and segmap structures which contain kernel virtual |
| 132 | * pointers to each other. These must (unfortunately) be kept in sync. |
| 133 | * |
| 134 | */ |
| 135 | #define NKREG	((int)((-(unsigned)KERNBASE) / NBPRG))	/* i.e., 8 */ |
| 136 | #define NUREG	(256 - NKREG)				/* i.e., 248 */ |
| 137 | |
| 138 | TAILQ_HEAD(mmuhd,mmuentry); |
| 139 | |
| 140 | /* |
| 141 | * data appearing in both user and kernel pmaps |
| 142 | * |
| 143 | * note: if we want the same binaries to work on the 4/4c and 4m, we have to |
| 144 | * include the fields for both to make sure that the struct kproc |
| 145 | * 	 is the same size. |
| 146 | */ |
| 147 | struct pmap { |
| 148 | 	union	ctxinfo *pm_ctx;	/* current context, if any */ |
| 149 | 	int	pm_ctxnum;		/* current context's number */ |
| 150 | 	u_int	pm_cpuset;		/* CPU's this pmap has context on */ |
| 151 | 	int	pm_refcount;		/* just what it says */ |
| 152 | |
| 153 | 	struct mmuhd	pm_reglist;	/* MMU regions on this pmap (4/4c) */ |
| 154 | 	struct mmuhd	pm_seglist;	/* MMU segments on this pmap (4/4c) */ |
| 155 | |
| 156 | 	struct regmap	*pm_regmap; |
| 157 | |
| 158 | 	int		**pm_reg_ptps;	/* SRMMU-edible region tables for 4m */ |
| 159 | 	int		*pm_reg_ptps_pa;/* _Physical_ address of pm_reg_ptps */ |
| 160 | |
| 161 | 	int		pm_gap_start;	/* Starting with this vreg there's */ |
| 162 | 	int		pm_gap_end;	/* no valid mapping until here */ |
| 163 | |
| 164 | 	struct pmap_statistics	pm_stats;	/* pmap statistics */ |
| 165 | 	u_int		pm_flags; |
| 166 | #define PMAP_USERCACHECLEAN	1 |
| 167 | }; |
| 168 | |
| 169 | struct regmap { |
| 170 | 	struct segmap	*rg_segmap;	/* point to NSGPRG PMEGs */ |
| 171 | 	int		*rg_seg_ptps; 	/* SRMMU-edible segment tables (NULL |
| 172 | 					 * indicates invalid region (4m) */ |
| 173 | 	smeg_t		rg_smeg;	/* the MMU region number (4c) */ |
| 174 | 	u_char		rg_nsegmap;	/* number of valid PMEGS */ |
| 175 | }; |
| 176 | |
| 177 | struct segmap { |
| 178 | 	uint64_t sg_wiremap;		/* per-page wire bits (4m) */ |
| 179 | 	int	*sg_pte;		/* points to NPTESG PTEs */ |
| 180 | 	pmeg_t	sg_pmeg;		/* the MMU segment number (4c) */ |
| 181 | 	u_char	sg_npte;		/* number of valid PTEs in sg_pte |
| 182 | 					 * (not used for 4m/4d kernel_map) */ |
| 183 | 	int8_t	sg_nwired;		/* number of wired pages */ |
| 184 | }; |
| 185 | |
| 186 | #ifdef _KERNEL |
| 187 | |
| 188 | #define PMAP_NULL	((pmap_t)0) |
| 189 | |
| 190 | /* Mostly private data exported for a few key consumers. */ |
| 191 | struct memarr; |
| 192 | extern struct memarr *pmemarr; |
| 193 | extern int npmemarr; |
| 194 | extern vaddr_t prom_vstart; |
| 195 | extern vaddr_t prom_vend; |
| 196 | |
| 197 | /* |
| 198 | * Bounds on managed physical addresses. Used by (MD) users |
| 199 | * of uvm_pglistalloc() to provide search hints. |
| 200 | */ |
| 201 | extern paddr_t		vm_first_phys, vm_last_phys; |
| 202 | extern psize_t		vm_num_phys; |
| 203 | |
| 204 | /* |
| 205 | * Since PTEs also contain type bits, we have to have some way |
| 206 | * to tell pmap_enter `this is an IO page' or `this is not to |
| 207 | * be cached'. Since physical addresses are always aligned, we |
| 208 | * can do this with the low order bits. |
| 209 | * |
| 210 | * The ordering below is important: PMAP_PGTYPE << PG_TNC must give |
| 211 | * exactly the PG_NC and PG_TYPE bits. |
| 212 | */ |
| 213 | #define	PMAP_OBIO	1		/* tells pmap_enter to use PG_OBIO */ |
| 214 | #define	PMAP_VME16	2		/* etc */ |
| 215 | #define	PMAP_VME32	3		/* etc */ |
| 216 | #define	PMAP_NC		4		/* tells pmap_enter to set PG_NC */ |
| 217 | #define	PMAP_TNC_4	7		/* mask to get PG_TYPE & PG_NC */ |
| 218 | |
| 219 | #define	PMAP_T2PTE_4(x)		(((x) & PMAP_TNC_4) << PG_TNC_SHIFT) |
| 220 | #define	PMAP_IOENC_4(io)	(io) |
| 221 | |
| 222 | /* |
| 223 | * On a SRMMU machine, the iospace is encoded in bits [3-6] of the |
| 224 | * physical address passed to pmap_enter(). |
| 225 | */ |
| 226 | #define PMAP_TYPE_SRMMU		0x78	/* mask to get 4m page type */ |
| 227 | #define PMAP_PTESHFT_SRMMU	25	/* right shift to put type in pte */ |
| 228 | #define PMAP_SHFT_SRMMU		3	/* left shift to extract iospace */ |
| 229 | #define	PMAP_TNC_SRMMU		127	/* mask to get PG_TYPE & PG_NC */ |
| 230 | |
| 231 | /*#define PMAP_IOC 0x00800000 -* IO cacheable, NOT shifted */ |
| 232 | |
| 233 | #define PMAP_T2PTE_SRMMU(x)	(((x) & PMAP_TYPE_SRMMU) << PMAP_PTESHFT_SRMMU) |
| 234 | #define PMAP_IOENC_SRMMU(io)	((io) << PMAP_SHFT_SRMMU) |
| 235 | |
| 236 | /* Encode IO space for pmap_enter() */ |
| 237 | #define PMAP_IOENC(io)	(CPU_HAS_SRMMU ? PMAP_IOENC_SRMMU(io) \ |
| 238 | 				 : PMAP_IOENC_4(io)) |
| 239 | |
| 240 | int	pmap_dumpsize(void); |
| 241 | int	pmap_dumpmmu(int (*)(dev_t, daddr_t, void *, size_t), daddr_t); |
| 242 | |
| 243 | #define	pmap_resident_count(pm)	((pm)->pm_stats.resident_count) |
| 244 | #define	pmap_wired_count(pm)	((pm)->pm_stats.wired_count) |
| 245 | |
| 246 | #define PMAP_PREFER(fo, ap, sz, td)	pmap_prefer((fo), (ap), (sz), (td)) |
| 247 | |
| 248 | #define PMAP_EXCLUDE_DECLS	/* tells MI pmap.h *not* to include decls */ |
| 249 | |
| 250 | /* FUNCTION DECLARATIONS FOR COMMON PMAP MODULE */ |
| 251 | |
| 252 | void		pmap_activate(struct lwp *); |
| 253 | void		pmap_deactivate(struct lwp *); |
| 254 | void		pmap_bootstrap(int nmmu, int nctx, int nregion); |
| 255 | void		pmap_prefer(vaddr_t, vaddr_t *, size_t, int); |
| 256 | int		pmap_pa_exists(paddr_t); |
| 257 | void		pmap_unwire(pmap_t, vaddr_t); |
| 258 | void		pmap_copy(pmap_t, pmap_t, vaddr_t, vsize_t, vaddr_t); |
| 259 | pmap_t		pmap_create(void); |
| 260 | void		pmap_destroy(pmap_t); |
| 261 | void		pmap_init(void); |
| 262 | vaddr_t		pmap_map(vaddr_t, paddr_t, paddr_t, int); |
| 263 | #define		pmap_phys_address(x) (x) |
| 264 | void		pmap_reference(pmap_t); |
| 265 | void		pmap_remove(pmap_t, vaddr_t, vaddr_t); |
| 266 | #define		pmap_update(pmap)		__USE(pmap) |
| 267 | void		pmap_virtual_space(vaddr_t *, vaddr_t *); |
| 268 | #ifdef PMAP_GROWKERNEL |
| 269 | vaddr_t		pmap_growkernel(vaddr_t); |
| 270 | #endif |
| 271 | void		pmap_redzone(void); |
| 272 | void		kvm_uncache(char *, int); |
| 273 | int		mmu_pagein(struct pmap *pm, vaddr_t, int); |
| 274 | void		pmap_writetext(unsigned char *, int); |
| 275 | void		pmap_globalize_boot_cpuinfo(struct cpu_info *); |
| 276 | bool		pmap_remove_all(struct pmap *pm); |
| 277 | #define 	pmap_mmap_flags(x)	0	/* dummy so far */ |
| 278 | |
| 279 | /* SUN4/SUN4C SPECIFIC DECLARATIONS */ |
| 280 | |
| 281 | #if defined(SUN4) || defined(SUN4C) |
| 282 | bool		pmap_clear_modify4_4c(struct vm_page *); |
| 283 | bool		pmap_clear_reference4_4c(struct vm_page *); |
| 284 | void		pmap_copy_page4_4c(paddr_t, paddr_t); |
| 285 | int		pmap_enter4_4c(pmap_t, vaddr_t, paddr_t, vm_prot_t, u_int); |
| 286 | bool		pmap_extract4_4c(pmap_t, vaddr_t, paddr_t *); |
| 287 | bool		pmap_is_modified4_4c(struct vm_page *); |
| 288 | bool		pmap_is_referenced4_4c(struct vm_page *); |
| 289 | void		pmap_kenter_pa4_4c(vaddr_t, paddr_t, vm_prot_t, u_int); |
| 290 | void		pmap_kremove4_4c(vaddr_t, vsize_t); |
| 291 | void		pmap_kprotect4_4c(vaddr_t, vsize_t, vm_prot_t); |
| 292 | void		pmap_page_protect4_4c(struct vm_page *, vm_prot_t); |
| 293 | void		pmap_protect4_4c(pmap_t, vaddr_t, vaddr_t, vm_prot_t); |
| 294 | void		pmap_zero_page4_4c(paddr_t); |
| 295 | #endif /* defined SUN4 || defined SUN4C */ |
| 296 | |
| 297 | /* SIMILAR DECLARATIONS FOR SUN4M/SUN4D MODULE */ |
| 298 | |
| 299 | #if defined(SUN4M) || defined(SUN4D) |
| 300 | bool		pmap_clear_modify4m(struct vm_page *); |
| 301 | bool		pmap_clear_reference4m(struct vm_page *); |
| 302 | void		pmap_copy_page4m(paddr_t, paddr_t); |
| 303 | void		pmap_copy_page_viking_mxcc(paddr_t, paddr_t); |
| 304 | void		pmap_copy_page_hypersparc(paddr_t, paddr_t); |
| 305 | int		pmap_enter4m(pmap_t, vaddr_t, paddr_t, vm_prot_t, u_int); |
| 306 | bool		pmap_extract4m(pmap_t, vaddr_t, paddr_t *); |
| 307 | bool		pmap_is_modified4m(struct vm_page *); |
| 308 | bool		pmap_is_referenced4m(struct vm_page *); |
| 309 | void		pmap_kenter_pa4m(vaddr_t, paddr_t, vm_prot_t, u_int); |
| 310 | void		pmap_kremove4m(vaddr_t, vsize_t); |
| 311 | void		pmap_kprotect4m(vaddr_t, vsize_t, vm_prot_t); |
| 312 | void		pmap_page_protect4m(struct vm_page *, vm_prot_t); |
| 313 | void		pmap_protect4m(pmap_t, vaddr_t, vaddr_t, vm_prot_t); |
| 314 | void		pmap_zero_page4m(paddr_t); |
| 315 | void		pmap_zero_page_viking_mxcc(paddr_t); |
| 316 | void		pmap_zero_page_hypersparc(paddr_t); |
| 317 | #endif /* defined SUN4M || defined SUN4D */ |
| 318 | |
| 319 | #if !(defined(SUN4M) || defined(SUN4D)) && (defined(SUN4) || defined(SUN4C)) |
| 320 | |
| 321 | #define		pmap_clear_modify	pmap_clear_modify4_4c |
| 322 | #define		pmap_clear_reference	pmap_clear_reference4_4c |
| 323 | #define		pmap_enter		pmap_enter4_4c |
| 324 | #define		pmap_extract		pmap_extract4_4c |
| 325 | #define		pmap_is_modified	pmap_is_modified4_4c |
| 326 | #define		pmap_is_referenced	pmap_is_referenced4_4c |
| 327 | #define		pmap_kenter_pa		pmap_kenter_pa4_4c |
| 328 | #define		pmap_kremove		pmap_kremove4_4c |
| 329 | #define		pmap_kprotect		pmap_kprotect4_4c |
| 330 | #define		pmap_page_protect	pmap_page_protect4_4c |
| 331 | #define		pmap_protect		pmap_protect4_4c |
| 332 | |
| 333 | #elif (defined(SUN4M) || defined(SUN4D)) && !(defined(SUN4) || defined(SUN4C)) |
| 334 | |
| 335 | #define		pmap_clear_modify	pmap_clear_modify4m |
| 336 | #define		pmap_clear_reference	pmap_clear_reference4m |
| 337 | #define		pmap_enter		pmap_enter4m |
| 338 | #define		pmap_extract		pmap_extract4m |
| 339 | #define		pmap_is_modified	pmap_is_modified4m |
| 340 | #define		pmap_is_referenced	pmap_is_referenced4m |
| 341 | #define		pmap_kenter_pa		pmap_kenter_pa4m |
| 342 | #define		pmap_kremove		pmap_kremove4m |
| 343 | #define		pmap_kprotect		pmap_kprotect4m |
| 344 | #define		pmap_page_protect	pmap_page_protect4m |
| 345 | #define		pmap_protect		pmap_protect4m |
| 346 | |
| 347 | #else /* must use function pointers */ |
| 348 | |
| 349 | extern bool	(*pmap_clear_modify_p)(struct vm_page *); |
| 350 | extern bool	(*pmap_clear_reference_p)(struct vm_page *); |
| 351 | extern int	(*pmap_enter_p)(pmap_t, vaddr_t, paddr_t, vm_prot_t, u_int); |
| 352 | extern bool	 (*pmap_extract_p)(pmap_t, vaddr_t, paddr_t *); |
| 353 | extern bool	(*pmap_is_modified_p)(struct vm_page *); |
| 354 | extern bool	(*pmap_is_referenced_p)(struct vm_page *); |
| 355 | extern void	(*pmap_kenter_pa_p)(vaddr_t, paddr_t, vm_prot_t, u_int); |
| 356 | extern void	(*pmap_kremove_p)(vaddr_t, vsize_t); |
| 357 | extern void	(*pmap_kprotect_p)(vaddr_t, vsize_t, vm_prot_t); |
| 358 | extern void	(*pmap_page_protect_p)(struct vm_page *, vm_prot_t); |
| 359 | extern void	(*pmap_protect_p)(pmap_t, vaddr_t, vaddr_t, vm_prot_t); |
| 360 | |
| 361 | #define		pmap_clear_modify	(*pmap_clear_modify_p) |
| 362 | #define		pmap_clear_reference	(*pmap_clear_reference_p) |
| 363 | #define		pmap_enter		(*pmap_enter_p) |
| 364 | #define		pmap_extract		(*pmap_extract_p) |
| 365 | #define		pmap_is_modified	(*pmap_is_modified_p) |
| 366 | #define		pmap_is_referenced	(*pmap_is_referenced_p) |
| 367 | #define		pmap_kenter_pa		(*pmap_kenter_pa_p) |
| 368 | #define		pmap_kremove		(*pmap_kremove_p) |
| 369 | #define		pmap_kprotect		(*pmap_kprotect_p) |
| 370 | #define		pmap_page_protect	(*pmap_page_protect_p) |
| 371 | #define		pmap_protect		(*pmap_protect_p) |
| 372 | |
| 373 | #endif |
| 374 | |
| 375 | /* pmap_{zero,copy}_page() may be assisted by specialized hardware */ |
| 376 | #define		pmap_zero_page		(*cpuinfo.zero_page) |
| 377 | #define		pmap_copy_page		(*cpuinfo.copy_page) |
| 378 | |
| 379 | #if defined(SUN4M) || defined(SUN4D) |
| 380 | /* |
| 381 | * Macros which implement SRMMU TLB flushing/invalidation |
| 382 | */ |
| 383 | #define tlb_flush_page_real(va) \ |
| 384 | 	sta(((vaddr_t)(va) & 0xfffff000) | ASI_SRMMUFP_L3, ASI_SRMMUFP, 0) |
| 385 | |
| 386 | #define tlb_flush_segment_real(va) \ |
| 387 | 	sta(((vaddr_t)(va) & 0xfffc0000) | ASI_SRMMUFP_L2, ASI_SRMMUFP, 0) |
| 388 | |
| 389 | #define tlb_flush_region_real(va) \ |
| 390 | 	sta(((vaddr_t)(va) & 0xff000000) | ASI_SRMMUFP_L1, ASI_SRMMUFP, 0) |
| 391 | |
| 392 | #define tlb_flush_context_real()	sta(ASI_SRMMUFP_L0, ASI_SRMMUFP, 0) |
| 393 | #define tlb_flush_all_real()		sta(ASI_SRMMUFP_LN, ASI_SRMMUFP, 0) |
| 394 | |
| 395 | void setpte4m(vaddr_t va, int pte); |
| 396 | |
| 397 | #endif /* SUN4M || SUN4D */ |
| 398 | |
| 399 | #define __HAVE_VM_PAGE_MD |
| 400 | |
| 401 | /* |
| 402 | * For each managed physical page, there is a list of all currently |
| 403 | * valid virtual mappings of that page. Since there is usually one |
| 404 | * (or zero) mapping per page, the table begins with an initial entry, |
| 405 | * rather than a pointer; this head entry is empty iff its pv_pmap |
| 406 | * field is NULL. |
| 407 | */ |
| 408 | struct vm_page_md { |
| 409 | 	struct pvlist { |
| 410 | 		struct	pvlist *pv_next;	/* next pvlist, if any */ |
| 411 | 		struct	pmap *pv_pmap;		/* pmap of this va */ |
| 412 | 		vaddr_t	pv_va;			/* virtual address */ |
| 413 | 		int	pv_flags;		/* flags (below) */ |
| 414 | 	} pvlisthead; |
| 415 | }; |
| 416 | #define VM_MDPAGE_PVHEAD(pg)	(&(pg)->mdpage.pvlisthead) |
| 417 | |
| 418 | #define VM_MDPAGE_INIT(pg) do {				\ |
| 419 | 	(pg)->mdpage.pvlisthead.pv_next = NULL;		\ |
| 420 | 	(pg)->mdpage.pvlisthead.pv_pmap = NULL;		\ |
| 421 | 	(pg)->mdpage.pvlisthead.pv_va = 0;		\ |
| 422 | 	(pg)->mdpage.pvlisthead.pv_flags = 0;		\ |
| 423 | } while(/*CONSTCOND*/0) |
| 424 | |
| 425 | #endif /* _KERNEL */ |
| 426 | |
| 427 | #endif /* _SPARC_PMAP_H_ */ |