1 /* $NetBSD: pte.h,v 1.25 2017/06/24 07:00:37 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_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