1 /* $NetBSD: pmap.c,v 1.44 2024/10/31 10:09:56 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 1999, 2000, 2001 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 and by Chris G. Demetriou. 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 (c) 1991 Regents of the University of California. 35 * All rights reserved. 36 * Copyright (c) 1994 John S. Dyson 37 * All rights reserved. 38 * Copyright (c) 1994 David Greenman 39 * All rights reserved. 40 * Copyright (c) 1998,2000 Doug Rabson 41 * All rights reserved. 42 * 43 * This code is derived from software contributed to Berkeley by 44 * the Systems Programming Group of the University of Utah Computer 45 * Science Department and William Jolitz of UUNET Technologies Inc. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by the University of 58 * California, Berkeley and its contributors. 59 * 4. Neither the name of the University nor the names of its contributors 60 * may be used to endorse or promote products derived from this software 61 * without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 * SUCH DAMAGE. 74 * 75 * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 76 * from: i386 Id: pmap.c,v 1.193 1998/04/19 15:22:48 bde Exp 77 * with some ideas from NetBSD's alpha pmap 78 */ 79 80 /* __FBSDID("$FreeBSD: src/sys/ia64/ia64/pmap.c,v 1.172 2005/11/20 06:09:48 alc Exp $"); */ 81 82 #include <sys/cdefs.h> 83 84 __KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.44 2024/10/31 10:09:56 andvar Exp $"); 85 86 #include <sys/param.h> 87 #include <sys/atomic.h> 88 #include <sys/systm.h> 89 #include <sys/buf.h> 90 #include <sys/reboot.h> 91 #include <sys/lock.h> 92 #include <sys/pool.h> 93 #include <sys/sched.h> 94 #include <sys/bitops.h> 95 96 #include <uvm/uvm.h> 97 #include <uvm/uvm_physseg.h> 98 99 #include <machine/pal.h> 100 #include <machine/atomic.h> 101 #include <machine/pte.h> 102 #include <machine/cpufunc.h> 103 #include <machine/md_var.h> 104 #include <machine/vmparam.h> 105 106 /* 107 * Manages physical address maps. 108 * 109 * Since the information managed by this module is 110 * also stored by the logical address mapping module, 111 * this module may throw away valid virtual-to-physical 112 * mappings at almost any time. However, invalidations 113 * of virtual-to-physical mappings must be done as 114 * requested. 115 * 116 * In order to cope with hardware architectures which 117 * make virtual-to-physical map invalidates expensive, 118 * this module may delay invalidate or reduced protection 119 * operations until such time as they are actually 120 * necessary. This module is given full information as 121 * to which processors are currently using which maps, 122 * and to when physical maps must be made correct. 123 */ 124 125 /* 126 * Following the Linux model, region IDs are allocated in groups of 127 * eight so that a single region ID can be used for as many RRs as we 128 * want by encoding the RR number into the low bits of the ID. 129 * 130 * We reserve region ID 0 for the kernel and allocate the remaining 131 * IDs for user pmaps. 132 * 133 * Region 0-3: User virtually mapped 134 * Region 4: PBVM and special mappings 135 * Region 5: Kernel virtual memory 136 * Region 6: Direct-mapped uncacheable 137 * Region 7: Direct-mapped cacheable 138 */ 139 140 #if !defined(DIAGNOSTIC) 141 #define PMAP_INLINE __inline 142 #else 143 #define PMAP_INLINE 144 #endif 145 146 #ifdef PV_STATS 147 #define PV_STAT(x) do { x ; } while (0) 148 #else 149 #define PV_STAT(x) do { } while (0) 150 #endif 151 152 #define pmap_accessed(lpte) ((lpte)->pte & PTE_ACCESSED) 153 #define pmap_dirty(lpte) ((lpte)->pte & PTE_DIRTY) 154 #define pmap_exec(lpte) ((lpte)->pte & PTE_AR_RX) 155 #define pmap_managed(lpte) ((lpte)->pte & PTE_MANAGED) 156 #define pmap_ppn(lpte) ((lpte)->pte & PTE_PPN_MASK) 157 #define pmap_present(lpte) ((lpte)->pte & PTE_PRESENT) 158 #define pmap_prot(lpte) (((lpte)->pte & PTE_PROT_MASK) >> 56) 159 #define pmap_wired(lpte) ((lpte)->pte & PTE_WIRED) 160 161 #define pmap_clear_accessed(lpte) (lpte)->pte &= ~PTE_ACCESSED 162 #define pmap_clear_dirty(lpte) (lpte)->pte &= ~PTE_DIRTY 163 #define pmap_clear_present(lpte) (lpte)->pte &= ~PTE_PRESENT 164 #define pmap_clear_wired(lpte) (lpte)->pte &= ~PTE_WIRED 165 166 #define pmap_set_wired(lpte) (lpte)->pte |= PTE_WIRED 167 168 /* 169 * Individual PV entries are stored in per-pmap chunks. This saves 170 * space by eliminating the need to record the pmap within every PV 171 * entry. 172 */ 173 #if PAGE_SIZE == 8192 174 #define _NPCM 6 175 #define _NPCPV 337 176 #define _NPCS 2 177 #elif PAGE_SIZE == 16384 178 #define _NPCM 11 179 #define _NPCPV 677 180 #define _NPCS 1 181 #else 182 #error "invalid page size" 183 #endif 184 185 struct pv_chunk { 186 pmap_t pc_pmap; 187 TAILQ_ENTRY(pv_chunk) pc_list; 188 u_long pc_map[_NPCM]; /* bitmap; 1 = free */ 189 TAILQ_ENTRY(pv_chunk) pc_lru; 190 u_long pc_spare[_NPCS]; 191 struct pv_entry pc_pventry[_NPCPV]; 192 }; 193 194 /* 195 * The VHPT bucket head structure. 196 */ 197 struct ia64_bucket { 198 uint64_t chain; 199 kmutex_t mutex; 200 u_int length; 201 }; 202 203 /* 204 * Statically allocated kernel pmap 205 */ 206 static struct pmap kernel_pmap_store;/* the kernel's pmap (proc0) */ 207 struct pmap *const kernel_pmap_ptr = &kernel_pmap_store; 208 209 vaddr_t virtual_avail; /* VA of first avail page (after kernel bss) */ 210 vaddr_t virtual_end; /* VA of last avail page (end of kernel AS) */ 211 212 /* XXX freebsd, needs to be sorted out */ 213 #define kernel_pmap pmap_kernel() 214 #define critical_enter() kpreempt_disable() 215 #define critical_exit() kpreempt_enable() 216 /* flags the entire page as dirty */ 217 #define vm_page_dirty(page) (page->flags &= ~PG_CLEAN) 218 #define vm_page_is_managed(page) (pmap_initialized && uvm_pageismanaged(VM_PAGE_TO_PHYS(page))) 219 220 /* 221 * Kernel virtual memory management. 222 */ 223 static int nkpt; 224 225 extern struct ia64_lpte ***ia64_kptdir; 226 227 #define KPTE_DIR0_INDEX(va) \ 228 (((va) >> (3*PAGE_SHIFT-8)) & ((1<<(PAGE_SHIFT-3))-1)) 229 #define KPTE_DIR1_INDEX(va) \ 230 (((va) >> (2*PAGE_SHIFT-5)) & ((1<<(PAGE_SHIFT-3))-1)) 231 #define KPTE_PTE_INDEX(va) \ 232 (((va) >> PAGE_SHIFT) & ((1<<(PAGE_SHIFT-5))-1)) 233 234 #define NKPTEPG (PAGE_SIZE / sizeof(struct ia64_lpte)) 235 236 vaddr_t kernel_vm_end; 237 238 /* Defaults for ptc.e. */ 239 /* 240 static uint64_t pmap_ptc_e_base = 0; 241 static uint32_t pmap_ptc_e_count1 = 1; 242 static uint32_t pmap_ptc_e_count2 = 1; 243 static uint32_t pmap_ptc_e_stride1 = 0; 244 static uint32_t pmap_ptc_e_stride2 = 0; 245 */ 246 /* Values for ptc.e. XXX values for SKI, add SKI kernel option methinks */ 247 static uint64_t pmap_ptc_e_base = 0x100000000; 248 static uint64_t pmap_ptc_e_count1 = 3; 249 static uint64_t pmap_ptc_e_count2 = 2; 250 static uint64_t pmap_ptc_e_stride1 = 0x2000; 251 static uint64_t pmap_ptc_e_stride2 = 0x100000000; 252 253 kmutex_t pmap_ptc_mutex; 254 255 /* 256 * Data for the RID allocator 257 */ 258 static int pmap_ridcount; 259 static int pmap_rididx; 260 static int pmap_ridmapsz; 261 static int pmap_ridmax; 262 static uint64_t *pmap_ridmap; 263 kmutex_t pmap_ridmutex; 264 265 static krwlock_t pvh_global_lock __attribute__ ((aligned (128))); 266 267 static pool_cache_t pmap_pool_cache; 268 269 /* 270 * Data for the pv entry allocation mechanism 271 */ 272 static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks); 273 static int pv_entry_count; 274 275 /* 276 * Data for allocating PTEs for user processes. 277 */ 278 static pool_cache_t pte_pool_cache; 279 280 struct ia64_bucket *pmap_vhpt_bucket; 281 282 /* XXX For freebsd, these are sysctl variables */ 283 static uint64_t pmap_vhpt_nbuckets = 0; 284 uint64_t pmap_vhpt_log2size = 0; 285 static uint64_t pmap_vhpt_inserts = 0; 286 287 static bool pmap_initialized = false; /* Has pmap_init completed? */ 288 static uint64_t pmap_pages_stolen = 0; /* instrumentation */ 289 290 static struct ia64_lpte *pmap_find_vhpt(vaddr_t va); 291 292 static void free_pv_chunk(struct pv_chunk *pc); 293 static void free_pv_entry(pmap_t pmap, pv_entry_t pv); 294 static pv_entry_t get_pv_entry(pmap_t pmap, bool try); 295 static struct vm_page *pmap_pv_reclaim(pmap_t locked_pmap); 296 297 static void pmap_free_pte(struct ia64_lpte *pte, vaddr_t va); 298 static int pmap_remove_pte(pmap_t pmap, struct ia64_lpte *pte, 299 vaddr_t va, pv_entry_t pv, int freepte); 300 static int pmap_remove_vhpt(vaddr_t va); 301 302 static vaddr_t pmap_steal_vhpt_memory(vsize_t); 303 304 static struct vm_page *vm_page_alloc1(void); 305 static void vm_page_free1(struct vm_page *pg); 306 307 static vm_memattr_t pmap_flags_to_memattr(u_int flags); 308 309 #if DEBUG 310 static void pmap_testout(void); 311 #endif 312 313 static void 314 pmap_initialize_vhpt(vaddr_t vhpt) 315 { 316 struct ia64_lpte *pte; 317 u_int i; 318 319 pte = (struct ia64_lpte *)vhpt; 320 for (i = 0; i < pmap_vhpt_nbuckets; i++) { 321 pte[i].pte = 0; 322 pte[i].itir = 0; 323 pte[i].tag = 1UL << 63; /* Invalid tag */ 324 pte[i].chain = (uintptr_t)(pmap_vhpt_bucket + i); 325 } 326 } 327 328 #ifdef MULTIPROCESSOR 329 vaddr_t 330 pmap_alloc_vhpt(void) 331 { 332 vaddr_t vhpt; 333 struct vm_page *m; 334 vsize_t size; 335 336 size = 1UL << pmap_vhpt_log2size; 337 m = vm_page_alloc_contig(NULL, 0, VM_ALLOC_SYSTEM | VM_ALLOC_NOOBJ | 338 VM_ALLOC_WIRED, atop(size), 0UL, ~0UL, size, 0UL, 339 VM_MEMATTR_DEFAULT); 340 if (m != NULL) { 341 vhpt = IA64_PHYS_TO_RR7(VM_PAGE_TO_PHYS(m)); 342 pmap_initialize_vhpt(vhpt); 343 return (vhpt); 344 } 345 return (0); 346 } 347 #endif 348 349 /* 350 * Bootstrap the system enough to run with virtual memory. 351 */ 352 void 353 pmap_bootstrap(void) 354 { 355 struct ia64_pal_result res; 356 vaddr_t base; 357 size_t size; 358 vsize_t bufsz; 359 int i, ridbits; 360 361 /* 362 * Query the PAL Code to find the loop parameters for the 363 * ptc.e instruction. 364 */ 365 res = ia64_call_pal_static(PAL_PTCE_INFO, 0, 0, 0); 366 if (res.pal_status != 0) 367 panic("Can't configure ptc.e parameters"); 368 pmap_ptc_e_base = res.pal_result[0]; 369 pmap_ptc_e_count1 = res.pal_result[1] >> 32; 370 pmap_ptc_e_count2 = res.pal_result[1] & ((1L<<32) - 1); 371 pmap_ptc_e_stride1 = res.pal_result[2] >> 32; 372 pmap_ptc_e_stride2 = res.pal_result[2] & ((1L<<32) - 1); 373 if (bootverbose) 374 printf("ptc.e base=0x%lx, count1=%ld, count2=%ld, " 375 "stride1=0x%lx, stride2=0x%lx\n", 376 pmap_ptc_e_base, 377 pmap_ptc_e_count1, 378 pmap_ptc_e_count2, 379 pmap_ptc_e_stride1, 380 pmap_ptc_e_stride2); 381 382 mutex_init(&pmap_ptc_mutex, MUTEX_DEFAULT, IPL_VM); 383 384 /* 385 * Setup RIDs. RIDs 0..7 are reserved for the kernel. 386 * 387 * We currently need at least 19 bits in the RID because PID_MAX 388 * can only be encoded in 17 bits and we need RIDs for 4 regions 389 * per process. With PID_MAX equalling 99999 this means that we 390 * need to be able to encode 399996 (=4*PID_MAX). 391 * The Itanium processor only has 18 bits and the architected 392 * minimum is exactly that. So, we cannot use a PID based scheme 393 * in those cases. Enter pmap_ridmap... 394 * We should avoid the map when running on a processor that has 395 * implemented enough bits. This means that we should pass the 396 * process/thread ID to pmap. This we currently don't do, so we 397 * use the map anyway. However, we don't want to allocate a map 398 * that is large enough to cover the range dictated by the number 399 * of bits in the RID, because that may result in a RID map of 400 * 2MB in size for a 24-bit RID. A 64KB map is enough. 401 * The bottomline: we create a 32KB map when the processor only 402 * implements 18 bits (or when we can't figure it out). Otherwise 403 * we create a 64KB map. 404 */ 405 res = ia64_call_pal_static(PAL_VM_SUMMARY, 0, 0, 0); 406 if (res.pal_status != 0) { 407 if (bootverbose) 408 printf("Can't read VM Summary - assuming 18 Region ID bits\n"); 409 ridbits = 18; /* guaranteed minimum */ 410 } else { 411 ridbits = (res.pal_result[1] >> 8) & 0xff; 412 if (bootverbose) 413 printf("Processor supports %d Region ID bits\n", 414 ridbits); 415 } 416 if (ridbits > 19) 417 ridbits = 19; 418 419 pmap_ridmax = (1 << ridbits); 420 pmap_ridmapsz = pmap_ridmax / 64; 421 pmap_ridmap = (uint64_t *)uvm_pageboot_alloc(pmap_ridmax / 8); 422 pmap_ridmap[0] |= 0xff; 423 pmap_rididx = 0; 424 pmap_ridcount = 8; 425 mutex_init(&pmap_ridmutex, MUTEX_DEFAULT, IPL_VM); 426 427 /* 428 * Compute the number of pages kmem_map will have. 429 */ 430 kmeminit_nkmempages(); 431 432 /* 433 * Figure out how many initial PTE's are necessary to map the 434 * kernel. We also reserve space for kmem_alloc_pageable() 435 * for vm_fork(). 436 */ 437 438 /* Get size of buffer cache and set an upper limit */ 439 bufsz = buf_memcalc(); 440 buf_setvalimit(bufsz); 441 442 nkpt = (((ubc_nwins << ubc_winshift) + 443 bufsz + 16 * NCARGS + pager_map_size) / PAGE_SIZE + 444 USRIOSIZE + (maxproc * UPAGES) + nkmempages) / NKPTEPG; 445 446 /* 447 * Allocate some memory for initial kernel 'page tables'. 448 */ 449 ia64_kptdir = (void *)uvm_pageboot_alloc(PAGE_SIZE); 450 memset((void *)ia64_kptdir, 0, PAGE_SIZE); 451 nkpt = 0; 452 kernel_vm_end = VM_INIT_KERNEL_ADDRESS; 453 454 /* 455 * Determine a valid (mappable) VHPT size. 456 */ 457 if (pmap_vhpt_log2size == 0) 458 pmap_vhpt_log2size = 20; 459 else if (pmap_vhpt_log2size < 16) 460 pmap_vhpt_log2size = 16; 461 else if (pmap_vhpt_log2size > 28) 462 pmap_vhpt_log2size = 28; 463 if (pmap_vhpt_log2size & 1) 464 pmap_vhpt_log2size--; 465 466 size = 1UL << pmap_vhpt_log2size; 467 /* XXX add some retries here */ 468 base = pmap_steal_vhpt_memory(size); 469 470 curcpu()->ci_vhpt = base; 471 472 if (base == 0) 473 panic("Unable to allocate VHPT"); 474 475 pmap_vhpt_nbuckets = size / sizeof(struct ia64_lpte); 476 pmap_vhpt_bucket = (void *)uvm_pageboot_alloc(pmap_vhpt_nbuckets * 477 sizeof(struct ia64_bucket)); 478 if (bootverbose) 479 printf("VHPT: address=%#lx, size=%#lx, buckets=%ld, address=%lx\n", 480 base, size, pmap_vhpt_nbuckets, (long unsigned int)&pmap_vhpt_bucket[0]); 481 482 for (i = 0; i < pmap_vhpt_nbuckets; i++) { 483 /* Stolen memory is zeroed. */ 484 mutex_init(&pmap_vhpt_bucket[i].mutex, MUTEX_DEFAULT, IPL_VM); 485 } 486 487 pmap_initialize_vhpt(base); 488 map_vhpt(base); 489 ia64_set_pta(base + (1 << 8) + (pmap_vhpt_log2size << 2) + 1); 490 ia64_srlz_i(); 491 492 /* XXX 493 virtual_avail = VM_INIT_KERNEL_ADDRESS; 494 virtual_end = VM_MAX_KERNEL_ADDRESS; 495 */ 496 497 /* 498 * Initialize the kernel pmap (which is statically allocated). 499 */ 500 PMAP_LOCK_INIT(kernel_pmap); 501 for (i = 0; i < IA64_VM_MINKERN_REGION; i++) 502 kernel_pmap->pm_rid[i] = 0; 503 TAILQ_INIT(&kernel_pmap->pm_pvchunk); 504 505 bzero(&kernel_pmap->pm_stats, sizeof kernel_pmap->pm_stats); 506 kernel_pmap->pm_refcount = 1; 507 508 curcpu()->ci_pmap = kernel_pmap; 509 510 /* 511 * Initialize the global pv list lock. 512 */ 513 rw_init(&pvh_global_lock); 514 515 /* Region 5 is mapped via the VHPT. */ 516 ia64_set_rr(IA64_RR_BASE(5), (5 << 8) | (PAGE_SHIFT << 2) | 1); 517 518 /* 519 * Clear out any random TLB entries left over from booting. 520 */ 521 pmap_invalidate_all(); 522 523 map_gateway_page(); 524 } 525 526 vaddr_t 527 pmap_page_to_va(struct vm_page *m) 528 { 529 paddr_t pa; 530 vaddr_t va; 531 532 pa = VM_PAGE_TO_PHYS(m); 533 va = (m->mdpage.memattr == VM_MEMATTR_UNCACHEABLE) ? IA64_PHYS_TO_RR6(pa) : 534 IA64_PHYS_TO_RR7(pa); 535 return (va); 536 } 537 538 /*************************************************** 539 * Manipulate TLBs for a pmap 540 ***************************************************/ 541 542 static void 543 pmap_invalidate_page(vaddr_t va) 544 { 545 struct ia64_lpte *pte; 546 //struct pcpu *pc; 547 uint64_t tag; 548 u_int vhpt_ofs; 549 struct cpu_info *ci; 550 CPU_INFO_ITERATOR cii; 551 552 critical_enter(); 553 554 vhpt_ofs = ia64_thash(va) - curcpu()->ci_vhpt; 555 556 tag = ia64_ttag(va); 557 558 for (CPU_INFO_FOREACH(cii,ci)) { 559 pte = (struct ia64_lpte *)(ci->ci_vhpt + vhpt_ofs); 560 atomic_cmpset_64(&pte->tag, tag, 1UL << 63); 561 } 562 563 mutex_spin_enter(&pmap_ptc_mutex); 564 565 ia64_ptc_ga(va, PAGE_SHIFT << 2); 566 ia64_mf(); 567 ia64_srlz_i(); 568 569 mutex_spin_exit(&pmap_ptc_mutex); 570 571 ia64_invala(); 572 573 critical_exit(); 574 } 575 576 void 577 pmap_invalidate_all(void) 578 { 579 uint64_t addr; 580 int i, j; 581 582 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 583 584 addr = pmap_ptc_e_base; 585 for (i = 0; i < pmap_ptc_e_count1; i++) { 586 for (j = 0; j < pmap_ptc_e_count2; j++) { 587 ia64_ptc_e(addr); 588 addr += pmap_ptc_e_stride2; 589 } 590 addr += pmap_ptc_e_stride1; 591 } 592 ia64_srlz_i(); 593 } 594 595 static uint32_t 596 pmap_allocate_rid(void) 597 { 598 uint64_t bit, bits; 599 int rid; 600 601 mutex_enter(&pmap_ridmutex); 602 603 if (pmap_ridcount == pmap_ridmax) 604 panic("pmap_allocate_rid: All Region IDs used"); 605 606 /* Find an index with a free bit. */ 607 while ((bits = pmap_ridmap[pmap_rididx]) == ~0UL) { 608 pmap_rididx++; 609 if (pmap_rididx == pmap_ridmapsz) 610 pmap_rididx = 0; 611 } 612 rid = pmap_rididx * 64; 613 614 /* Find a free bit. */ 615 bit = 1UL; 616 while (bits & bit) { 617 rid++; 618 bit <<= 1; 619 } 620 621 pmap_ridmap[pmap_rididx] |= bit; 622 pmap_ridcount++; 623 624 mutex_exit(&pmap_ridmutex); 625 626 return rid; 627 } 628 629 static void 630 pmap_free_rid(uint32_t rid) 631 { 632 uint64_t bit; 633 int idx; 634 635 idx = rid / 64; 636 bit = ~(1UL << (rid & 63)); 637 638 mutex_enter(&pmap_ridmutex); 639 pmap_ridmap[idx] &= bit; 640 pmap_ridcount--; 641 642 mutex_exit(&pmap_ridmutex); 643 } 644 645 /*************************************************** 646 * Page table page management routines..... 647 ***************************************************/ 648 CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE); 649 650 static __inline struct pv_chunk * 651 pv_to_chunk(pv_entry_t pv) 652 { 653 return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK)); 654 } 655 656 #define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap) 657 658 #define PC_FREE_FULL 0xfffffffffffffffful 659 #define PC_FREE_PARTIAL \ 660 ((1UL << (_NPCPV - sizeof(u_long) * 8 * (_NPCM - 1))) - 1) 661 662 #if PAGE_SIZE == 8192 663 static const u_long pc_freemask[_NPCM] = { 664 PC_FREE_FULL, PC_FREE_FULL, PC_FREE_FULL, 665 PC_FREE_FULL, PC_FREE_FULL, PC_FREE_PARTIAL 666 }; 667 #elif PAGE_SIZE == 16384 668 static const u_long pc_freemask[_NPCM] = { 669 PC_FREE_FULL, PC_FREE_FULL, PC_FREE_FULL, 670 PC_FREE_FULL, PC_FREE_FULL, PC_FREE_FULL, 671 PC_FREE_FULL, PC_FREE_FULL, PC_FREE_FULL, 672 PC_FREE_FULL, PC_FREE_PARTIAL 673 }; 674 #endif 675 676 #ifdef PV_STATS 677 static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail; 678 static long pv_entry_frees, pv_entry_allocs; 679 static int pv_entry_spare; 680 #endif 681 682 /* 683 * We are in a serious low memory condition. Resort to 684 * drastic measures to free some pages so we can allocate 685 * another pv entry chunk. 686 */ 687 static struct vm_page 688 *pmap_pv_reclaim(pmap_t locked_pmap) 689 { 690 struct pch newtail; 691 struct pv_chunk *pc; 692 struct ia64_lpte *pte; 693 pmap_t pmap; 694 pv_entry_t pv; 695 vaddr_t va; 696 struct vm_page *m; 697 struct vm_page *m_pc; 698 u_long inuse; 699 int bit, field, freed, idx; 700 701 PMAP_LOCK_ASSERT(locked_pmap); 702 pmap = NULL; 703 m_pc = NULL; 704 TAILQ_INIT(&newtail); 705 while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL) { 706 TAILQ_REMOVE(&pv_chunks, pc, pc_lru); 707 if (pmap != pc->pc_pmap) { 708 if (pmap != NULL) { 709 if (pmap != locked_pmap) { 710 pmap_switch(locked_pmap); 711 PMAP_UNLOCK(pmap); 712 } 713 } 714 pmap = pc->pc_pmap; 715 /* Avoid deadlock and lock recursion. */ 716 if (pmap > locked_pmap) 717 PMAP_LOCK(pmap); 718 else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) { 719 pmap = NULL; 720 TAILQ_INSERT_TAIL(&newtail, pc, pc_lru); 721 continue; 722 } 723 pmap_switch(pmap); 724 } 725 726 /* 727 * Destroy every non-wired, 8 KB page mapping in the chunk. 728 */ 729 freed = 0; 730 for (field = 0; field < _NPCM; field++) { 731 for (inuse = ~pc->pc_map[field] & pc_freemask[field]; 732 inuse != 0; inuse &= ~(1UL << bit)) { 733 bit = ffs64(inuse) - 1; 734 idx = field * sizeof(inuse) * NBBY + bit; 735 pv = &pc->pc_pventry[idx]; 736 va = pv->pv_va; 737 pte = pmap_find_vhpt(va); 738 KASSERTMSG(pte != NULL, "pte"); 739 if (pmap_wired(pte)) 740 continue; 741 pmap_remove_vhpt(va); 742 pmap_invalidate_page(va); 743 m = PHYS_TO_VM_PAGE(pmap_ppn(pte)); 744 if (pmap_dirty(pte)) 745 vm_page_dirty(m); 746 pmap_free_pte(pte, va); 747 TAILQ_REMOVE(&m->mdpage.pv_list, pv, pv_list); 748 /* XXX 749 if (TAILQ_EMPTY(&m->mdpage.pv_list)) 750 //vm_page_aflag_clear(m, PGA_WRITEABLE); 751 m->flags |= PG_RDONLY; 752 */ 753 pc->pc_map[field] |= 1UL << bit; 754 freed++; 755 } 756 } 757 if (freed == 0) { 758 TAILQ_INSERT_TAIL(&newtail, pc, pc_lru); 759 continue; 760 } 761 /* Every freed mapping is for a 8 KB page. */ 762 pmap->pm_stats.resident_count -= freed; 763 PV_STAT(pv_entry_frees += freed); 764 PV_STAT(pv_entry_spare += freed); 765 pv_entry_count -= freed; 766 TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); 767 for (field = 0; field < _NPCM; field++) 768 if (pc->pc_map[field] != pc_freemask[field]) { 769 TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, 770 pc_list); 771 TAILQ_INSERT_TAIL(&newtail, pc, pc_lru); 772 773 /* 774 * One freed pv entry in locked_pmap is 775 * sufficient. 776 */ 777 if (pmap == locked_pmap) 778 goto out; 779 break; 780 } 781 if (field == _NPCM) { 782 PV_STAT(pv_entry_spare -= _NPCPV); 783 PV_STAT(pc_chunk_count--); 784 PV_STAT(pc_chunk_frees++); 785 /* Entire chunk is free; return it. */ 786 m_pc = PHYS_TO_VM_PAGE(IA64_RR_MASK((vaddr_t)pc)); 787 break; 788 } 789 } 790 out: 791 TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru); 792 if (pmap != NULL) { 793 if (pmap != locked_pmap) { 794 pmap_switch(locked_pmap); 795 PMAP_UNLOCK(pmap); 796 } 797 } 798 return (m_pc); 799 } 800 801 /* 802 * free the pv_entry back to the free list 803 */ 804 static void 805 free_pv_entry(pmap_t pmap, pv_entry_t pv) 806 { 807 struct pv_chunk *pc; 808 int bit, field, idx; 809 810 KASSERT(rw_write_held(&pvh_global_lock)); 811 PMAP_LOCK_ASSERT(pmap); 812 PV_STAT(pv_entry_frees++); 813 PV_STAT(pv_entry_spare++); 814 pv_entry_count--; 815 pc = pv_to_chunk(pv); 816 idx = pv - &pc->pc_pventry[0]; 817 field = idx / (sizeof(u_long) * NBBY); 818 bit = idx % (sizeof(u_long) * NBBY); 819 pc->pc_map[field] |= 1ul << bit; 820 for (idx = 0; idx < _NPCM; idx++) 821 if (pc->pc_map[idx] != pc_freemask[idx]) { 822 /* 823 * 98% of the time, pc is already at the head of the 824 * list. If it isn't already, move it to the head. 825 */ 826 if (__predict_false(TAILQ_FIRST(&pmap->pm_pvchunk) != 827 pc)) { 828 TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); 829 TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, 830 pc_list); 831 } 832 return; 833 } 834 TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); 835 free_pv_chunk(pc); 836 } 837 838 static void 839 free_pv_chunk(struct pv_chunk *pc) 840 { 841 struct vm_page *m; 842 843 TAILQ_REMOVE(&pv_chunks, pc, pc_lru); 844 PV_STAT(pv_entry_spare -= _NPCPV); 845 PV_STAT(pc_chunk_count--); 846 PV_STAT(pc_chunk_frees++); 847 /* entire chunk is free, return it */ 848 m = PHYS_TO_VM_PAGE(IA64_RR_MASK((vaddr_t)pc)); 849 #if 0 850 /* XXX freebsd these move pages around in queue */ 851 vm_page_unwire(m, 0); // releases one wiring and moves page back active/inactive queue 852 vm_page_free(m); // moves page to "free" queue & disassociate with object 853 854 /* XXX might to need locks/other checks here, uvm_unwire, pmap_kremove... */ 855 uvm_pagefree(m); 856 #endif 857 vm_page_free1(m); 858 } 859 860 /* 861 * get a new pv_entry, allocating a block from the system 862 * when needed. 863 */ 864 static pv_entry_t 865 get_pv_entry(pmap_t pmap, bool try) 866 { 867 struct pv_chunk *pc; 868 pv_entry_t pv; 869 struct vm_page *m; 870 int bit, field, idx; 871 872 KASSERT(rw_write_held(&pvh_global_lock)); 873 PMAP_LOCK_ASSERT(pmap); 874 PV_STAT(pv_entry_allocs++); 875 pv_entry_count++; 876 retry: 877 pc = TAILQ_FIRST(&pmap->pm_pvchunk); 878 if (pc != NULL) { 879 for (field = 0; field < _NPCM; field++) { 880 if (pc->pc_map[field]) { 881 bit = ffs64(pc->pc_map[field]) - 1; 882 break; 883 } 884 } 885 if (field < _NPCM) { 886 idx = field * sizeof(pc->pc_map[field]) * NBBY + bit; 887 pv = &pc->pc_pventry[idx]; 888 pc->pc_map[field] &= ~(1ul << bit); 889 /* If this was the last item, move it to tail */ 890 for (field = 0; field < _NPCM; field++) 891 if (pc->pc_map[field] != 0) { 892 PV_STAT(pv_entry_spare--); 893 return (pv); /* not full, return */ 894 } 895 TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list); 896 TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc, pc_list); 897 PV_STAT(pv_entry_spare--); 898 return (pv); 899 } 900 } 901 902 /* No free items, allocate another chunk */ 903 m = vm_page_alloc1(); 904 905 if (m == NULL) { 906 if (try) { 907 pv_entry_count--; 908 PV_STAT(pc_chunk_tryfail++); 909 return (NULL); 910 } 911 m = pmap_pv_reclaim(pmap); 912 if (m == NULL) 913 goto retry; 914 } 915 916 PV_STAT(pc_chunk_count++); 917 PV_STAT(pc_chunk_allocs++); 918 pc = (struct pv_chunk *)IA64_PHYS_TO_RR7(VM_PAGE_TO_PHYS(m)); 919 pc->pc_pmap = pmap; 920 pc->pc_map[0] = pc_freemask[0] & ~1ul; /* preallocated bit 0 */ 921 for (field = 1; field < _NPCM; field++) 922 pc->pc_map[field] = pc_freemask[field]; 923 TAILQ_INSERT_TAIL(&pv_chunks, pc, pc_lru); 924 pv = &pc->pc_pventry[0]; 925 TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list); 926 PV_STAT(pv_entry_spare += _NPCPV - 1); 927 return (pv); 928 } 929 930 /* 931 * Conditionally create a pv entry. 932 */ 933 #if 0 934 static bool 935 pmap_try_insert_pv_entry(pmap_t pmap, vaddr_t va, struct vm_page *m) 936 { 937 pv_entry_t pv; 938 939 PMAP_LOCK_ASSERT(pmap); 940 KASSERT(rw_write_held(&pvh_global_lock)); 941 if ((pv = get_pv_entry(pmap, true)) != NULL) { 942 pv->pv_va = va; 943 TAILQ_INSERT_TAIL(&m->mdpage.pv_list, pv, pv_list); 944 return (true); 945 } else 946 return (false); 947 } 948 #endif 949 950 /* 951 * Add an ia64_lpte to the VHPT. 952 */ 953 static void 954 pmap_enter_vhpt(struct ia64_lpte *pte, vaddr_t va) 955 { 956 struct ia64_bucket *bckt; 957 struct ia64_lpte *vhpte; 958 uint64_t pte_pa; 959 960 /* Can fault, so get it out of the way. */ 961 pte_pa = ia64_tpa((vaddr_t)pte); 962 963 vhpte = (struct ia64_lpte *)ia64_thash(va); 964 bckt = (struct ia64_bucket *)vhpte->chain; 965 966 mutex_spin_enter(&bckt->mutex); 967 pte->chain = bckt->chain; 968 ia64_mf(); 969 bckt->chain = pte_pa; 970 971 pmap_vhpt_inserts++; 972 bckt->length++; 973 mutex_spin_exit(&bckt->mutex); 974 } 975 976 /* 977 * Remove the ia64_lpte matching va from the VHPT. Return zero if it 978 * worked or an appropriate error code otherwise. 979 */ 980 static int 981 pmap_remove_vhpt(vaddr_t va) 982 { 983 struct ia64_bucket *bckt; 984 struct ia64_lpte *pte; 985 struct ia64_lpte *lpte; 986 struct ia64_lpte *vhpte; 987 uint64_t chain, tag; 988 989 tag = ia64_ttag(va); 990 vhpte = (struct ia64_lpte *)ia64_thash(va); 991 bckt = (struct ia64_bucket *)vhpte->chain; 992 993 lpte = NULL; 994 mutex_spin_enter(&bckt->mutex); 995 chain = bckt->chain; 996 pte = (struct ia64_lpte *)IA64_PHYS_TO_RR7(chain); 997 while (chain != 0 && pte->tag != tag) { 998 lpte = pte; 999 chain = pte->chain; 1000 pte = (struct ia64_lpte *)IA64_PHYS_TO_RR7(chain); 1001 } 1002 if (chain == 0) { 1003 mutex_spin_exit(&bckt->mutex); 1004 return (ENOENT); 1005 } 1006 1007 /* Snip this pv_entry out of the collision chain. */ 1008 if (lpte == NULL) 1009 bckt->chain = pte->chain; 1010 else 1011 lpte->chain = pte->chain; 1012 ia64_mf(); 1013 1014 bckt->length--; 1015 1016 mutex_spin_exit(&bckt->mutex); 1017 return (0); 1018 } 1019 1020 /* 1021 * Find the ia64_lpte for the given va, if any. 1022 */ 1023 static struct ia64_lpte * 1024 pmap_find_vhpt(vaddr_t va) 1025 { 1026 struct ia64_bucket *bckt; 1027 struct ia64_lpte *pte; 1028 uint64_t chain, tag; 1029 1030 tag = ia64_ttag(va); 1031 pte = (struct ia64_lpte *)ia64_thash(va); 1032 bckt = (struct ia64_bucket *)pte->chain; 1033 1034 mutex_spin_enter(&bckt->mutex); 1035 chain = bckt->chain; 1036 pte = (struct ia64_lpte *)IA64_PHYS_TO_RR7(chain); 1037 while (chain != 0 && pte->tag != tag) { 1038 chain = pte->chain; 1039 pte = (struct ia64_lpte *)IA64_PHYS_TO_RR7(chain); 1040 } 1041 1042 mutex_spin_exit(&bckt->mutex); 1043 return ((chain != 0) ? pte : NULL); 1044 } 1045 1046 /* 1047 * Remove an entry from the list of managed mappings. 1048 */ 1049 static int 1050 pmap_remove_entry(pmap_t pmap, struct vm_page *m, vaddr_t va, pv_entry_t pv) 1051 { 1052 1053 KASSERT(rw_write_held(&pvh_global_lock)); 1054 if (!pv) { 1055 TAILQ_FOREACH(pv, &m->mdpage.pv_list, pv_list) { 1056 if (pmap == PV_PMAP(pv) && va == pv->pv_va) 1057 break; 1058 } 1059 } 1060 1061 if (pv) { 1062 TAILQ_REMOVE(&m->mdpage.pv_list, pv, pv_list); 1063 /* XXX 1064 if (TAILQ_FIRST(&m->mdpage.pv_list) == NULL) 1065 //vm_page_aflag_clear(m, PGA_WRITEABLE); 1066 m->flags |= PG_RDONLY; 1067 */ 1068 free_pv_entry(pmap, pv); 1069 return 0; 1070 } else { 1071 return ENOENT; 1072 } 1073 } 1074 1075 /* 1076 * Create a pv entry for page at pa for 1077 * (pmap, va). 1078 */ 1079 static void 1080 pmap_insert_entry(pmap_t pmap, vaddr_t va, struct vm_page *m) 1081 { 1082 pv_entry_t pv; 1083 1084 KASSERT(rw_write_held(&pvh_global_lock)); 1085 pv = get_pv_entry(pmap, false); 1086 pv->pv_va = va; 1087 TAILQ_INSERT_TAIL(&m->mdpage.pv_list, pv, pv_list); 1088 } 1089 1090 /*************************************************** 1091 * Low level mapping routines..... 1092 ***************************************************/ 1093 1094 /* 1095 * Find the kernel lpte for mapping the given virtual address, which 1096 * must be in the part of region 5 which we can cover with our kernel 1097 * 'page tables'. 1098 */ 1099 static struct ia64_lpte * 1100 pmap_find_kpte(vaddr_t va) 1101 { 1102 struct ia64_lpte **dir1; 1103 struct ia64_lpte *leaf; 1104 1105 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1106 UVMHIST_LOG(maphist, "(va=%p)", va, 0, 0, 0); 1107 1108 KASSERTMSG((va >> 61) == 5, "kernel mapping 0x%lx not in region 5", va); 1109 1110 KASSERTMSG(va < kernel_vm_end, "kernel mapping 0x%lx out of range", va); 1111 1112 dir1 = ia64_kptdir[KPTE_DIR0_INDEX(va)]; 1113 leaf = dir1[KPTE_DIR1_INDEX(va)]; 1114 1115 UVMHIST_LOG(maphist, "(kpte_dir0=%#lx, kpte_dir1=%#lx, kpte_pte=%#lx)", 1116 KPTE_DIR0_INDEX(va), KPTE_DIR1_INDEX(va), KPTE_PTE_INDEX(va), 0); 1117 UVMHIST_LOG(maphist, "(dir1=%p, leaf=%p ret=%p)", 1118 dir1, leaf, &leaf[KPTE_PTE_INDEX(va)], 0); 1119 1120 return (&leaf[KPTE_PTE_INDEX(va)]); 1121 } 1122 1123 /* 1124 * Find a pte suitable for mapping a user-space address. If one exists 1125 * in the VHPT, that one will be returned, otherwise a new pte is 1126 * allocated. 1127 */ 1128 static struct ia64_lpte * 1129 pmap_find_pte(vaddr_t va) 1130 { 1131 struct ia64_lpte *pte; 1132 1133 if (va >= VM_MAXUSER_ADDRESS) 1134 return pmap_find_kpte(va); 1135 1136 pte = pmap_find_vhpt(va); 1137 if (pte == NULL) { 1138 pte = pool_cache_get(pte_pool_cache, PR_NOWAIT); 1139 if (pte != NULL) { 1140 memset((void *)pte, 0, sizeof(struct ia64_lpte)); 1141 pte->tag = 1UL << 63; 1142 } 1143 } 1144 1145 return (pte); 1146 } 1147 1148 /* 1149 * Free a pte which is now unused. This simply returns it to the zone 1150 * allocator if it is a user mapping. For kernel mappings, clear the 1151 * valid bit to make it clear that the mapping is not currently used. 1152 */ 1153 static void 1154 pmap_free_pte(struct ia64_lpte *pte, vaddr_t va) 1155 { 1156 if (va < VM_MAXUSER_ADDRESS) 1157 pool_cache_put(pte_pool_cache, pte); 1158 else 1159 pmap_clear_present(pte); 1160 } 1161 1162 static PMAP_INLINE void 1163 pmap_pte_prot(pmap_t pm, struct ia64_lpte *pte, vm_prot_t prot) 1164 { 1165 static long prot2ar[4] = { 1166 PTE_AR_R, /* VM_PROT_NONE */ 1167 PTE_AR_RW, /* VM_PROT_WRITE */ 1168 PTE_AR_RX|PTE_ED, /* VM_PROT_EXECUTE */ 1169 PTE_AR_RWX|PTE_ED /* VM_PROT_WRITE|VM_PROT_EXECUTE */ 1170 }; 1171 1172 pte->pte &= ~(PTE_PROT_MASK | PTE_PL_MASK | PTE_AR_MASK | PTE_ED); 1173 pte->pte |= (uint64_t)(prot & VM_PROT_ALL) << 56; 1174 pte->pte |= (prot == VM_PROT_NONE || pm == kernel_pmap) 1175 ? PTE_PL_KERN : PTE_PL_USER; 1176 pte->pte |= prot2ar[(prot & VM_PROT_ALL) >> 1]; 1177 } 1178 1179 static PMAP_INLINE void 1180 pmap_pte_attr(struct ia64_lpte *pte, vm_memattr_t ma) 1181 { 1182 pte->pte &= ~PTE_MA_MASK; 1183 pte->pte |= (ma & PTE_MA_MASK); 1184 } 1185 1186 /* 1187 * Set a pte to contain a valid mapping and enter it in the VHPT. If 1188 * the pte was originally valid, then its assumed to already be in the 1189 * VHPT. 1190 * This functions does not set the protection bits. It's expected 1191 * that those have been set correctly prior to calling this function. 1192 */ 1193 static void 1194 pmap_set_pte(struct ia64_lpte *pte, vaddr_t va, vaddr_t pa, 1195 bool wired, bool managed) 1196 { 1197 pte->pte &= PTE_PROT_MASK | PTE_MA_MASK | PTE_PL_MASK | 1198 PTE_AR_MASK | PTE_ED; 1199 pte->pte |= PTE_PRESENT; 1200 pte->pte |= (managed) ? PTE_MANAGED : (PTE_DIRTY | PTE_ACCESSED); 1201 pte->pte |= (wired) ? PTE_WIRED : 0; 1202 pte->pte |= pa & PTE_PPN_MASK; 1203 1204 pte->itir = PAGE_SHIFT << 2; 1205 1206 ia64_mf(); 1207 1208 pte->tag = ia64_ttag(va); 1209 } 1210 1211 /* 1212 * Remove the (possibly managed) mapping represented by pte from the 1213 * given pmap. 1214 */ 1215 static int 1216 pmap_remove_pte(pmap_t pmap, struct ia64_lpte *pte, vaddr_t va, 1217 pv_entry_t pv, int freepte) 1218 { 1219 int error; 1220 struct vm_page *m; 1221 1222 /* 1223 * First remove from the VHPT. 1224 */ 1225 error = pmap_remove_vhpt(va); 1226 KASSERTMSG(error == 0, "%s: pmap_remove_vhpt returned %d",__func__, error); 1227 1228 pmap_invalidate_page(va); 1229 1230 if (pmap_wired(pte)) 1231 pmap->pm_stats.wired_count -= 1; 1232 1233 pmap->pm_stats.resident_count -= 1; 1234 if (pmap_managed(pte)) { 1235 m = PHYS_TO_VM_PAGE(pmap_ppn(pte)); 1236 if (pmap_dirty(pte)) 1237 vm_page_dirty(m); 1238 1239 error = pmap_remove_entry(pmap, m, va, pv); 1240 } 1241 if (freepte) 1242 pmap_free_pte(pte, va); 1243 1244 return (error); 1245 } 1246 1247 /* 1248 * pmap_init: [ INTERFACE ] 1249 * 1250 * Initialize the pmap module. Called by vm_init(), to initialize any 1251 * structures that the pmap system needs to map virtual memory. 1252 * 1253 * Note: no locking is necessary in this function. 1254 */ 1255 void 1256 pmap_init(void) 1257 { 1258 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1259 1260 pmap_pool_cache = pool_cache_init(sizeof(struct pmap), 0, 0, 0, 1261 "pmap_pool_cache", NULL, IPL_VM, 1262 NULL, NULL, NULL); 1263 if (pmap_pool_cache == NULL) 1264 panic("%s cannot allocate pmap pool", __func__); 1265 1266 pte_pool_cache = pool_cache_init(sizeof(struct ia64_lpte), 0, 0, 0, 1267 "pte_pool_cache", NULL, IPL_VM, 1268 NULL, NULL, NULL); 1269 if (pte_pool_cache == NULL) 1270 panic("%s cannot allocate pte pool", __func__); 1271 1272 1273 pmap_initialized = true; 1274 1275 #if DEBUG 1276 if (0) pmap_testout(); 1277 #endif 1278 } 1279 1280 /* 1281 * pmap_virtual_space: [ INTERFACE ] 1282 * 1283 * Define the initial bounds of the kernel virtual address space. 1284 */ 1285 void 1286 pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp) 1287 { 1288 *vstartp = VM_MIN_KERNEL_ADDRESS; 1289 *vendp = VM_MAX_KERNEL_ADDRESS; 1290 } 1291 1292 /* 1293 * pmap_steal_memory: [ INTERFACE ] 1294 * 1295 * Bootstrap memory allocator (alternative to uvm_pageboot_alloc()). 1296 * This function allows for early dynamic memory allocation until the 1297 * virtual memory system has been bootstrapped. After that point, either 1298 * kmem_alloc or malloc should be used. This function works by stealing 1299 * pages from the (to be) managed page pool, then implicitly mapping the 1300 * pages (by using their RR7 addresses) and zeroing them. 1301 * 1302 * It may be used once the physical memory segments have been pre-loaded 1303 * into the vm_physmem[] array. Early memory allocation MUST use this 1304 * interface! This cannot be used after uvm_page_init(), and will 1305 * generate a panic if tried. 1306 * 1307 * Note that this memory will never be freed, and in essence it is wired 1308 * down. 1309 * 1310 * We must adjust *vstartp and/or *vendp iff we use address space 1311 * from the kernel virtual address range defined by pmap_virtual_space(). 1312 * 1313 * Note: no locking is necessary in this function. 1314 */ 1315 vaddr_t 1316 pmap_steal_memory(vsize_t size, vaddr_t *vstartp, vaddr_t *vendp) 1317 { 1318 int npgs; 1319 uvm_physseg_t upm; 1320 vaddr_t va; 1321 paddr_t pa; 1322 1323 size = round_page(size); 1324 npgs = atop(size); 1325 1326 for (upm = uvm_physseg_get_first(); 1327 uvm_physseg_valid_p(upm); 1328 upm = uvm_physseg_get_next(upm)) { 1329 if (uvm.page_init_done == true) 1330 panic("pmap_steal_memory: called _after_ bootstrap"); 1331 1332 if (uvm_physseg_get_avail_start(upm) != uvm_physseg_get_start(upm) || 1333 uvm_physseg_get_avail_start(upm) >= uvm_physseg_get_avail_end(upm)) 1334 continue; 1335 1336 if ((uvm_physseg_get_avail_end(upm) - uvm_physseg_get_avail_start(upm)) 1337 < npgs) 1338 continue; 1339 1340 /* 1341 * There are enough pages here; steal them! 1342 */ 1343 pa = ptoa(uvm_physseg_get_start(upm)); 1344 uvm_physseg_unplug(atop(pa), npgs); 1345 1346 va = IA64_PHYS_TO_RR7(pa); 1347 memset((void *)va, 0, size); 1348 pmap_pages_stolen += npgs; 1349 return va; 1350 } 1351 1352 /* 1353 * If we got here, this was no memory left. 1354 */ 1355 panic("pmap_steal_memory: no memory to steal"); 1356 } 1357 1358 /* 1359 * pmap_steal_vhpt_memory: Derived from alpha/pmap.c:pmap_steal_memory() 1360 * Note: This function is not visible outside the pmap module. 1361 * Based on pmap_steal_memory(); 1362 * Assumptions: size is always a power of 2. 1363 * Returns: Allocated memory at a naturally aligned address 1364 */ 1365 static vaddr_t 1366 pmap_steal_vhpt_memory(vsize_t size) 1367 { 1368 int npgs; 1369 uvm_physseg_t upm; 1370 vaddr_t va; 1371 paddr_t pa = 0; 1372 paddr_t vhpt_start = 0, start1, start2, end1, end2; 1373 1374 size = round_page(size); 1375 npgs = atop(size); 1376 1377 for (upm = uvm_physseg_get_first(); 1378 uvm_physseg_valid_p(upm); 1379 upm = uvm_physseg_get_next(upm)) { 1380 if (uvm.page_init_done == true) 1381 panic("pmap_vhpt_steal_memory: called _after_ bootstrap"); 1382 1383 if (uvm_physseg_get_avail_start(upm) != uvm_physseg_get_start(upm) || /* XXX: ??? */ 1384 uvm_physseg_get_avail_start(upm) >= uvm_physseg_get_avail_end(upm)) 1385 continue; 1386 1387 /* Break off a VHPT sized, aligned chunk off this segment. */ 1388 1389 start1 = uvm_physseg_get_avail_start(upm); 1390 1391 /* Align requested start address on requested size boundary */ 1392 end1 = vhpt_start = roundup(start1, npgs); 1393 1394 start2 = vhpt_start + npgs; 1395 end2 = uvm_physseg_get_avail_end(upm); 1396 1397 /* Case 1: Doesn't fit. skip this segment */ 1398 1399 if (start2 > end2) { 1400 vhpt_start = 0; 1401 continue; 1402 } 1403 1404 /* For all cases of fit: 1405 * - Remove segment. 1406 * - Re-insert fragments via uvm_page_physload(); 1407 */ 1408 1409 /* 1410 * We _fail_ on a vhpt request which exhausts memory. 1411 */ 1412 if (start1 == end1 && 1413 start2 == end2 && 1414 uvm_physseg_get_first() == uvm_physseg_get_last() /* single segment */) { 1415 #ifdef DEBUG 1416 printf("pmap_vhpt_steal_memory: out of memory!"); 1417 #endif 1418 return -1; 1419 } 1420 1421 /* Remove this segment from the list. */ 1422 if (uvm_physseg_unplug(uvm_physseg_get_start(upm), 1423 uvm_physseg_get_end(upm) - uvm_physseg_get_start(upm)) == false) { 1424 panic("%s: uvm_physseg_unplug(%"PRIxPADDR", %"PRIxPADDR") failed\n", 1425 __func__, uvm_physseg_get_start(upm), 1426 uvm_physseg_get_end(upm) - uvm_physseg_get_start(upm)); 1427 } 1428 1429 /* Case 2: Perfect fit - skip segment reload. */ 1430 1431 if (start1 == end1 && start2 == end2) break; 1432 1433 /* Case 3: Left unfit - reload it. 1434 */ 1435 1436 if (start1 != end1) 1437 uvm_page_physload(start1, end1, start1, end1, 1438 VM_FREELIST_DEFAULT); 1439 1440 /* Case 4: Right unfit - reload it. */ 1441 1442 if (start2 != end2) 1443 uvm_page_physload(start2, end2, start2, end2, 1444 VM_FREELIST_DEFAULT); 1445 1446 /* Case 5: Both unfit - Redundant, isn't it ? */ 1447 break; 1448 } 1449 1450 /* 1451 * If we got here, we couldn't find a fit. 1452 */ 1453 if (vhpt_start == 0) { 1454 #ifdef DEBUG 1455 printf("pmap_steal_vhpt_memory: no VHPT aligned fit found."); 1456 #endif 1457 return -1; 1458 } 1459 1460 /* 1461 * There are enough pages here; steal them! 1462 */ 1463 pa = ptoa(vhpt_start); 1464 va = IA64_PHYS_TO_RR7(pa); 1465 memset((void *)va, 0, size); 1466 pmap_pages_stolen += npgs; 1467 return va; 1468 } 1469 1470 /* 1471 * pmap_create: [ INTERFACE ] 1472 * 1473 * Create and return a physical map. 1474 * 1475 * Note: no locking is necessary in this function. 1476 */ 1477 pmap_t 1478 pmap_create(void) 1479 { 1480 pmap_t pmap; 1481 int i; 1482 1483 pmap = pool_cache_get(pmap_pool_cache, PR_WAITOK); 1484 1485 if (pmap == NULL) 1486 panic("%s no pool", __func__); 1487 1488 PMAP_LOCK_INIT(pmap); 1489 1490 for (i = 0; i < IA64_VM_MINKERN_REGION; i++) 1491 pmap->pm_rid[i] = pmap_allocate_rid(); 1492 1493 TAILQ_INIT(&pmap->pm_pvchunk); 1494 1495 pmap->pm_stats.resident_count = 0; 1496 pmap->pm_stats.wired_count = 0; 1497 1498 pmap->pm_refcount = 1; 1499 1500 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1501 UVMHIST_LOG(maphist, "(pm=%p)", pmap, 0, 0, 0); 1502 1503 return pmap; 1504 } 1505 1506 /* 1507 * pmap_destroy: [ INTERFACE ] 1508 * 1509 * Drop the reference count on the specified pmap, releasing 1510 * all resources if the reference count drops to zero. 1511 */ 1512 void 1513 pmap_destroy(pmap_t pmap) 1514 { 1515 int i; 1516 1517 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1518 UVMHIST_LOG(maphist, "(pm=%p)", pmap, 0, 0, 0); 1519 1520 membar_release(); 1521 if (atomic_dec_64_nv(&pmap->pm_refcount) > 0) 1522 return; 1523 membar_acquire(); 1524 1525 KASSERT(pmap->pm_stats.resident_count == 0); 1526 KASSERT(pmap->pm_stats.wired_count == 0); 1527 1528 KASSERT(TAILQ_EMPTY(&pmap->pm_pvchunk)); /* XXX hmmm */ 1529 KASSERT(!PMAP_LOCKED(pmap)); /* XXX hmmm */ 1530 /*PMAP_LOCK(pmap); */ /* XXX overkill */ 1531 1532 for (i = 0; i < IA64_VM_MINKERN_REGION; i++) 1533 if (pmap->pm_rid[i]) 1534 pmap_free_rid(pmap->pm_rid[i]); 1535 1536 /*PMAP_UNLOCK(pmap);*/ /* XXX hmm */ 1537 PMAP_LOCK_DESTROY(pmap); 1538 1539 pool_cache_put(pmap_pool_cache, pmap); 1540 } 1541 1542 /* 1543 * pmap_reference: [ INTERFACE ] 1544 * 1545 * Add a reference to the specified pmap. 1546 */ 1547 void 1548 pmap_reference(pmap_t pmap) 1549 { 1550 atomic_inc_64(&pmap->pm_refcount); 1551 } 1552 1553 /* 1554 * pmap_resident_count: [ INTERFACE ] 1555 * 1556 * Query the ``resident pages'' statistic for pmap. 1557 */ 1558 long 1559 pmap_resident_count(pmap_t pmap) 1560 { 1561 return (pmap->pm_stats.resident_count); 1562 } 1563 1564 /* 1565 * pmap_wired_count: [ INTERFACE ] 1566 * 1567 * Query the ``wired pages'' statistic for pmap. 1568 * 1569 */ 1570 long 1571 pmap_wired_count(pmap_t pmap) 1572 { 1573 return (pmap->pm_stats.wired_count); 1574 } 1575 1576 /* 1577 * pmap_growkernel: [ INTERFACE ] 1578 * 1579 */ 1580 vaddr_t 1581 pmap_growkernel(vaddr_t maxkvaddr) 1582 { 1583 struct ia64_lpte **dir1; 1584 struct ia64_lpte *leaf; 1585 struct vm_page *pg; 1586 #if 0 1587 struct vm_page *nkpg; 1588 paddr_t pa; 1589 vaddr_t va; 1590 #endif 1591 1592 /* XXX this function may still need serious fixin' */ 1593 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1594 UVMHIST_LOG(maphist, "(va=%#lx, nkpt=%ld, kvm_end=%#lx before)", maxkvaddr, nkpt, kernel_vm_end, 0); 1595 1596 vaddr_t addr = maxkvaddr; 1597 1598 /* XXX use uvm_pageboot_alloc if not done? */ 1599 if (!uvm.page_init_done) 1600 panic("uvm_page init not done"); 1601 1602 while (kernel_vm_end <= addr) { 1603 if (nkpt == PAGE_SIZE/8 + PAGE_SIZE*PAGE_SIZE/64) 1604 panic("%s: out of kernel address space", __func__); 1605 dir1 = ia64_kptdir[KPTE_DIR0_INDEX(kernel_vm_end)]; 1606 1607 if (dir1 == NULL) { 1608 #if 0 1609 /* FreeBSD does it this way... */ 1610 nkpg = vm_page_alloc(NULL, nkpt++, VM_ALLOC_NOOBJ|VM_ALLOC_INTERRUPT|VM_ALLOC_WIRED); 1611 pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE|UVM_PGA_ZERO); 1612 #endif 1613 pg = vm_page_alloc1(); 1614 if (!pg) 1615 panic("%s: cannot add dir1 page", __func__); 1616 nkpt++; 1617 1618 #if 0 1619 dir1 = (struct ia64_lpte **)pmap_page_to_va(nkpg); 1620 bzero(dir1, PAGE_SIZE); 1621 #endif 1622 dir1 = (struct ia64_lpte **)pmap_page_to_va(pg); 1623 1624 ia64_kptdir[KPTE_DIR0_INDEX(kernel_vm_end)] = dir1; 1625 } 1626 1627 #if 0 1628 nkpg = vm_page_alloc(NULL, nkpt++, VM_ALLOC_NOOBJ|VM_ALLOC_INTERRUPT|VM_ALLOC_WIRED); 1629 pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE|UVM_PGA_ZERO); 1630 #endif 1631 pg = vm_page_alloc1(); 1632 if (!pg) 1633 panic("%s: cannot add PTE page", __func__); 1634 nkpt++; 1635 #if 0 1636 leaf = (struct ia64_lpte *)pmap_page_to_va(nkpg); 1637 bzero(leaf, PAGE_SIZE); 1638 #endif 1639 leaf = (struct ia64_lpte *)pmap_page_to_va(pg); 1640 1641 dir1[KPTE_DIR1_INDEX(kernel_vm_end)] = leaf; 1642 1643 kernel_vm_end += PAGE_SIZE * NKPTEPG; 1644 } 1645 1646 UVMHIST_LOG(maphist, "(va=%#lx, nkpt=%ld, kvm_end=%#lx after)", maxkvaddr, nkpt, kernel_vm_end, 0); 1647 1648 /* XXX fix */ 1649 return kernel_vm_end; 1650 } 1651 1652 /* 1653 * pmap_enter: [ INTERFACE ] 1654 * 1655 * Create a mapping in physical map pmap for the physical 1656 * address pa at the virtual address va with protection speci- 1657 * fied by bits in prot. 1658 */ 1659 int 1660 pmap_enter(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags) 1661 { 1662 pmap_t oldpmap; 1663 struct vm_page *m; 1664 vaddr_t opa; 1665 struct ia64_lpte origpte; 1666 struct ia64_lpte *pte; 1667 bool icache_inval, managed, wired, canfail; 1668 /* vm_memattr_t ma; */ 1669 1670 /* XXX this needs work */ 1671 1672 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1673 UVMHIST_LOG(maphist, "(pm=%p, va=%#lx, pa=%p, prot=%#x)", pmap, va, pa, prot); 1674 1675 /* wired = (flags & PMAP_ENTER_WIRED) != 0; */ 1676 wired = (flags & PMAP_WIRED) != 0; 1677 canfail = (flags & PMAP_CANFAIL) != 0; 1678 1679 /* ma = pmap_flags_to_memattr(flags); */ 1680 1681 rw_enter(&pvh_global_lock, RW_WRITER); 1682 PMAP_LOCK(pmap); 1683 oldpmap = pmap_switch(pmap); 1684 1685 va &= ~PAGE_MASK; 1686 KASSERTMSG(va <= VM_MAX_KERNEL_ADDRESS, "%s: toobig", __func__); 1687 1688 /* XXX 1689 if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m)) 1690 VM_OBJECT_ASSERT_LOCKED(m->object); 1691 */ 1692 1693 /* 1694 * Find (or create) a pte for the given mapping. 1695 */ 1696 pte = pmap_find_pte(va); 1697 1698 if (pte == NULL) { 1699 pmap_switch(oldpmap); 1700 PMAP_UNLOCK(pmap); 1701 rw_exit(&pvh_global_lock); 1702 1703 if (canfail) 1704 return (ENOMEM); 1705 else 1706 panic("%s: no pte available", __func__); 1707 } 1708 1709 origpte = *pte; 1710 if (!pmap_present(pte)) { 1711 opa = ~0UL; 1712 pmap_enter_vhpt(pte, va); 1713 } else 1714 opa = pmap_ppn(pte); 1715 1716 managed = false; 1717 /* XXX hmm 1718 pa = VM_PAGE_TO_PHYS(m); 1719 */ 1720 1721 m = PHYS_TO_VM_PAGE(pa); 1722 if (m == NULL) { 1723 /* implies page not managed? */ 1724 panic("%s: new page needed", __func__); 1725 } 1726 icache_inval = (prot & VM_PROT_EXECUTE) ? true : false; 1727 1728 /* 1729 * Mapping has not changed, must be protection or wiring change. 1730 */ 1731 if (opa == pa) { 1732 /* 1733 * Wiring change, just update stats. We don't worry about 1734 * wiring PT pages as they remain resident as long as there 1735 * are valid mappings in them. Hence, if a user page is wired, 1736 * the PT page will be also. 1737 */ 1738 if (wired && !pmap_wired(&origpte)) 1739 pmap->pm_stats.wired_count++; 1740 else if (!wired && pmap_wired(&origpte)) 1741 pmap->pm_stats.wired_count--; 1742 1743 managed = (pmap_managed(&origpte)) ? true : false; 1744 1745 /* 1746 * We might be turning off write access to the page, 1747 * so we go ahead and sense modify status. Otherwise, 1748 * we can avoid I-cache invalidation if the page 1749 * already allowed execution. 1750 */ 1751 if (managed && pmap_dirty(&origpte)) 1752 vm_page_dirty(m); 1753 else if (pmap_exec(&origpte)) 1754 icache_inval = false; 1755 1756 pmap_invalidate_page(va); 1757 goto validate; 1758 } 1759 1760 /* 1761 * Mapping has changed, invalidate old range and fall 1762 * through to handle validating new mapping. 1763 */ 1764 if (opa != ~0UL) { 1765 pmap_remove_pte(pmap, pte, va, 0, 0); 1766 pmap_enter_vhpt(pte, va); 1767 } 1768 1769 /* 1770 * Enter on the PV list if part of our managed memory. 1771 */ 1772 if (vm_page_is_managed(m)) { 1773 #if 0 1774 KASSERTMSG(va < kmi.clean_sva || va >= kmi.clean_eva, 1775 ("pmap_enter: managed mapping within the clean submap")); 1776 #endif 1777 pmap_insert_entry(pmap, va, m); 1778 managed = true; 1779 } 1780 1781 /* 1782 * Increment counters 1783 */ 1784 pmap->pm_stats.resident_count++; 1785 if (wired) 1786 pmap->pm_stats.wired_count++; 1787 1788 validate: 1789 1790 /* 1791 * Now validate mapping with desired protection/wiring. This 1792 * adds the pte to the VHPT if necessary. 1793 */ 1794 pmap_pte_prot(pmap, pte, prot); 1795 pmap_pte_attr(pte, m->mdpage.memattr); 1796 pmap_set_pte(pte, va, pa, wired, managed); 1797 1798 /* Invalidate the I-cache when needed. */ 1799 if (icache_inval) 1800 ia64_sync_icache(va, PAGE_SIZE); 1801 1802 /* XXX 1803 if ((prot & VM_PROT_WRITE) != 0 && managed) 1804 //vm_page_aflag_set(m, PGA_WRITEABLE); 1805 m->flags &= ~PG_RDONLY; 1806 */ 1807 rw_exit(&pvh_global_lock); 1808 pmap_switch(oldpmap); 1809 PMAP_UNLOCK(pmap); 1810 return (0); 1811 } 1812 1813 /* 1814 * pmap_remove: [ INTERFACE ] 1815 * 1816 * Remove the given range of addresses from the specified map. 1817 * 1818 * It is assumed that the start and end are properly 1819 * rounded to the page size. 1820 * 1821 * Sparsely used ranges are inefficiently removed. The VHPT is 1822 * probed for every page within the range. XXX 1823 */ 1824 void 1825 pmap_remove(pmap_t pmap, vaddr_t sva, vaddr_t eva) 1826 { 1827 pmap_t oldpmap; 1828 vaddr_t va; 1829 struct ia64_lpte *pte; 1830 1831 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1832 UVMHIST_LOG(maphist, "(pm=%p, sva=%#lx, eva=%#lx)", pmap, sva, eva, 0); 1833 1834 /* 1835 * Perform an unsynchronized read. This is, however, safe. 1836 */ 1837 if (pmap->pm_stats.resident_count == 0) 1838 return; 1839 1840 rw_enter(&pvh_global_lock, RW_WRITER); 1841 PMAP_LOCK(pmap); 1842 oldpmap = pmap_switch(pmap); 1843 for (va = sva; va < eva; va += PAGE_SIZE) { 1844 pte = pmap_find_vhpt(va); 1845 if (pte != NULL) 1846 pmap_remove_pte(pmap, pte, va, 0, 1); 1847 } 1848 1849 rw_exit(&pvh_global_lock); 1850 pmap_switch(oldpmap); 1851 PMAP_UNLOCK(pmap); 1852 } 1853 1854 /* 1855 * pmap_remove_all: [ INTERFACE ] 1856 * 1857 * This function is a hint to the pmap implementation that all 1858 * entries in pmap will be removed before any more entries are 1859 * entered. 1860 */ 1861 bool 1862 pmap_remove_all(pmap_t pmap) 1863 { 1864 /* XXX do nothing */ 1865 return false; 1866 } 1867 1868 /* 1869 * pmap_protect: [ INTERFACE ] 1870 * 1871 * Set the physical protection on the specified range of this map 1872 * as requested. 1873 */ 1874 void 1875 pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot) 1876 { 1877 pmap_t oldpmap; 1878 struct ia64_lpte *pte; 1879 1880 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1881 UVMHIST_LOG(maphist, "(pm=%p, sva=%#lx, eva=%#lx, prot=%#x)", 1882 pmap, sva, eva, prot); 1883 UVMHIST_LOG(maphist, "(VM_PROT_READ=%u, VM_PROT_WRITE=%u, VM_PROT_EXECUTE=%u)", 1884 (prot & VM_PROT_READ) != 0, (prot & VM_PROT_WRITE) != 0, 1885 (prot & VM_PROT_EXECUTE) != 0, 0); 1886 1887 if ((prot & VM_PROT_READ) == VM_PROT_NONE) { 1888 pmap_remove(pmap, sva, eva); 1889 return; 1890 } 1891 1892 if ((prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) == 1893 (VM_PROT_WRITE|VM_PROT_EXECUTE)) 1894 return; 1895 1896 if ((sva & PAGE_MASK) || (eva & PAGE_MASK)) 1897 panic("pmap_protect: unaligned addresses"); 1898 sva = trunc_page(sva); 1899 eva = round_page(eva) - 1; 1900 1901 PMAP_LOCK(pmap); 1902 oldpmap = pmap_switch(pmap); 1903 for ( ; sva < eva; sva += PAGE_SIZE) { 1904 /* If page is invalid, skip this page */ 1905 pte = pmap_find_vhpt(sva); 1906 if (pte == NULL) 1907 continue; 1908 1909 /* If there's no change, skip it too */ 1910 if (pmap_prot(pte) == prot) 1911 continue; 1912 1913 /* wired pages unaffected by prot changes */ 1914 if (pmap_wired(pte)) 1915 continue; 1916 1917 if ((prot & VM_PROT_WRITE) == 0 && 1918 pmap_managed(pte) && pmap_dirty(pte)) { 1919 paddr_t pa = pmap_ppn(pte); 1920 struct vm_page *m = PHYS_TO_VM_PAGE(pa); 1921 1922 vm_page_dirty(m); 1923 pmap_clear_dirty(pte); 1924 } 1925 1926 if (prot & VM_PROT_EXECUTE) 1927 ia64_sync_icache(sva, PAGE_SIZE); 1928 1929 pmap_pte_prot(pmap, pte, prot); 1930 pmap_invalidate_page(sva); 1931 } 1932 pmap_switch(oldpmap); 1933 PMAP_UNLOCK(pmap); 1934 } 1935 1936 /* 1937 * pmap_unwire: [ INTERFACE ] 1938 * 1939 * Clear the wired attribute for a map/virtual-address pair. 1940 * 1941 * The wired attribute of the page table entry is not a hardware feature, 1942 * so there is no need to invalidate any TLB entries. 1943 * 1944 * The mapping must already exist in the pmap. 1945 */ 1946 void 1947 pmap_unwire(pmap_t pmap, vaddr_t va) 1948 { 1949 pmap_t oldpmap; 1950 struct ia64_lpte *pte; 1951 1952 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1953 UVMHIST_LOG(maphist, "(pm=%p, va=%#x)", pmap, va, 0, 0); 1954 1955 PMAP_LOCK(pmap); 1956 oldpmap = pmap_switch(pmap); 1957 1958 pte = pmap_find_vhpt(va); 1959 1960 /* XXX panic if no pte or not wired? */ 1961 if (pte == NULL) 1962 panic("pmap_unwire: %lx not found in vhpt", va); 1963 1964 if (!pmap_wired(pte)) 1965 panic("pmap_unwire: pte %p isn't wired", pte); 1966 1967 pmap->pm_stats.wired_count--; 1968 pmap_clear_wired(pte); 1969 1970 pmap_switch(oldpmap); 1971 PMAP_UNLOCK(pmap); 1972 } 1973 1974 /* 1975 * pmap_extract: [ INTERFACE ] 1976 * 1977 * Extract the physical address associated with the given 1978 * pmap/virtual address pair. 1979 */ 1980 bool 1981 pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap) 1982 { 1983 struct ia64_lpte *pte; 1984 pmap_t oldpmap; 1985 paddr_t pa; 1986 1987 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 1988 UVMHIST_LOG(maphist, "(pm=%p, va=%#lx, pap=%#lx)", pmap, va, pap, 0); 1989 1990 pa = 0; 1991 1992 PMAP_LOCK(pmap); 1993 oldpmap = pmap_switch(pmap); 1994 pte = pmap_find_vhpt(va); 1995 if (pte != NULL && pmap_present(pte)) 1996 pa = pmap_ppn(pte); 1997 pmap_switch(oldpmap); 1998 PMAP_UNLOCK(pmap); 1999 2000 if (pa && (pap != NULL)) 2001 *pap = pa; 2002 2003 UVMHIST_LOG(maphist, "(pa=%#lx)", pa, 0, 0, 0); 2004 2005 return (pa != 0); 2006 } 2007 /* 2008 * Extract the physical page address associated with a kernel 2009 * virtual address. 2010 */ 2011 paddr_t 2012 pmap_kextract(vaddr_t va) 2013 { 2014 struct ia64_lpte *pte; 2015 /*uint64_t *pbvm_pgtbl;*/ 2016 paddr_t pa; 2017 /*u_int idx;*/ 2018 2019 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2020 UVMHIST_LOG(maphist, "(va=%#lx)", va, 0, 0, 0); 2021 2022 KASSERTMSG(va >= VM_MAXUSER_ADDRESS, "Must be kernel VA"); 2023 2024 /* Regions 6 and 7 are direct mapped. */ 2025 if (va >= IA64_RR_BASE(6)) { 2026 pa = IA64_RR_MASK(va); 2027 goto out; 2028 } 2029 2030 /* Region 5 is our KVA. Bail out if the VA is beyond our limits. */ 2031 if (va >= kernel_vm_end) 2032 goto err_out; 2033 if (va >= VM_INIT_KERNEL_ADDRESS) { 2034 pte = pmap_find_kpte(va); 2035 pa = pmap_present(pte) ? pmap_ppn(pte) | (va & PAGE_MASK) : 0; 2036 goto out; 2037 } 2038 #if 0 /* XXX fix */ 2039 /* The PBVM page table. */ 2040 if (va >= IA64_PBVM_PGTBL + bootinfo->bi_pbvm_pgtblsz) 2041 goto err_out; 2042 if (va >= IA64_PBVM_PGTBL) { 2043 pa = (va - IA64_PBVM_PGTBL) + bootinfo->bi_pbvm_pgtbl; 2044 goto out; 2045 } 2046 2047 /* The PBVM itself. */ 2048 if (va >= IA64_PBVM_BASE) { 2049 pbvm_pgtbl = (void *)IA64_PBVM_PGTBL; 2050 idx = (va - IA64_PBVM_BASE) >> IA64_PBVM_PAGE_SHIFT; 2051 if (idx >= (bootinfo->bi_pbvm_pgtblsz >> 3)) 2052 goto err_out; 2053 if ((pbvm_pgtbl[idx] & PTE_PRESENT) == 0) 2054 goto err_out; 2055 pa = (pbvm_pgtbl[idx] & PTE_PPN_MASK) + 2056 (va & IA64_PBVM_PAGE_MASK); 2057 goto out; 2058 } 2059 #endif 2060 2061 err_out: 2062 KASSERT(1); 2063 printf("XXX: %s: va=%#lx is invalid\n", __func__, va); 2064 pa = 0; 2065 /* FALLTHROUGH */ 2066 2067 out: 2068 UVMHIST_LOG(maphist, "(pa=%#lx)", pa, 0, 0, 0); 2069 return (pa); 2070 } 2071 2072 /* 2073 * pmap_kenter_pa: [ INTERFACE ] 2074 * 2075 * Enter a va -> pa mapping into the kernel pmap without any 2076 * physical->virtual tracking. 2077 * 2078 * Note: no locking is necessary in this function. 2079 */ 2080 void 2081 pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags) 2082 { 2083 struct ia64_lpte *pte; 2084 vm_memattr_t attr; 2085 const bool managed = false; /* don't gather ref/mod info */ 2086 const bool wired = true; /* pmap_kenter_pa always wired */ 2087 2088 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2089 UVMHIST_LOG(maphist, "(va=%#lx, pa=%#lx, prot=%p, flags=%p)", va, pa, prot, flags); 2090 2091 KASSERT(va >= VM_MIN_KERNEL_ADDRESS && va < VM_MAX_KERNEL_ADDRESS); 2092 2093 attr = pmap_flags_to_memattr(flags); 2094 2095 pte = pmap_find_kpte(va); 2096 if (pmap_present(pte)) 2097 pmap_invalidate_page(va); 2098 else 2099 pmap_enter_vhpt(pte, va); 2100 2101 pmap_pte_prot(kernel_pmap, pte, VM_PROT_ALL); 2102 pmap_pte_attr(pte, attr); 2103 pmap_set_pte(pte, va, pa, wired, managed); 2104 } 2105 2106 /* 2107 * pmap_kremove: [ INTERFACE ] 2108 * 2109 * Remove all mappings starting at virtual address va for size 2110 * bytes from the kernel physical map. All mappings that are 2111 * removed must be the ``unmanaged'' type created with 2112 * pmap_kenter_pa(). The implementation may assert this. 2113 */ 2114 void 2115 pmap_kremove(vaddr_t va, vsize_t size) 2116 { 2117 struct ia64_lpte *pte; 2118 vaddr_t eva = va + size; 2119 2120 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2121 UVMHIST_LOG(maphist, "(va=%#lx)", va, 0, 0, 0); 2122 2123 while (va < eva) { 2124 pte = pmap_find_kpte(va); 2125 if (pmap_present(pte)) { 2126 KASSERT(pmap_managed(pte) != 0); 2127 pmap_remove_vhpt(va); 2128 pmap_invalidate_page(va); 2129 pmap_clear_present(pte); 2130 } 2131 va += PAGE_SIZE; 2132 } 2133 } 2134 2135 /* 2136 * pmap_copy: [ INTERFACE ] 2137 * 2138 * This function copies the mappings starting at src_addr in 2139 * src_map for len bytes into dst_map starting at dst_addr. 2140 * 2141 * Note that while this function is required to be provided by 2142 * a pmap implementation, it is not actually required to do 2143 * anything. pmap_copy() is merely advisory (it is used in 2144 * the fork(2) path to ``pre-fault'' the child's address 2145 * space). 2146 */ 2147 void 2148 pmap_copy(pmap_t dst_map, pmap_t src_map, vaddr_t dst_addr, vsize_t len, 2149 vaddr_t src_addr) 2150 { 2151 /* nothing required */ 2152 } 2153 2154 /* 2155 * pmap_update: [ INTERFACE ] 2156 * 2157 * If a pmap implementation does not delay virtual-to-physical 2158 * mapping updates, pmap_update() has no operation. 2159 */ 2160 void 2161 pmap_update(pmap_t pmap) 2162 { 2163 /* nothing required */ 2164 } 2165 2166 /* 2167 * pmap_activate: [ INTERFACE ] 2168 * 2169 * Activate the pmap used by the specified process. This includes 2170 * reloading the MMU context if the current process, and marking 2171 * the pmap in use by the processor. 2172 * 2173 * Note: We may use only spin locks here, since we are called 2174 * by a critical section in cpu_switch()! 2175 */ 2176 void 2177 pmap_activate(struct lwp *l) 2178 { 2179 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2180 UVMHIST_LOG(maphist, "(lwp=%p)", l, 0, 0, 0); 2181 KASSERT(l == curlwp); 2182 #if 0 2183 /* pmap_switch(vmspace_pmap(td->td_proc->p_vmspace)); */ 2184 pmap_switch(vm_map_pmap(&l->l_proc->p_vmspace->vm_map)); 2185 #else 2186 struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap; 2187 2188 if (pmap == pmap_kernel()) { 2189 return; 2190 } 2191 2192 if (l != curlwp) { 2193 return; 2194 } 2195 2196 pmap_switch(pmap); 2197 #endif 2198 } 2199 2200 /* 2201 * pmap_deactivate: [ INTERFACE ] 2202 * 2203 * Deactivate the physical map used by the process behind lwp 2204 * l. It is generally used in conjunction with 2205 * pmap_activate(). Like pmap_activate(), pmap_deactivate() 2206 * may not always be called when l is the current lwp. 2207 * 2208 */ 2209 void 2210 pmap_deactivate(struct lwp *l) 2211 { 2212 /* XXX ? */ 2213 } 2214 2215 /* 2216 * pmap_zero_page: [ INTERFACE ] 2217 * 2218 * Zero the specified (machine independent) page by mapping the page 2219 * into virtual memory and clear its contents, one machine dependent 2220 * page at a time. 2221 * 2222 * Note: no locking is necessary in this function. 2223 */ 2224 void 2225 pmap_zero_page(paddr_t phys) 2226 { 2227 struct vm_page *m; 2228 vaddr_t va; 2229 2230 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2231 UVMHIST_LOG(maphist, "(pa=%p)", phys, 0, 0, 0); 2232 2233 m = PHYS_TO_VM_PAGE(phys); 2234 KASSERT(m != NULL); 2235 2236 va = pmap_page_to_va(m); 2237 KASSERT(trunc_page(va) == va); 2238 2239 UVMHIST_LOG(maphist, "(pa=%p, va=%p)", phys, va, 0, 0); 2240 memset((void *)va, 0, PAGE_SIZE); 2241 } 2242 2243 /* 2244 * pmap_copy_page: [ INTERFACE ] 2245 * 2246 * Copy the specified (machine independent) page by mapping the page 2247 * into virtual memory and using memcpy to copy the page, one machine 2248 * dependent page at a time. 2249 * 2250 * Note: no locking is necessary in this function. 2251 */ 2252 void 2253 pmap_copy_page(paddr_t psrc, paddr_t pdst) 2254 { 2255 struct vm_page *md, *ms; 2256 vaddr_t dst_va, src_va; 2257 2258 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2259 UVMHIST_LOG(maphist, "(sp=%p, dp=%p)", psrc, pdst, 0, 0); 2260 2261 md = PHYS_TO_VM_PAGE(pdst); 2262 ms = PHYS_TO_VM_PAGE(psrc); 2263 KASSERT(md != NULL && ms != NULL); 2264 2265 dst_va = pmap_page_to_va(md); 2266 src_va = pmap_page_to_va(ms); 2267 KASSERT(trunc_page(dst_va) == dst_va && trunc_page(src_va) == src_va); 2268 2269 memcpy((void *)dst_va, (void *)src_va, PAGE_SIZE); 2270 } 2271 2272 /* 2273 * pmap_page_protect: [ INTERFACE ] 2274 * 2275 * Lower the permissions for all mappings of the page pg to 2276 * prot. This function is used by the virtual memory system 2277 * to implement copy-on-write (called with VM_PROT_READ set in 2278 * prot) and to revoke all mappings when cleaning a page 2279 * (called with no bits set in prot). Access permissions must 2280 * never be added to a page as a result of this call. 2281 */ 2282 void 2283 pmap_page_protect(struct vm_page *pg, vm_prot_t prot) 2284 { 2285 //struct ia64_lpte *pte; 2286 pmap_t pmap; 2287 pv_entry_t pv; 2288 vaddr_t va; 2289 2290 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2291 UVMHIST_LOG(maphist, "(m=%p, prot=%p)", pg, prot, 0, 0); 2292 2293 if ((prot & VM_PROT_WRITE) != 0) 2294 return; 2295 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) { 2296 /* XXX FreeBSD 2297 if ((pg->mdpage.aflags & PGA_WRITEABLE) == 0) 2298 return; 2299 */ 2300 if (pg->flags & PG_RDONLY) 2301 return; 2302 rw_enter(&pvh_global_lock, RW_WRITER); 2303 TAILQ_FOREACH(pv, &pg->mdpage.pv_list, pv_list) { 2304 pmap = PV_PMAP(pv); 2305 va = pv->pv_va; 2306 // locking of pmap done in pmap_protect 2307 pmap_protect(pmap, va, va + PAGE_SIZE, prot); 2308 } 2309 /* XXX 2310 vm_page_aflag_clear(pg, PGA_WRITEABLE); 2311 */ 2312 pg->flags |= PG_RDONLY; 2313 2314 rw_exit(&pvh_global_lock); 2315 } else { 2316 pmap_remove_all_phys(pg); 2317 } 2318 } 2319 2320 /* 2321 * pmap_clear_modify: [ INTERFACE ] 2322 * 2323 * Clear the modify bits on the specified physical page. 2324 */ 2325 bool 2326 pmap_clear_modify(struct vm_page *pg) 2327 { 2328 struct ia64_lpte *pte; 2329 pmap_t oldpmap, pmap; 2330 pv_entry_t pv; 2331 bool rv; 2332 2333 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2334 UVMHIST_LOG(maphist, "(m=%p)", pg, 0, 0, 0); 2335 2336 KASSERTMSG(vm_page_is_managed(pg), "%s : page %p not managed", 2337 __func__, pg); 2338 2339 rv = false; 2340 2341 //VM_OBJECT_ASSERT_WLOCKED(m->object); 2342 //KASSERT(!vm_page_xbusied(m), 2343 // ("pmap_clear_modify: page %p is exclusive busied", m)); 2344 2345 /* 2346 * If the page is not PGA_WRITEABLE, then no PTEs can be modified. 2347 * If the object containing the page is locked and the page is not 2348 * exclusive busied, then PGA_WRITEABLE cannot be concurrently set. 2349 */ 2350 2351 #if 0 /* XXX freebsd does this, looks faster but not required */ 2352 if ((m->aflags & PGA_WRITEABLE) == 0) 2353 return; 2354 if (pg->flags & PG_RDONLY) 2355 return (rv); 2356 #endif 2357 rw_enter(&pvh_global_lock, RW_WRITER); 2358 TAILQ_FOREACH(pv, &pg->mdpage.pv_list, pv_list) { 2359 pmap = PV_PMAP(pv); 2360 PMAP_LOCK(pmap); 2361 oldpmap = pmap_switch(pmap); 2362 pte = pmap_find_vhpt(pv->pv_va); 2363 KASSERTMSG(pte != NULL, "pte"); 2364 if (pmap_dirty(pte)) { 2365 pmap_clear_dirty(pte); 2366 pmap_invalidate_page(pv->pv_va); 2367 rv = true; 2368 } 2369 pmap_switch(oldpmap); 2370 PMAP_UNLOCK(pmap); 2371 } 2372 2373 rw_exit(&pvh_global_lock); 2374 2375 return (rv); 2376 } 2377 2378 /* 2379 * pmap_clear_reference: [ INTERFACE ] 2380 * 2381 * Clear the reference bit on the specified physical page. 2382 * 2383 * returns true or false 2384 * indicating whether or not the ``referenced'' attribute was 2385 * set on the page before it was cleared 2386 */ 2387 bool 2388 pmap_clear_reference(struct vm_page *pg) 2389 { 2390 struct ia64_lpte *pte; 2391 pmap_t oldpmap, pmap; 2392 pv_entry_t pv; 2393 bool rv; 2394 2395 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2396 UVMHIST_LOG(maphist, "(m=%p)", pg, 0, 0, 0); 2397 2398 KASSERTMSG(vm_page_is_managed(pg), "%s: page %p is not managed", 2399 __func__, pg); 2400 2401 rv = false; 2402 2403 rw_enter(&pvh_global_lock, RW_WRITER); 2404 TAILQ_FOREACH(pv, &pg->mdpage.pv_list, pv_list) { 2405 pmap = PV_PMAP(pv); 2406 PMAP_LOCK(pmap); 2407 oldpmap = pmap_switch(pmap); 2408 pte = pmap_find_vhpt(pv->pv_va); 2409 KASSERTMSG(pte != NULL, "pte"); 2410 if (pmap_accessed(pte)) { 2411 rv = true; 2412 pmap_clear_accessed(pte); 2413 pmap_invalidate_page(pv->pv_va); 2414 } 2415 pmap_switch(oldpmap); 2416 PMAP_UNLOCK(pmap); 2417 } 2418 2419 rw_exit(&pvh_global_lock); 2420 return (rv); 2421 } 2422 2423 /* 2424 * pmap_is_modified: [ INTERFACE ] 2425 * 2426 */ 2427 bool 2428 pmap_is_modified(struct vm_page *pg) 2429 { 2430 struct ia64_lpte *pte; 2431 pmap_t oldpmap, pmap; 2432 pv_entry_t pv; 2433 bool rv; 2434 2435 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2436 UVMHIST_LOG(maphist, "(m=%p)", pg, 0, 0, 0); 2437 2438 KASSERTMSG(vm_page_is_managed(pg), "%s: page %p is not managed", 2439 __func__, pg); 2440 rv = false; 2441 2442 /* 2443 * If the page is not exclusive busied, then PGA_WRITEABLE cannot be 2444 * concurrently set while the object is locked. Thus, if PGA_WRITEABLE 2445 * is clear, no PTEs can be dirty. 2446 */ 2447 /* XXX freebsd 2448 VM_OBJECT_ASSERT_WLOCKED(m->object); 2449 if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0) 2450 return (rv); 2451 */ 2452 rw_enter(&pvh_global_lock, RW_WRITER); 2453 TAILQ_FOREACH(pv, &pg->mdpage.pv_list, pv_list) { 2454 pmap = PV_PMAP(pv); 2455 PMAP_LOCK(pmap); 2456 oldpmap = pmap_switch(pmap); 2457 pte = pmap_find_vhpt(pv->pv_va); 2458 pmap_switch(oldpmap); 2459 KASSERTMSG(pte != NULL, "pte"); 2460 2461 rv = pmap_dirty(pte) ? true : false; 2462 PMAP_UNLOCK(pmap); 2463 if (rv) 2464 break; 2465 } 2466 2467 rw_exit(&pvh_global_lock); 2468 return (rv); 2469 } 2470 2471 /* 2472 * pmap_is_referenced: [ INTERFACE ] 2473 * 2474 * Test whether or not the ``referenced'' attribute is set on 2475 * page pg. 2476 * 2477 */ 2478 bool 2479 pmap_is_referenced(struct vm_page *pg) 2480 { 2481 struct ia64_lpte *pte; 2482 pmap_t oldpmap, pmap; 2483 pv_entry_t pv; 2484 bool rv; 2485 2486 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2487 UVMHIST_LOG(maphist, "(m=%p)", pg, 0, 0, 0); 2488 2489 KASSERTMSG(vm_page_is_managed(pg), "%s: page %p is not managed", 2490 __func__, pg); 2491 2492 rv = false; 2493 rw_enter(&pvh_global_lock, RW_WRITER); 2494 TAILQ_FOREACH(pv, &pg->mdpage.pv_list, pv_list) { 2495 pmap = PV_PMAP(pv); 2496 PMAP_LOCK(pmap); 2497 oldpmap = pmap_switch(pmap); 2498 pte = pmap_find_vhpt(pv->pv_va); 2499 KASSERTMSG(pte != NULL, "pte"); 2500 rv = pmap_accessed(pte) ? true : false; 2501 pmap_switch(oldpmap); 2502 PMAP_UNLOCK(pmap); 2503 if (rv) 2504 break; 2505 } 2506 2507 rw_exit(&pvh_global_lock); 2508 return (rv); 2509 } 2510 2511 /* 2512 * pmap_phys_address: [ INTERFACE ] 2513 * 2514 * Return the physical address corresponding to the specified 2515 * cookie. Used by the device pager to decode a device driver's 2516 * mmap entry point return value. 2517 * 2518 * Note: no locking is necessary in this function. 2519 */ 2520 paddr_t 2521 pmap_phys_address(paddr_t ppn) 2522 { 2523 return ia64_ptob(ppn); 2524 } 2525 2526 pmap_t 2527 pmap_switch(pmap_t pm) 2528 { 2529 pmap_t prevpm; 2530 int i; 2531 2532 critical_enter(); 2533 2534 prevpm = curcpu()->ci_pmap; 2535 if (prevpm == pm) 2536 goto out; 2537 if (pm == NULL) { 2538 for (i = 0; i < IA64_VM_MINKERN_REGION; i++) { 2539 ia64_set_rr(IA64_RR_BASE(i), 2540 (i << 8)|(PAGE_SHIFT << 2)|1); 2541 } 2542 } else { 2543 for (i = 0; i < IA64_VM_MINKERN_REGION; i++) { 2544 ia64_set_rr(IA64_RR_BASE(i), 2545 (pm->pm_rid[i] << 8)|(PAGE_SHIFT << 2)|1); 2546 } 2547 } 2548 2549 /* XXX */ 2550 ia64_srlz_d(); 2551 curcpu()->ci_pmap = pm; 2552 ia64_srlz_d(); 2553 2554 out: 2555 critical_exit(); 2556 return (prevpm); 2557 } 2558 2559 2560 /* 2561 * Synchronize CPU instruction caches of the specified range. 2562 * Same as freebsd 2563 * void pmap_sync_icache(pmap_t pm, vaddr_t va, vsize_t sz) 2564 */ 2565 void 2566 pmap_procwr(struct proc *p, vaddr_t va, vsize_t sz) 2567 { 2568 pmap_t oldpm; 2569 struct ia64_lpte *pte; 2570 vaddr_t lim; 2571 vsize_t len; 2572 2573 struct pmap * const pm = p->p_vmspace->vm_map.pmap; 2574 2575 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2576 UVMHIST_LOG(maphist, "(pm=%p, va=%#lx, sz=%#lx)", pm, va, sz, 0); 2577 2578 sz += va & 31; 2579 va &= ~31; 2580 sz = (sz + 31) & ~31; 2581 2582 PMAP_LOCK(pm); 2583 oldpm = pmap_switch(pm); 2584 while (sz > 0) { 2585 lim = round_page(va); 2586 len = MIN(lim - va, sz); 2587 pte = pmap_find_vhpt(va); 2588 if (pte != NULL && pmap_present(pte)) 2589 ia64_sync_icache(va, len); 2590 va += len; 2591 sz -= len; 2592 } 2593 pmap_switch(oldpm); 2594 PMAP_UNLOCK(pm); 2595 } 2596 2597 /* 2598 * Routine: pmap_remove_all_phys 2599 * Function: 2600 * Removes this physical page from 2601 * all physical maps in which it resides. 2602 * Reflects back modify bits to the pager. 2603 * 2604 * Notes: 2605 * Original versions of this routine were very 2606 * inefficient because they iteratively called 2607 * pmap_remove (slow...) 2608 */ 2609 void 2610 pmap_remove_all_phys(struct vm_page *m) 2611 { 2612 pmap_t oldpmap; 2613 pv_entry_t pv; 2614 2615 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2616 UVMHIST_LOG(maphist, "(m=%p)", m, 0, 0, 0); 2617 2618 KASSERTMSG(vm_page_is_managed(m), "%s: page %p is not managed", 2619 __func__, m); 2620 2621 rw_enter(&pvh_global_lock, RW_WRITER); 2622 while ((pv = TAILQ_FIRST(&m->mdpage.pv_list)) != NULL) { 2623 struct ia64_lpte *pte; 2624 pmap_t pmap = PV_PMAP(pv); 2625 vaddr_t va = pv->pv_va; 2626 2627 PMAP_LOCK(pmap); 2628 oldpmap = pmap_switch(pmap); 2629 pte = pmap_find_vhpt(va); 2630 KASSERTMSG(pte != NULL, "pte"); 2631 if (pmap_ppn(pte) != VM_PAGE_TO_PHYS(m)) 2632 panic("%s: pv_table for %lx is inconsistent", 2633 __func__, VM_PAGE_TO_PHYS(m)); 2634 pmap_remove_pte(pmap, pte, va, pv, 1); 2635 pmap_switch(oldpmap); 2636 PMAP_UNLOCK(pmap); 2637 } 2638 /* XXX freebsd 2639 vm_page_aflag_clear(m, PGA_WRITEABLE); 2640 */ 2641 m->flags |= PG_RDONLY; 2642 2643 rw_exit(&pvh_global_lock); 2644 } 2645 2646 /* 2647 * vm_page_alloc1: 2648 * 2649 * Allocate and return a memory cell with no associated object. 2650 */ 2651 static struct vm_page 2652 *vm_page_alloc1(void) 2653 { 2654 struct vm_page *pg; 2655 2656 pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_USERESERVE|UVM_PGA_ZERO); 2657 if (pg) { 2658 pg->wire_count = 1; /* no mappings yet */ 2659 pg->flags &= ~PG_BUSY; /* never busy */ 2660 } 2661 return pg; 2662 } 2663 2664 /* 2665 * vm_page_free1: 2666 * 2667 * Returns the given page to the free list, 2668 * disassociating it with any VM object. 2669 * 2670 * Object and page must be locked prior to entry. 2671 */ 2672 static void 2673 vm_page_free1(struct vm_page *pg) 2674 { 2675 KASSERT(pg->flags != (PG_CLEAN|PG_FAKE)); /* Freeing invalid page */ 2676 2677 pg->flags |= PG_BUSY; 2678 pg->wire_count = 0; 2679 uvm_pagefree(pg); 2680 } 2681 2682 /* 2683 * pmap_flag_to_attr 2684 * 2685 * Convert pmap_enter/pmap_kenter_pa flags to memory attributes 2686 */ 2687 static vm_memattr_t 2688 pmap_flags_to_memattr(u_int flags) 2689 { 2690 u_int cacheflags = flags & PMAP_CACHE_MASK; 2691 2692 #if 0 2693 UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist); 2694 UVMHIST_LOG(maphist, "(PMAP_NOCACHE=%u, PMAP_WRITE_COMBINE=%u, " 2695 "PMAP_WRITE_BACK=%u, PMAP_NOCACHE_OVR=%u)", 2696 (flags & PMAP_NOCACHE) != 0, (flags & PMAP_WRITE_COMBINE) != 0, 2697 (flags & PMAP_WRITE_BACK) != 0, (flags & PMAP_NOCACHE_OVR) != 0); 2698 #endif 2699 switch (cacheflags) { 2700 case PMAP_NOCACHE: 2701 return VM_MEMATTR_UNCACHEABLE; 2702 case PMAP_WRITE_COMBINE: 2703 /* XXX implement if possible */ 2704 KASSERT(1); 2705 return VM_MEMATTR_WRITE_COMBINING; 2706 case PMAP_WRITE_BACK: 2707 return VM_MEMATTR_WRITE_BACK; 2708 case PMAP_NOCACHE_OVR: 2709 default: 2710 return VM_MEMATTR_DEFAULT; 2711 } 2712 } 2713 2714 #ifdef DEBUG 2715 /* 2716 * Test ref/modify handling. 2717 */ 2718 2719 static void 2720 pmap_testout(void) 2721 { 2722 vaddr_t va; 2723 volatile int *loc; 2724 int val = 0; 2725 paddr_t pa; 2726 struct vm_page *pg; 2727 int ref, mod; 2728 bool extracted; 2729 2730 /* Allocate a page */ 2731 va = (vaddr_t)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED | UVM_KMF_ZERO); 2732 KASSERT(va != 0); 2733 loc = (int*)va; 2734 2735 extracted = pmap_extract(pmap_kernel(), va, &pa); 2736 printf("va %p pa %lx extracted %u\n", (void *)(u_long)va, pa, extracted); 2737 printf("kextract %lx\n", pmap_kextract(va)); 2738 2739 pg = PHYS_TO_VM_PAGE(pa); 2740 pmap_enter(pmap_kernel(), va, pa, VM_PROT_ALL, 0); 2741 pmap_update(pmap_kernel()); 2742 2743 ref = pmap_is_referenced(pg); 2744 mod = pmap_is_modified(pg); 2745 2746 printf("Entered page va %p pa %lx: ref %d, mod %d\n", 2747 (void *)(u_long)va, (long)pa, ref, mod); 2748 2749 /* Now clear reference and modify */ 2750 ref = pmap_clear_reference(pg); 2751 mod = pmap_clear_modify(pg); 2752 printf("Clearing page va %p pa %lx: ref %d, mod %d\n", 2753 (void *)(u_long)va, (long)pa, 2754 ref, mod); 2755 2756 /* Check it's properly cleared */ 2757 ref = pmap_is_referenced(pg); 2758 mod = pmap_is_modified(pg); 2759 printf("Checking cleared page: ref %d, mod %d\n", 2760 ref, mod); 2761 2762 /* Reference page */ 2763 val = *loc; 2764 2765 ref = pmap_is_referenced(pg); 2766 mod = pmap_is_modified(pg); 2767 printf("Referenced page: ref %d, mod %d val %x\n", 2768 ref, mod, val); 2769 2770 /* Now clear reference and modify */ 2771 ref = pmap_clear_reference(pg); 2772 mod = pmap_clear_modify(pg); 2773 printf("Clearing page va %p pa %lx: ref %d, mod %d\n", 2774 (void *)(u_long)va, (long)pa, 2775 ref, mod); 2776 2777 /* Modify page */ 2778 *loc = 1; 2779 2780 ref = pmap_is_referenced(pg); 2781 mod = pmap_is_modified(pg); 2782 printf("Modified page: ref %d, mod %d\n", 2783 ref, mod); 2784 2785 /* Now clear reference and modify */ 2786 ref = pmap_clear_reference(pg); 2787 mod = pmap_clear_modify(pg); 2788 printf("Clearing page va %p pa %lx: ref %d, mod %d\n", 2789 (void *)(u_long)va, (long)pa, 2790 ref, mod); 2791 2792 /* Check it's properly cleared */ 2793 ref = pmap_is_referenced(pg); 2794 mod = pmap_is_modified(pg); 2795 printf("Checking cleared page: ref %d, mod %d\n", 2796 ref, mod); 2797 2798 /* Modify page */ 2799 *loc = 1; 2800 2801 ref = pmap_is_referenced(pg); 2802 mod = pmap_is_modified(pg); 2803 printf("Modified page: ref %d, mod %d\n", 2804 ref, mod); 2805 2806 /* Check pmap_protect() */ 2807 pmap_protect(pmap_kernel(), va, va+1, VM_PROT_READ); 2808 pmap_update(pmap_kernel()); 2809 ref = pmap_is_referenced(pg); 2810 mod = pmap_is_modified(pg); 2811 printf("pmap_protect(VM_PROT_READ): ref %d, mod %d\n", 2812 ref, mod); 2813 2814 /* Now clear reference and modify */ 2815 ref = pmap_clear_reference(pg); 2816 mod = pmap_clear_modify(pg); 2817 printf("Clearing page va %p pa %lx: ref %d, mod %d\n", 2818 (void *)(u_long)va, (long)pa, 2819 ref, mod); 2820 2821 /* Modify page */ 2822 pmap_enter(pmap_kernel(), va, pa, VM_PROT_ALL, 0); 2823 pmap_update(pmap_kernel()); 2824 *loc = 1; 2825 2826 ref = pmap_is_referenced(pg); 2827 mod = pmap_is_modified(pg); 2828 printf("Modified page: ref %d, mod %d\n", 2829 ref, mod); 2830 2831 /* Check pmap_protect() */ 2832 pmap_protect(pmap_kernel(), va, va+1, VM_PROT_NONE); 2833 pmap_update(pmap_kernel()); 2834 ref = pmap_is_referenced(pg); 2835 mod = pmap_is_modified(pg); 2836 printf("pmap_protect(VM_PROT_READ): ref %d, mod %d\n", 2837 ref, mod); 2838 2839 /* Now clear reference and modify */ 2840 ref = pmap_clear_reference(pg); 2841 mod = pmap_clear_modify(pg); 2842 printf("Clearing page va %p pa %lx: ref %d, mod %d\n", 2843 (void *)(u_long)va, (long)pa, 2844 ref, mod); 2845 2846 /* Modify page */ 2847 pmap_enter(pmap_kernel(), va, pa, VM_PROT_ALL, 0); 2848 pmap_update(pmap_kernel()); 2849 *loc = 1; 2850 2851 ref = pmap_is_referenced(pg); 2852 mod = pmap_is_modified(pg); 2853 printf("Modified page: ref %d, mod %d\n", 2854 ref, mod); 2855 2856 /* Check pmap_pag_protect() */ 2857 pmap_page_protect(pg, VM_PROT_READ); 2858 ref = pmap_is_referenced(pg); 2859 mod = pmap_is_modified(pg); 2860 printf("pmap_protect(): ref %d, mod %d\n", 2861 ref, mod); 2862 2863 /* Now clear reference and modify */ 2864 ref = pmap_clear_reference(pg); 2865 mod = pmap_clear_modify(pg); 2866 printf("Clearing page va %p pa %lx: ref %d, mod %d\n", 2867 (void *)(u_long)va, (long)pa, 2868 ref, mod); 2869 2870 2871 /* Modify page */ 2872 pmap_enter(pmap_kernel(), va, pa, VM_PROT_ALL, 0); 2873 pmap_update(pmap_kernel()); 2874 *loc = 1; 2875 2876 ref = pmap_is_referenced(pg); 2877 mod = pmap_is_modified(pg); 2878 printf("Modified page: ref %d, mod %d\n", 2879 ref, mod); 2880 2881 /* Check pmap_pag_protect() */ 2882 pmap_page_protect(pg, VM_PROT_NONE); 2883 ref = pmap_is_referenced(pg); 2884 mod = pmap_is_modified(pg); 2885 printf("pmap_protect(): ref %d, mod %d\n", 2886 ref, mod); 2887 2888 /* Now clear reference and modify */ 2889 ref = pmap_clear_reference(pg); 2890 mod = pmap_clear_modify(pg); 2891 printf("Clearing page va %p pa %lx: ref %d, mod %d\n", 2892 (void *)(u_long)va, (long)pa, 2893 ref, mod); 2894 2895 /* Unmap page */ 2896 pmap_remove(pmap_kernel(), va, va+1); 2897 pmap_update(pmap_kernel()); 2898 ref = pmap_is_referenced(pg); 2899 mod = pmap_is_modified(pg); 2900 printf("Unmapped page: ref %d, mod %d\n", ref, mod); 2901 2902 /* Now clear reference and modify */ 2903 ref = pmap_clear_reference(pg); 2904 mod = pmap_clear_modify(pg); 2905 printf("Clearing page va %p pa %lx: ref %d, mod %d\n", 2906 (void *)(u_long)va, (long)pa, ref, mod); 2907 2908 /* Check it's properly cleared */ 2909 ref = pmap_is_referenced(pg); 2910 mod = pmap_is_modified(pg); 2911 printf("Checking cleared page: ref %d, mod %d\n", 2912 ref, mod); 2913 2914 pmap_remove(pmap_kernel(), va, va+1); 2915 pmap_update(pmap_kernel()); 2916 //pmap_free_page(pa, cpus_active); 2917 uvm_km_free(kernel_map, (vaddr_t)va, PAGE_SIZE, 2918 UVM_KMF_WIRED | UVM_KMF_ZERO); 2919 2920 panic("end of testout"); 2921 } 2922 #endif 2923