Home | History | Annotate | Line # | Download | only in include
      1 /*	$NetBSD: pte.h,v 1.29 2026/05/21 12:10:28 skrll Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /*
     34  * Copyright 1996 The Board of Trustees of The Leland Stanford
     35  * Junior University. All Rights Reserved.
     36  *
     37  * Permission to use, copy, modify, and distribute this
     38  * software and its documentation for any purpose and without
     39  * fee is hereby granted, provided that the above copyright
     40  * notice appear in all copies.  Stanford University
     41  * makes no representations about the suitability of this
     42  * software for any purpose.  It is provided "as is" without
     43  * express or implied warranty.
     44  */
     45 
     46 #ifndef  __MIPS_PTE_H__
     47 #define	 __MIPS_PTE_H__
     48 
     49 #include <mips/mips1_pte.h>
     50 #include <mips/mips3_pte.h>
     51 
     52 #define	PG_ASID	0x000000ff	/* Address space ID */
     53 
     54 #ifndef _LOCORE
     55 #ifndef __BSD_PTENTRY_T__
     56 #define	__BSD_PTENTRY_T__
     57 typedef uint32_t pt_entry_t;
     58 #define	PRIxPTE		PRIx32
     59 #endif
     60 
     61 /*
     62  * Macros/inline functions to hide PTE format differences.
     63  */
     64 
     65 #define	mips_pg_nv_bit()	(MIPS1_PG_NV)	/* same on mips1 and mips3 */
     66 
     67 
     68 bool pmap_is_page_ro_p(struct pmap *pmap, vaddr_t, uint32_t);
     69 
     70 
     71 /* MIPS1-only */
     72 #if defined(MIPS1) && !defined(MIPS3_PLUS)
     73 #define	mips_pg_v(entry)	((entry) & MIPS1_PG_V)
     74 #define	mips_pg_wired(entry)	((entry) & MIPS1_PG_WIRED)
     75 
     76 #define	mips_pg_m_bit()		(MIPS1_PG_D)
     77 #define	mips_pg_rw_bit()	(MIPS1_PG_RW)	/* no RW bits for mips1 */
     78 #define	mips_pg_ro_bit()	(MIPS1_PG_RO)
     79 #define	mips_pg_ropage_bit()	(MIPS1_PG_RO)	/* XXX not MIPS1_PG_ROPAGE? */
     80 #define	mips_pg_rwpage_bit()	(MIPS1_PG_RWPAGE)
     81 #define	mips_pg_rwncpage_bit()	(MIPS1_PG_RWNCPAGE)
     82 #define	mips_pg_cwpage_bit()	(MIPS1_PG_CWPAGE)
     83 #define	mips_pg_cwncpage_bit()	(MIPS1_PG_CWNCPAGE)
     84 #define	mips_pg_global_bit()	(MIPS1_PG_G)
     85 #define	mips_pg_wired_bit()	(MIPS1_PG_WIRED)
     86 
     87 #define	pte_to_paddr(pte)	MIPS1_PTE_TO_PADDR((pte))
     88 #define	PAGE_IS_RDONLY(pte, va)	MIPS1_PAGE_IS_RDONLY((pte), (va))
     89 
     90 #define	mips_tlbpfn_to_paddr(x)		mips1_tlbpfn_to_paddr((vaddr_t)(x))
     91 #define	mips_paddr_to_tlbpfn(x)		mips1_paddr_to_tlbpfn((x))
     92 #endif /* mips1 */
     93 
     94 
     95 /* MIPS3 (or greater) only */
     96 #if !defined(MIPS1) && defined(MIPS3_PLUS)
     97 #define	mips_pg_v(entry)	((entry) & MIPS3_PG_V)
     98 #define	mips_pg_wired(entry)	((entry) & MIPS3_PG_WIRED)
     99 
    100 #define	mips_pg_m_bit()		(MIPS3_PG_D)
    101 #define	mips_pg_rw_bit()	(MIPS3_PG_D)
    102 #define	mips_pg_ro_bit()	(MIPS3_PG_RO)
    103 #define	mips_pg_ropage_bit()	(MIPS3_PG_ROPAGE)
    104 #define	mips_pg_rwpage_bit()	(MIPS3_PG_RWPAGE)
    105 #define	mips_pg_rwncpage_bit()	(MIPS3_PG_RWNCPAGE)
    106 #define	mips_pg_cwpage_bit()	(MIPS3_PG_CWPAGE)
    107 #define	mips_pg_cwncpage_bit()	(MIPS3_PG_CWNCPAGE)
    108 #define	mips_pg_global_bit()	(MIPS3_PG_G)
    109 #define	mips_pg_wired_bit()	(MIPS3_PG_WIRED)
    110 
    111 #define	pte_to_paddr(pte)	MIPS3_PTE_TO_PADDR((pte))
    112 #define	PAGE_IS_RDONLY(pte, va)	MIPS3_PAGE_IS_RDONLY((pte), (va))
    113 
    114 #define	mips_tlbpfn_to_paddr(x)		mips3_tlbpfn_to_paddr((vaddr_t)(x))
    115 #define	mips_paddr_to_tlbpfn(x)		mips3_paddr_to_tlbpfn((x))
    116 #endif /* mips3 */
    117 
    118 /* MIPS1 and MIPS3 (or greater) */
    119 #if defined(MIPS1) && defined(MIPS3_PLUS)
    120 
    121 static __inline bool
    122     mips_pg_v(uint32_t entry),
    123     mips_pg_wired(uint32_t entry),
    124     PAGE_IS_RDONLY(uint32_t pte, vaddr_t va);
    125 
    126 static __inline uint32_t
    127     mips_pg_wired_bit(void) __pure,
    128     mips_pg_m_bit(void) __pure,
    129     mips_pg_ro_bit(void) __pure,
    130     mips_pg_rw_bit(void) __pure,
    131     mips_pg_ropage_bit(void) __pure,
    132     mips_pg_cwpage_bit(void) __pure,
    133     mips_pg_rwpage_bit(void) __pure,
    134     mips_pg_global_bit(void) __pure;
    135 static __inline paddr_t pte_to_paddr(pt_entry_t pte) __pure;
    136 static __inline bool PAGE_IS_RDONLY(uint32_t pte, vaddr_t va) __pure;
    137 
    138 static __inline paddr_t mips_tlbpfn_to_paddr(uint32_t pfn) __pure;
    139 static __inline uint32_t mips_paddr_to_tlbpfn(paddr_t pa) __pure;
    140 
    141 
    142 static __inline bool
    143 mips_pg_v(uint32_t entry)
    144 {
    145 	if (MIPS_HAS_R4K_MMU)
    146 		return (entry & MIPS3_PG_V) != 0;
    147 	return (entry & MIPS1_PG_V) != 0;
    148 }
    149 
    150 static __inline bool
    151 mips_pg_wired(uint32_t entry)
    152 {
    153 	if (MIPS_HAS_R4K_MMU)
    154 		return (entry & MIPS3_PG_WIRED) != 0;
    155 	return (entry & MIPS1_PG_WIRED) != 0;
    156 }
    157 
    158 static __inline uint32_t
    159 mips_pg_m_bit(void)
    160 {
    161 	if (MIPS_HAS_R4K_MMU)
    162 		return (MIPS3_PG_D);
    163 	return (MIPS1_PG_D);
    164 }
    165 
    166 static __inline unsigned int
    167 mips_pg_ro_bit(void)
    168 {
    169 	if (MIPS_HAS_R4K_MMU)
    170 		return (MIPS3_PG_RO);
    171 	return (MIPS1_PG_RO);
    172 }
    173 
    174 static __inline unsigned int
    175 mips_pg_rw_bit(void)
    176 {
    177 	if (MIPS_HAS_R4K_MMU)
    178 		return (MIPS3_PG_D);
    179 	return (MIPS1_PG_RW);
    180 }
    181 
    182 static __inline unsigned int
    183 mips_pg_ropage_bit(void)
    184 {
    185 	if (MIPS_HAS_R4K_MMU)
    186 		return (MIPS3_PG_ROPAGE);
    187 	return (MIPS1_PG_RO);
    188 }
    189 
    190 static __inline unsigned int
    191 mips_pg_rwpage_bit(void)
    192 {
    193 	if (MIPS_HAS_R4K_MMU)
    194 		return (MIPS3_PG_RWPAGE);
    195 	return (MIPS1_PG_RWPAGE);
    196 }
    197 
    198 static __inline unsigned int
    199 mips_pg_cwpage_bit(void)
    200 {
    201 	if (MIPS_HAS_R4K_MMU)
    202 		return (MIPS3_PG_CWPAGE);
    203 	return (MIPS1_PG_CWPAGE);
    204 }
    205 
    206 
    207 static __inline unsigned int
    208 mips_pg_global_bit(void)
    209 {
    210 	if (MIPS_HAS_R4K_MMU)
    211 		return (MIPS3_PG_G);
    212 	return (MIPS1_PG_G);
    213 }
    214 
    215 static __inline unsigned int
    216 mips_pg_wired_bit(void)
    217 {
    218 	if (MIPS_HAS_R4K_MMU)
    219 		return (MIPS3_PG_WIRED);
    220 	return (MIPS1_PG_WIRED);
    221 }
    222 
    223 static __inline paddr_t
    224 pte_to_paddr(pt_entry_t pte)
    225 {
    226 	if (MIPS_HAS_R4K_MMU)
    227 		return (MIPS3_PTE_TO_PADDR(pte));
    228 	return (MIPS1_PTE_TO_PADDR(pte));
    229 }
    230 
    231 static __inline bool
    232 PAGE_IS_RDONLY(uint32_t pte, vaddr_t va)
    233 {
    234 	if (MIPS_HAS_R4K_MMU)
    235 		return (MIPS3_PAGE_IS_RDONLY(pte, va));
    236 	return (MIPS1_PAGE_IS_RDONLY(pte, va));
    237 }
    238 
    239 static __inline paddr_t
    240 mips_tlbpfn_to_paddr(uint32_t pfn)
    241 {
    242 	if (MIPS_HAS_R4K_MMU)
    243 		return (mips3_tlbpfn_to_paddr(pfn));
    244 	return (mips1_tlbpfn_to_paddr(pfn));
    245 }
    246 
    247 static __inline uint32_t
    248 mips_paddr_to_tlbpfn(paddr_t pa)
    249 {
    250 	if (MIPS_HAS_R4K_MMU)
    251 		return (mips3_paddr_to_tlbpfn(pa));
    252 	return (mips1_paddr_to_tlbpfn(pa));
    253 }
    254 #endif
    255 
    256 #endif /* ! _LOCORE */
    257 
    258 #if defined(_KERNEL) && !defined(_LOCORE)
    259 #define	MIPS_MMU(X)	(MIPS_HAS_R4K_MMU ? MIPS3_##X : MIPS1_##X)
    260 static inline bool
    261 pte_valid_p(pt_entry_t pte)
    262 {
    263 	return (pte & MIPS_MMU(PG_V)) != 0;
    264 }
    265 
    266 static inline bool
    267 pte_modified_p(pt_entry_t pte)
    268 {
    269 	return (pte & MIPS_MMU(PG_D)) != 0;
    270 }
    271 
    272 static inline bool
    273 pte_referenced_p(pt_entry_t pte)
    274 {
    275 	return false;
    276 }
    277 
    278 static inline bool
    279 pte_global_p(pt_entry_t pte)
    280 {
    281 	return (pte & MIPS_MMU(PG_G)) != 0;
    282 }
    283 
    284 static inline bool
    285 pte_wired_p(pt_entry_t pte)
    286 {
    287 	return (pte & MIPS_MMU(PG_WIRED)) != 0;
    288 }
    289 
    290 static inline pt_entry_t
    291 pte_wire_entry(pt_entry_t pte)
    292 {
    293 	return pte | MIPS_MMU(PG_WIRED);
    294 }
    295 
    296 static inline pt_entry_t
    297 pte_unwire_entry(pt_entry_t pte)
    298 {
    299 	return pte & ~MIPS_MMU(PG_WIRED);
    300 }
    301 
    302 static inline uint32_t
    303 pte_value(pt_entry_t pte)
    304 {
    305 	return pte;
    306 }
    307 
    308 static inline bool
    309 pte_readonly_p(pt_entry_t pte)
    310 {
    311 	return (pte & MIPS_MMU(PG_RO)) != 0;
    312 }
    313 
    314 static inline bool
    315 pte_cached_p(pt_entry_t pte)
    316 {
    317 	if (MIPS_HAS_R4K_MMU) {
    318 		return MIPS3_PG_TO_CCA(pte) == MIPS3_PG_TO_CCA(mips_options.mips3_pg_cached);
    319 	} else {
    320 		return (pte & MIPS1_PG_N) == 0;
    321 	}
    322 }
    323 
    324 static inline bool
    325 pte_deferred_exec_p(pt_entry_t pte)
    326 {
    327 	return false;
    328 }
    329 
    330 static inline pt_entry_t
    331 pte_nv_entry(bool kernel_p)
    332 {
    333 	__CTASSERT(MIPS1_PG_NV == MIPS3_PG_NV);
    334 	__CTASSERT(MIPS1_PG_NV == 0);
    335 	return (kernel_p && MIPS_HAS_R4K_MMU) ? MIPS3_PG_G : 0;
    336 }
    337 
    338 static inline pt_entry_t
    339 pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot)
    340 {
    341 	const uint32_t ro_bit = MIPS_MMU(PG_RO);
    342 	const uint32_t rw_bit = MIPS_MMU(PG_D);
    343 
    344 	return (pte & ~(ro_bit|rw_bit))
    345 	    | ((prot & VM_PROT_WRITE) ? rw_bit : ro_bit);
    346 }
    347 
    348 static inline pt_entry_t
    349 pte_clear_modify(pt_entry_t pte)
    350 {
    351 	return pte & ~MIPS_MMU(PG_D);
    352 }
    353 
    354 static inline pt_entry_t
    355 pte_clear_reference(pt_entry_t pte)
    356 {
    357 	return pte;
    358 }
    359 
    360 static inline pt_entry_t
    361 pte_cached_change(pt_entry_t pte, bool cached)
    362 {
    363 	if (MIPS_HAS_R4K_MMU) {
    364 		pte &= ~MIPS3_PG_CACHEMODE;
    365 		pte |= (cached ? MIPS3_PG_CACHED : MIPS3_PG_UNCACHED);
    366 	}
    367 	return pte;
    368 }
    369 
    370 static inline void
    371 pte_set(pt_entry_t *ptep, pt_entry_t pte)
    372 {
    373 	*ptep = pte;
    374 }
    375 
    376 #ifdef __PMAP_PRIVATE
    377 struct vm_page_md;
    378 
    379 static inline pt_entry_t
    380 pte_make_kenter_pa(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
    381     u_int flags)
    382 {
    383 	pt_entry_t pte;
    384 	if (MIPS_HAS_R4K_MMU) {
    385 		pte = mips3_paddr_to_tlbpfn(pa)
    386 		    | ((prot & VM_PROT_WRITE) ? MIPS3_PG_D : MIPS3_PG_RO)
    387 		    | ((flags & PMAP_NOCACHE) ? MIPS3_PG_UNCACHED : MIPS3_PG_CACHED)
    388 		    | MIPS3_PG_WIRED | MIPS3_PG_V | MIPS3_PG_G;
    389 	} else {
    390 		pte = mips1_paddr_to_tlbpfn(pa)
    391 		    | ((prot & VM_PROT_WRITE) ? MIPS1_PG_D : MIPS1_PG_RO)
    392 		    | ((flags & PMAP_NOCACHE) ? MIPS1_PG_N : 0)
    393 		    | MIPS1_PG_WIRED | MIPS1_PG_V | MIPS1_PG_G;
    394 	}
    395 	return pte;
    396 }
    397 
    398 static inline pt_entry_t
    399 pte_make_enter(paddr_t pa, const struct vm_page_md *mdpg, vm_prot_t prot,
    400     u_int flags, bool is_kernel_pmap_p)
    401 {
    402 	pt_entry_t pte;
    403 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    404 	const bool cached = (flags & PMAP_NOCACHE) == 0
    405 	    && (pa & PGC_NOCACHE) == 0;
    406 	const bool prefetch = (pa & PGC_PREFETCH) != 0;
    407 
    408 	pa &= ~(PGC_NOCACHE|PGC_PREFETCH);
    409 #endif
    410 
    411 #if defined(cobalt) || defined(newsmips) || defined(pmax) /* otherwise ok */
    412 	/* this is not error in general. */
    413 	KASSERTMSG((pa & 0x80000000) == 0, "%#"PRIxPADDR, pa);
    414 #endif
    415 
    416 	if (mdpg != NULL) {
    417 		if ((prot & VM_PROT_WRITE) == 0) {
    418 			/*
    419 			 * If page is not yet referenced, we could emulate this
    420 			 * by not setting the page valid, and setting the
    421 			 * referenced status in the TLB fault handler, similar
    422 			 * to how page modified status is done for UTLBmod
    423 			 * exceptions.
    424 			 */
    425 			pte = mips_pg_ropage_bit();
    426 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    427 		} else if (cached == false) {
    428 			if (VM_PAGEMD_MODIFIED_P(mdpg)) {
    429 				pte = mips_pg_rwncpage_bit();
    430 			} else {
    431 				pte = mips_pg_cwncpage_bit();
    432 			}
    433 #endif
    434 		} else {
    435 			if (VM_PAGEMD_MODIFIED_P(mdpg)) {
    436 				pte = mips_pg_rwpage_bit();
    437 			} else {
    438 				pte = mips_pg_cwpage_bit();
    439 			}
    440 		}
    441 	} else if (MIPS_HAS_R4K_MMU) {
    442 		/*
    443 		 * Assumption: if it is not part of our managed memory
    444 		 * then it must be device memory which may be volatile.
    445 		 */
    446 		u_int cca = PMAP_CCA_FOR_PA(pa);
    447 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    448 		if (prefetch)
    449 			cca = mips_options.mips3_cca_devmem;
    450 #endif
    451 		pte = MIPS3_PG_IOPAGE(cca) & ~MIPS3_PG_G;
    452 	} else if (prot & VM_PROT_WRITE) {
    453 		pte = MIPS1_PG_N | MIPS1_PG_D;
    454 	} else {
    455 		pte = MIPS1_PG_N | MIPS1_PG_RO;
    456 	}
    457 
    458 	if (MIPS_HAS_R4K_MMU) {
    459 		pte |= mips3_paddr_to_tlbpfn(pa)
    460 		    | (is_kernel_pmap_p ? MIPS3_PG_G : 0);
    461 	} else {
    462 		pte |= mips1_paddr_to_tlbpfn(pa)
    463 		    | MIPS1_PG_V
    464 		    | (is_kernel_pmap_p ? MIPS1_PG_G : 0);
    465 	}
    466 
    467 	return pte;
    468 }
    469 #endif /* __PMAP_PRIVATE */
    470 
    471 #endif	/* defined(_KERNEL) && !defined(_LOCORE) */
    472 #endif /* __MIPS_PTE_H__ */
    473