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