Home | History | Annotate | Line # | Download | only in include
pte.h revision 1.26
      1 /*	$NetBSD: pte.h,v 1.26 2020/07/26 08:08:41 simonb 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_global_p(pt_entry_t pte)
    274 {
    275 	return (pte & MIPS_MMU(PG_G)) != 0;
    276 }
    277 
    278 static inline bool
    279 pte_wired_p(pt_entry_t pte)
    280 {
    281 	return (pte & MIPS_MMU(PG_WIRED)) != 0;
    282 }
    283 
    284 static inline pt_entry_t
    285 pte_wire_entry(pt_entry_t pte)
    286 {
    287 	return pte | MIPS_MMU(PG_WIRED);
    288 }
    289 
    290 static inline pt_entry_t
    291 pte_unwire_entry(pt_entry_t pte)
    292 {
    293 	return pte & ~MIPS_MMU(PG_WIRED);
    294 }
    295 
    296 static inline uint32_t
    297 pte_value(pt_entry_t pte)
    298 {
    299 	return pte;
    300 }
    301 
    302 static inline bool
    303 pte_readonly_p(pt_entry_t pte)
    304 {
    305 	return (pte & MIPS_MMU(PG_RO)) != 0;
    306 }
    307 
    308 static inline bool
    309 pte_zero_p(pt_entry_t pte)
    310 {
    311 	return pte == 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_prot_nowrite(pt_entry_t pte)
    350 {
    351 	return pte & ~MIPS_MMU(PG_D);
    352 }
    353 
    354 static inline pt_entry_t
    355 pte_cached_change(pt_entry_t pte, bool cached)
    356 {
    357 	if (MIPS_HAS_R4K_MMU) {
    358 		pte &= ~MIPS3_PG_CACHEMODE;
    359 		pte |= (cached ? MIPS3_PG_CACHED : MIPS3_PG_UNCACHED);
    360 	}
    361 	return pte;
    362 }
    363 
    364 static inline void
    365 pte_set(pt_entry_t *ptep, pt_entry_t pte)
    366 {
    367 	*ptep = pte;
    368 }
    369 
    370 #ifdef __PMAP_PRIVATE
    371 struct vm_page_md;
    372 
    373 static inline pt_entry_t
    374 pte_make_kenter_pa(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
    375     u_int flags)
    376 {
    377 	pt_entry_t pte;
    378 	if (MIPS_HAS_R4K_MMU) {
    379 		pte = mips3_paddr_to_tlbpfn(pa)
    380 		    | ((prot & VM_PROT_WRITE) ? MIPS3_PG_D : MIPS3_PG_RO)
    381 		    | ((flags & PMAP_NOCACHE) ? MIPS3_PG_UNCACHED : MIPS3_PG_CACHED)
    382 		    | MIPS3_PG_WIRED | MIPS3_PG_V | MIPS3_PG_G;
    383 	} else {
    384 		pte = mips1_paddr_to_tlbpfn(pa)
    385 		    | ((prot & VM_PROT_WRITE) ? MIPS1_PG_D : MIPS1_PG_RO)
    386 		    | ((flags & PMAP_NOCACHE) ? MIPS1_PG_N : 0)
    387 		    | MIPS1_PG_WIRED | MIPS1_PG_V | MIPS1_PG_G;
    388 	}
    389 	return pte;
    390 }
    391 
    392 static inline pt_entry_t
    393 pte_make_enter(paddr_t pa, const struct vm_page_md *mdpg, vm_prot_t prot,
    394     u_int flags, bool is_kernel_pmap_p)
    395 {
    396 	pt_entry_t pte;
    397 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    398 	const bool cached = (flags & PMAP_NOCACHE) == 0
    399 	    && (pa & PGC_NOCACHE) == 0;
    400 	const bool prefetch = (pa & PGC_PREFETCH) != 0;
    401 
    402 	pa &= ~(PGC_NOCACHE|PGC_PREFETCH);
    403 #endif
    404 
    405 #if defined(cobalt) || defined(newsmips) || defined(pmax) /* otherwise ok */
    406 	/* this is not error in general. */
    407 	KASSERTMSG((pa & 0x80000000) == 0, "%#"PRIxPADDR, pa);
    408 #endif
    409 
    410 	if (mdpg != NULL) {
    411 		if ((prot & VM_PROT_WRITE) == 0) {
    412 			/*
    413 			 * If page is not yet referenced, we could emulate this
    414 			 * by not setting the page valid, and setting the
    415 			 * referenced status in the TLB fault handler, similar
    416 			 * to how page modified status is done for UTLBmod
    417 			 * exceptions.
    418 			 */
    419 			pte = mips_pg_ropage_bit();
    420 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    421 		} else if (cached == false) {
    422 			if (VM_PAGEMD_MODIFIED_P(mdpg)) {
    423 				pte = mips_pg_rwncpage_bit();
    424 			} else {
    425 				pte = mips_pg_cwncpage_bit();
    426 			}
    427 #endif
    428 		} else {
    429 			if (VM_PAGEMD_MODIFIED_P(mdpg)) {
    430 				pte = mips_pg_rwpage_bit();
    431 			} else {
    432 				pte = mips_pg_cwpage_bit();
    433 			}
    434 		}
    435 	} else if (MIPS_HAS_R4K_MMU) {
    436 		/*
    437 		 * Assumption: if it is not part of our managed memory
    438 		 * then it must be device memory which may be volatile.
    439 		 */
    440 		u_int cca = PMAP_CCA_FOR_PA(pa);
    441 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    442 		if (prefetch)
    443 			cca = mips_options.mips3_cca_devmem;
    444 #endif
    445 		pte = MIPS3_PG_IOPAGE(cca) & ~MIPS3_PG_G;
    446 	} else if (prot & VM_PROT_WRITE) {
    447 		pte = MIPS1_PG_N | MIPS1_PG_D;
    448 	} else {
    449 		pte = MIPS1_PG_N | MIPS1_PG_RO;
    450 	}
    451 
    452 	if (MIPS_HAS_R4K_MMU) {
    453 		pte |= mips3_paddr_to_tlbpfn(pa)
    454 		    | (is_kernel_pmap_p ? MIPS3_PG_G : 0);
    455 	} else {
    456 		pte |= mips1_paddr_to_tlbpfn(pa)
    457 		    | MIPS1_PG_V
    458 		    | (is_kernel_pmap_p ? MIPS1_PG_G : 0);
    459 	}
    460 
    461 	return pte;
    462 }
    463 #endif /* __PMAP_PRIVATE */
    464 
    465 #endif	/* defined(_KERNEL) && !defined(_LOCORE) */
    466 #endif /* __MIPS_PTE_H__ */
    467