Home | History | Annotate | Line # | Download | only in include
      1 /*	$NetBSD: pte.h,v 1.27 2020/08/22 15:34:51 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_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_cached_p(pt_entry_t pte)
    310 {
    311 	if (MIPS_HAS_R4K_MMU) {
    312 		return MIPS3_PG_TO_CCA(pte) == MIPS3_PG_TO_CCA(mips_options.mips3_pg_cached);
    313 	} else {
    314 		return (pte & MIPS1_PG_N) == 0;
    315 	}
    316 }
    317 
    318 static inline bool
    319 pte_deferred_exec_p(pt_entry_t pte)
    320 {
    321 	return false;
    322 }
    323 
    324 static inline pt_entry_t
    325 pte_nv_entry(bool kernel_p)
    326 {
    327 	__CTASSERT(MIPS1_PG_NV == MIPS3_PG_NV);
    328 	__CTASSERT(MIPS1_PG_NV == 0);
    329 	return (kernel_p && MIPS_HAS_R4K_MMU) ? MIPS3_PG_G : 0;
    330 }
    331 
    332 static inline pt_entry_t
    333 pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot)
    334 {
    335 	const uint32_t ro_bit = MIPS_MMU(PG_RO);
    336 	const uint32_t rw_bit = MIPS_MMU(PG_D);
    337 
    338 	return (pte & ~(ro_bit|rw_bit))
    339 	    | ((prot & VM_PROT_WRITE) ? rw_bit : ro_bit);
    340 }
    341 
    342 static inline pt_entry_t
    343 pte_prot_nowrite(pt_entry_t pte)
    344 {
    345 	return pte & ~MIPS_MMU(PG_D);
    346 }
    347 
    348 static inline pt_entry_t
    349 pte_cached_change(pt_entry_t pte, bool cached)
    350 {
    351 	if (MIPS_HAS_R4K_MMU) {
    352 		pte &= ~MIPS3_PG_CACHEMODE;
    353 		pte |= (cached ? MIPS3_PG_CACHED : MIPS3_PG_UNCACHED);
    354 	}
    355 	return pte;
    356 }
    357 
    358 static inline void
    359 pte_set(pt_entry_t *ptep, pt_entry_t pte)
    360 {
    361 	*ptep = pte;
    362 }
    363 
    364 #ifdef __PMAP_PRIVATE
    365 struct vm_page_md;
    366 
    367 static inline pt_entry_t
    368 pte_make_kenter_pa(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot,
    369     u_int flags)
    370 {
    371 	pt_entry_t pte;
    372 	if (MIPS_HAS_R4K_MMU) {
    373 		pte = mips3_paddr_to_tlbpfn(pa)
    374 		    | ((prot & VM_PROT_WRITE) ? MIPS3_PG_D : MIPS3_PG_RO)
    375 		    | ((flags & PMAP_NOCACHE) ? MIPS3_PG_UNCACHED : MIPS3_PG_CACHED)
    376 		    | MIPS3_PG_WIRED | MIPS3_PG_V | MIPS3_PG_G;
    377 	} else {
    378 		pte = mips1_paddr_to_tlbpfn(pa)
    379 		    | ((prot & VM_PROT_WRITE) ? MIPS1_PG_D : MIPS1_PG_RO)
    380 		    | ((flags & PMAP_NOCACHE) ? MIPS1_PG_N : 0)
    381 		    | MIPS1_PG_WIRED | MIPS1_PG_V | MIPS1_PG_G;
    382 	}
    383 	return pte;
    384 }
    385 
    386 static inline pt_entry_t
    387 pte_make_enter(paddr_t pa, const struct vm_page_md *mdpg, vm_prot_t prot,
    388     u_int flags, bool is_kernel_pmap_p)
    389 {
    390 	pt_entry_t pte;
    391 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    392 	const bool cached = (flags & PMAP_NOCACHE) == 0
    393 	    && (pa & PGC_NOCACHE) == 0;
    394 	const bool prefetch = (pa & PGC_PREFETCH) != 0;
    395 
    396 	pa &= ~(PGC_NOCACHE|PGC_PREFETCH);
    397 #endif
    398 
    399 #if defined(cobalt) || defined(newsmips) || defined(pmax) /* otherwise ok */
    400 	/* this is not error in general. */
    401 	KASSERTMSG((pa & 0x80000000) == 0, "%#"PRIxPADDR, pa);
    402 #endif
    403 
    404 	if (mdpg != NULL) {
    405 		if ((prot & VM_PROT_WRITE) == 0) {
    406 			/*
    407 			 * If page is not yet referenced, we could emulate this
    408 			 * by not setting the page valid, and setting the
    409 			 * referenced status in the TLB fault handler, similar
    410 			 * to how page modified status is done for UTLBmod
    411 			 * exceptions.
    412 			 */
    413 			pte = mips_pg_ropage_bit();
    414 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    415 		} else if (cached == false) {
    416 			if (VM_PAGEMD_MODIFIED_P(mdpg)) {
    417 				pte = mips_pg_rwncpage_bit();
    418 			} else {
    419 				pte = mips_pg_cwncpage_bit();
    420 			}
    421 #endif
    422 		} else {
    423 			if (VM_PAGEMD_MODIFIED_P(mdpg)) {
    424 				pte = mips_pg_rwpage_bit();
    425 			} else {
    426 				pte = mips_pg_cwpage_bit();
    427 			}
    428 		}
    429 	} else if (MIPS_HAS_R4K_MMU) {
    430 		/*
    431 		 * Assumption: if it is not part of our managed memory
    432 		 * then it must be device memory which may be volatile.
    433 		 */
    434 		u_int cca = PMAP_CCA_FOR_PA(pa);
    435 #if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
    436 		if (prefetch)
    437 			cca = mips_options.mips3_cca_devmem;
    438 #endif
    439 		pte = MIPS3_PG_IOPAGE(cca) & ~MIPS3_PG_G;
    440 	} else if (prot & VM_PROT_WRITE) {
    441 		pte = MIPS1_PG_N | MIPS1_PG_D;
    442 	} else {
    443 		pte = MIPS1_PG_N | MIPS1_PG_RO;
    444 	}
    445 
    446 	if (MIPS_HAS_R4K_MMU) {
    447 		pte |= mips3_paddr_to_tlbpfn(pa)
    448 		    | (is_kernel_pmap_p ? MIPS3_PG_G : 0);
    449 	} else {
    450 		pte |= mips1_paddr_to_tlbpfn(pa)
    451 		    | MIPS1_PG_V
    452 		    | (is_kernel_pmap_p ? MIPS1_PG_G : 0);
    453 	}
    454 
    455 	return pte;
    456 }
    457 #endif /* __PMAP_PRIVATE */
    458 
    459 #endif	/* defined(_KERNEL) && !defined(_LOCORE) */
    460 #endif /* __MIPS_PTE_H__ */
    461