1 /* 2 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3 * Copyright (C) 1995, 1996 TooLs GmbH. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by TooLs GmbH. 17 * 4. The name of TooLs GmbH may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $ 32 */ 33 /* 34 * Copyright (C) 2001 Benno Rice. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58 #ifndef lint 59 static const char rcsid[] = 60 "$FreeBSD$"; 61 #endif /* not lint */ 62 63 #include <sys/param.h> 64 #include <sys/systm.h> 65 #include <sys/kernel.h> 66 #include <sys/proc.h> 67 #include <sys/malloc.h> 68 #include <sys/msgbuf.h> 69 #include <sys/vmmeter.h> 70 #include <sys/mman.h> 71 #include <sys/queue.h> 72 #include <sys/lock.h> 73 #include <sys/mutex.h> 74 75 #include <vm/vm.h> 76 #include <vm/vm_param.h> 77 #include <vm/vm_kern.h> 78 #include <vm/vm_page.h> 79 #include <vm/vm_map.h> 80 #include <vm/vm_object.h> 81 #include <vm/vm_extern.h> 82 #include <vm/vm_pageout.h> 83 #include <vm/vm_pager.h> 84 #include <vm/vm_zone.h> 85 86 #include <sys/user.h> 87 88 #include <machine/bat.h> 89 #include <machine/pcb.h> 90 #include <machine/powerpc.h> 91 #include <machine/pte.h> 92 93 pte_t *ptable; 94 int ptab_cnt; 95 u_int ptab_mask; 96 #define HTABSIZE (ptab_cnt * 64) 97 98 #define MINPV 2048 99 100 struct pte_ovfl { 101 LIST_ENTRY(pte_ovfl) po_list; /* Linked list of overflow entries */ 102 struct pte po_pte; /* PTE for this mapping */ 103 }; 104 105 LIST_HEAD(pte_ovtab, pte_ovfl) *potable; /* Overflow entries for ptable */ 106 107 static struct pmap kernel_pmap_store; 108 pmap_t kernel_pmap; 109 110 static int npgs; 111 static u_int nextavail; 112 113 #ifndef MSGBUFADDR 114 extern vm_offset_t msgbuf_paddr; 115 #endif 116 117 static struct mem_region *mem, *avail; 118 119 vm_offset_t avail_start; 120 vm_offset_t avail_end; 121 vm_offset_t virtual_avail; 122 vm_offset_t virtual_end; 123 124 vm_offset_t kernel_vm_end; 125 126 static int pmap_pagedaemon_waken = 0; 127 128 extern unsigned int Maxmem; 129 130 #define ATTRSHFT 4 131 132 struct pv_entry *pv_table; 133 134 static vm_zone_t pvzone; 135 static struct vm_zone pvzone_store; 136 static struct vm_object pvzone_obj; 137 static int pv_entry_count=0, pv_entry_max=0, pv_entry_high_water=0; 138 static struct pv_entry *pvinit; 139 140 #if !defined(PMAP_SHPGPERPROC) 141 #define PMAP_SHPGPERPROC 200 142 #endif 143 144 struct pv_page; 145 struct pv_page_info { 146 LIST_ENTRY(pv_page) pgi_list; 147 struct pv_entry *pgi_freelist; 148 int pgi_nfree; 149 }; 150 #define NPVPPG ((PAGE_SIZE - sizeof(struct pv_page_info)) / sizeof(struct pv_entry)) 151 struct pv_page { 152 struct pv_page_info pvp_pgi; 153 struct pv_entry pvp_pv[NPVPPG]; 154 }; 155 LIST_HEAD(pv_page_list, pv_page) pv_page_freelist; 156 int pv_nfree; 157 int pv_pcnt; 158 static struct pv_entry *pmap_alloc_pv(void); 159 static void pmap_free_pv(struct pv_entry *); 160 161 struct po_page; 162 struct po_page_info { 163 LIST_ENTRY(po_page) pgi_list; 164 vm_page_t pgi_page; 165 LIST_HEAD(po_freelist, pte_ovfl) pgi_freelist; 166 int pgi_nfree; 167 }; 168 #define NPOPPG ((PAGE_SIZE - sizeof(struct po_page_info)) / sizeof(struct pte_ovfl)) 169 struct po_page { 170 struct po_page_info pop_pgi; 171 struct pte_ovfl pop_po[NPOPPG]; 172 }; 173 LIST_HEAD(po_page_list, po_page) po_page_freelist; 174 int po_nfree; 175 int po_pcnt; 176 static struct pte_ovfl *poalloc(void); 177 static void pofree(struct pte_ovfl *, int); 178 179 static u_int usedsr[NPMAPS / sizeof(u_int) / 8]; 180 181 static int pmap_initialized; 182 183 int pte_spill(vm_offset_t); 184 185 /* 186 * These small routines may have to be replaced, 187 * if/when we support processors other that the 604. 188 */ 189 static __inline void 190 tlbie(vm_offset_t ea) 191 { 192 193 __asm __volatile ("tlbie %0" :: "r"(ea)); 194 } 195 196 static __inline void 197 tlbsync(void) 198 { 199 200 __asm __volatile ("sync; tlbsync; sync"); 201 } 202 203 static __inline void 204 tlbia(void) 205 { 206 vm_offset_t i; 207 208 __asm __volatile ("sync"); 209 for (i = 0; i < (vm_offset_t)0x00040000; i += 0x00001000) { 210 tlbie(i); 211 } 212 tlbsync(); 213 } 214 215 static __inline int 216 ptesr(sr_t *sr, vm_offset_t addr) 217 { 218 219 return sr[(u_int)addr >> ADDR_SR_SHFT]; 220 } 221 222 static __inline int 223 pteidx(sr_t sr, vm_offset_t addr) 224 { 225 int hash; 226 227 hash = (sr & SR_VSID) ^ (((u_int)addr & ADDR_PIDX) >> ADDR_PIDX_SHFT); 228 return hash & ptab_mask; 229 } 230 231 static __inline int 232 ptematch(pte_t *ptp, sr_t sr, vm_offset_t va, int which) 233 { 234 235 return ptp->pte_hi == (((sr & SR_VSID) << PTE_VSID_SHFT) | 236 (((u_int)va >> ADDR_API_SHFT) & PTE_API) | which); 237 } 238 239 static __inline struct pv_entry * 240 pa_to_pv(vm_offset_t pa) 241 { 242 #if 0 /* XXX */ 243 int bank, pg; 244 245 bank = vm_physseg_find(atop(pa), &pg); 246 if (bank == -1) 247 return NULL; 248 return &vm_physmem[bank].pmseg.pvent[pg]; 249 #endif 250 return (NULL); 251 } 252 253 static __inline char * 254 pa_to_attr(vm_offset_t pa) 255 { 256 #if 0 /* XXX */ 257 int bank, pg; 258 259 bank = vm_physseg_find(atop(pa), &pg); 260 if (bank == -1) 261 return NULL; 262 return &vm_physmem[bank].pmseg.attrs[pg]; 263 #endif 264 return (NULL); 265 } 266 267 /* 268 * Try to insert page table entry *pt into the ptable at idx. 269 * 270 * Note: *pt mustn't have PTE_VALID set. 271 * This is done here as required by Book III, 4.12. 272 */ 273 static int 274 pte_insert(int idx, pte_t *pt) 275 { 276 pte_t *ptp; 277 int i; 278 279 /* 280 * First try primary hash. 281 */ 282 for (ptp = ptable + idx * 8, i = 8; --i >= 0; ptp++) { 283 if (!(ptp->pte_hi & PTE_VALID)) { 284 *ptp = *pt; 285 ptp->pte_hi &= ~PTE_HID; 286 __asm __volatile ("sync"); 287 ptp->pte_hi |= PTE_VALID; 288 return 1; 289 } 290 } 291 292 /* 293 * Then try secondary hash. 294 */ 295 296 idx ^= ptab_mask; 297 298 for (ptp = ptable + idx * 8, i = 8; --i >= 0; ptp++) { 299 if (!(ptp->pte_hi & PTE_VALID)) { 300 *ptp = *pt; 301 ptp->pte_hi |= PTE_HID; 302 __asm __volatile ("sync"); 303 ptp->pte_hi |= PTE_VALID; 304 return 1; 305 } 306 } 307 308 return 0; 309 } 310 311 /* 312 * Spill handler. 313 * 314 * Tries to spill a page table entry from the overflow area. 315 * Note that this routine runs in real mode on a separate stack, 316 * with interrupts disabled. 317 */ 318 int 319 pte_spill(vm_offset_t addr) 320 { 321 int idx, i; 322 sr_t sr; 323 struct pte_ovfl *po; 324 pte_t ps; 325 pte_t *pt; 326 327 __asm ("mfsrin %0,%1" : "=r"(sr) : "r"(addr)); 328 idx = pteidx(sr, addr); 329 for (po = potable[idx].lh_first; po; po = po->po_list.le_next) { 330 if (ptematch(&po->po_pte, sr, addr, 0)) { 331 /* 332 * Now found an entry to be spilled into the real 333 * ptable. 334 */ 335 if (pte_insert(idx, &po->po_pte)) { 336 LIST_REMOVE(po, po_list); 337 pofree(po, 0); 338 return 1; 339 } 340 /* 341 * Have to substitute some entry. Use the primary 342 * hash for this. 343 * 344 * Use low bits of timebase as random generator 345 */ 346 __asm ("mftb %0" : "=r"(i)); 347 pt = ptable + idx * 8 + (i & 7); 348 pt->pte_hi &= ~PTE_VALID; 349 ps = *pt; 350 __asm __volatile ("sync"); 351 tlbie(addr); 352 tlbsync(); 353 *pt = po->po_pte; 354 __asm __volatile ("sync"); 355 pt->pte_hi |= PTE_VALID; 356 po->po_pte = ps; 357 if (ps.pte_hi & PTE_HID) { 358 /* 359 * We took an entry that was on the alternate 360 * hash chain, so move it to it's original 361 * chain. 362 */ 363 po->po_pte.pte_hi &= ~PTE_HID; 364 LIST_REMOVE(po, po_list); 365 LIST_INSERT_HEAD(potable + (idx ^ ptab_mask), 366 po, po_list); 367 } 368 return 1; 369 } 370 } 371 372 return 0; 373 } 374 375 /* 376 * This is called during powerpc_init, before the system is really initialized. 377 */ 378 void 379 pmap_setavailmem(u_int kernelstart, u_int kernelend) 380 { 381 struct mem_region *mp, *mp1; 382 int cnt, i; 383 u_int s, e, sz; 384 385 /* 386 * Get memory. 387 */ 388 mem_regions(&mem, &avail); 389 for (mp = mem; mp->size; mp++) 390 Maxmem += btoc(mp->size); 391 392 /* 393 * Count the number of available entries. 394 */ 395 for (cnt = 0, mp = avail; mp->size; mp++) { 396 cnt++; 397 } 398 399 /* 400 * Page align all regions. 401 * Non-page aligned memory isn't very interesting to us. 402 * Also, sort the entries for ascending addresses. 403 */ 404 kernelstart &= ~PAGE_MASK; 405 kernelend = (kernelend + PAGE_MASK) & ~PAGE_MASK; 406 for (mp = avail; mp->size; mp++) { 407 s = mp->start; 408 e = mp->start + mp->size; 409 /* 410 * Check whether this region holds all of the kernel. 411 */ 412 if (s < kernelstart && e > kernelend) { 413 avail[cnt].start = kernelend; 414 avail[cnt++].size = e - kernelend; 415 e = kernelstart; 416 } 417 /* 418 * Look whether this regions starts within the kernel. 419 */ 420 if (s >= kernelstart && s < kernelend) { 421 if (e <= kernelend) 422 goto empty; 423 s = kernelend; 424 } 425 /* 426 * Now look whether this region ends within the kernel. 427 */ 428 if (e > kernelstart && e <= kernelend) { 429 if (s >= kernelstart) 430 goto empty; 431 e = kernelstart; 432 } 433 /* 434 * Now page align the start and size of the region. 435 */ 436 s = round_page(s); 437 e = trunc_page(e); 438 if (e < s) { 439 e = s; 440 } 441 sz = e - s; 442 /* 443 * Check whether some memory is left here. 444 */ 445 if (sz == 0) { 446 empty: 447 bcopy(mp + 1, mp, 448 (cnt - (mp - avail)) * sizeof *mp); 449 cnt--; 450 mp--; 451 continue; 452 } 453 454 /* 455 * Do an insertion sort. 456 */ 457 npgs += btoc(sz); 458 459 for (mp1 = avail; mp1 < mp; mp1++) { 460 if (s < mp1->start) { 461 break; 462 } 463 } 464 465 if (mp1 < mp) { 466 bcopy(mp1, mp1 + 1, (char *)mp - (char *)mp1); 467 mp1->start = s; 468 mp1->size = sz; 469 } else { 470 mp->start = s; 471 mp->size = sz; 472 } 473 } 474 475 #ifdef HTABENTS 476 ptab_cnt = HTABENTS; 477 #else 478 ptab_cnt = (Maxmem + 1) / 2; 479 480 /* The minimum is 1024 PTEGs. */ 481 if (ptab_cnt < 1024) { 482 ptab_cnt = 1024; 483 } 484 485 /* Round up to power of 2. */ 486 __asm ("cntlzw %0,%1" : "=r"(i) : "r"(ptab_cnt - 1)); 487 ptab_cnt = 1 << (32 - i); 488 #endif 489 490 /* 491 * Find suitably aligned memory for HTAB. 492 */ 493 for (mp = avail; mp->size; mp++) { 494 s = roundup(mp->start, HTABSIZE) - mp->start; 495 496 if (mp->size < s + HTABSIZE) { 497 continue; 498 } 499 500 ptable = (pte_t *)(mp->start + s); 501 502 if (mp->size == s + HTABSIZE) { 503 if (s) 504 mp->size = s; 505 else { 506 bcopy(mp + 1, mp, 507 (cnt - (mp - avail)) * sizeof *mp); 508 mp = avail; 509 } 510 break; 511 } 512 513 if (s != 0) { 514 bcopy(mp, mp + 1, 515 (cnt - (mp - avail)) * sizeof *mp); 516 mp++->size = s; 517 cnt++; 518 } 519 520 mp->start += s + HTABSIZE; 521 mp->size -= s + HTABSIZE; 522 break; 523 } 524 525 if (!mp->size) { 526 panic("not enough memory?"); 527 } 528 529 npgs -= btoc(HTABSIZE); 530 bzero((void *)ptable, HTABSIZE); 531 ptab_mask = ptab_cnt - 1; 532 533 /* 534 * We cannot do pmap_steal_memory here, 535 * since we don't run with translation enabled yet. 536 */ 537 s = sizeof(struct pte_ovtab) * ptab_cnt; 538 sz = round_page(s); 539 540 for (mp = avail; mp->size; mp++) { 541 if (mp->size >= sz) { 542 break; 543 } 544 } 545 546 if (!mp->size) { 547 panic("not enough memory?"); 548 } 549 550 npgs -= btoc(sz); 551 potable = (struct pte_ovtab *)mp->start; 552 mp->size -= sz; 553 mp->start += sz; 554 555 if (mp->size <= 0) { 556 bcopy(mp + 1, mp, (cnt - (mp - avail)) * sizeof *mp); 557 } 558 559 for (i = 0; i < ptab_cnt; i++) { 560 LIST_INIT(potable + i); 561 } 562 563 #ifndef MSGBUFADDR 564 /* 565 * allow for msgbuf 566 */ 567 sz = round_page(MSGBUFSIZE); 568 mp = NULL; 569 570 for (mp1 = avail; mp1->size; mp1++) { 571 if (mp1->size >= sz) { 572 mp = mp1; 573 } 574 } 575 576 if (mp == NULL) { 577 panic("not enough memory?"); 578 } 579 580 npgs -= btoc(sz); 581 msgbuf_paddr = mp->start + mp->size - sz; 582 mp->size -= sz; 583 584 if (mp->size <= 0) { 585 bcopy(mp + 1, mp, (cnt - (mp - avail)) * sizeof *mp); 586 } 587 #endif 588 589 nextavail = avail->start; 590 avail_start = avail->start; 591 for (mp = avail, i = 0; mp->size; mp++) { 592 avail_end = mp->start + mp->size; 593 phys_avail[i++] = mp->start; 594 phys_avail[i++] = mp->start + mp->size; 595 } 596 597 598 } 599 600 void 601 pmap_bootstrap() 602 { 603 int i; 604 u_int32_t batl, batu; 605 606 /* 607 * Initialize kernel pmap and hardware. 608 */ 609 kernel_pmap = &kernel_pmap_store; 610 611 batu = BATU(0x80000000, BAT_BL_256M, BAT_Vs); 612 batl = BATL(0x80000000, BAT_M, BAT_PP_RW); 613 __asm ("mtdbatu 1,%0; mtdbatl 1,%1" :: "r" (batu), "r" (batl)); 614 615 #if NPMAPS >= KERNEL_SEGMENT / 16 616 usedsr[KERNEL_SEGMENT / 16 / (sizeof usedsr[0] * 8)] 617 |= 1 << ((KERNEL_SEGMENT / 16) % (sizeof usedsr[0] * 8)); 618 #endif 619 620 #if 0 /* XXX */ 621 for (i = 0; i < 16; i++) { 622 kernel_pmap->pm_sr[i] = EMPTY_SEGMENT; 623 __asm __volatile ("mtsrin %0,%1" 624 :: "r"(EMPTY_SEGMENT), "r"(i << ADDR_SR_SHFT)); 625 } 626 #endif 627 628 for (i = 0; i < 16; i++) { 629 int j; 630 631 __asm __volatile ("mfsrin %0,%1" 632 : "=r" (j) 633 : "r" (i << ADDR_SR_SHFT)); 634 635 kernel_pmap->pm_sr[i] = j; 636 } 637 638 kernel_pmap->pm_sr[KERNEL_SR] = KERNEL_SEGMENT; 639 __asm __volatile ("mtsr %0,%1" 640 :: "n"(KERNEL_SR), "r"(KERNEL_SEGMENT)); 641 642 __asm __volatile ("sync; mtsdr1 %0; isync" 643 :: "r"((u_int)ptable | (ptab_mask >> 10))); 644 645 tlbia(); 646 647 virtual_avail = VM_MIN_KERNEL_ADDRESS; 648 virtual_end = VM_MAX_KERNEL_ADDRESS; 649 } 650 651 /* 652 * Initialize anything else for pmap handling. 653 * Called during vm_init(). 654 */ 655 void 656 pmap_init(vm_offset_t phys_start, vm_offset_t phys_end) 657 { 658 int initial_pvs; 659 660 /* 661 * init the pv free list 662 */ 663 initial_pvs = vm_page_array_size; 664 if (initial_pvs < MINPV) { 665 initial_pvs = MINPV; 666 } 667 pvzone = &pvzone_store; 668 pvinit = (struct pv_entry *) kmem_alloc(kernel_map, 669 initial_pvs * sizeof(struct pv_entry)); 670 zbootinit(pvzone, "PV ENTRY", sizeof(struct pv_entry), pvinit, 671 vm_page_array_size); 672 673 pmap_initialized = TRUE; 674 } 675 676 /* 677 * Initialize a preallocated and zeroed pmap structure. 678 */ 679 void 680 pmap_pinit(struct pmap *pm) 681 { 682 int i, j; 683 684 /* 685 * Allocate some segment registers for this pmap. 686 */ 687 pm->pm_refs = 1; 688 for (i = 0; i < sizeof usedsr / sizeof usedsr[0]; i++) { 689 if (usedsr[i] != 0xffffffff) { 690 j = ffs(~usedsr[i]) - 1; 691 usedsr[i] |= 1 << j; 692 pm->pm_sr[0] = (i * sizeof usedsr[0] * 8 + j) * 16; 693 for (i = 1; i < 16; i++) { 694 pm->pm_sr[i] = pm->pm_sr[i - 1] + 1; 695 } 696 return; 697 } 698 } 699 panic("out of segments"); 700 } 701 702 void 703 pmap_pinit2(pmap_t pmap) 704 { 705 706 /* 707 * Nothing to be done. 708 */ 709 return; 710 } 711 712 /* 713 * Add a reference to the given pmap. 714 */ 715 void 716 pmap_reference(struct pmap *pm) 717 { 718 719 pm->pm_refs++; 720 } 721 722 /* 723 * Retire the given pmap from service. 724 * Should only be called if the map contains no valid mappings. 725 */ 726 void 727 pmap_destroy(struct pmap *pm) 728 { 729 730 if (--pm->pm_refs == 0) { 731 pmap_release(pm); 732 free((caddr_t)pm, M_VMPGDATA); 733 } 734 } 735 736 /* 737 * Release any resources held by the given physical map. 738 * Called when a pmap initialized by pmap_pinit is being released. 739 */ 740 void 741 pmap_release(struct pmap *pm) 742 { 743 int i, j; 744 745 if (!pm->pm_sr[0]) { 746 panic("pmap_release"); 747 } 748 i = pm->pm_sr[0] / 16; 749 j = i % (sizeof usedsr[0] * 8); 750 i /= sizeof usedsr[0] * 8; 751 usedsr[i] &= ~(1 << j); 752 } 753 754 /* 755 * Copy the range specified by src_addr/len 756 * from the source map to the range dst_addr/len 757 * in the destination map. 758 * 759 * This routine is only advisory and need not do anything. 760 */ 761 void 762 pmap_copy(struct pmap *dst_pmap, struct pmap *src_pmap, vm_offset_t dst_addr, 763 vm_size_t len, vm_offset_t src_addr) 764 { 765 766 return; 767 } 768 769 /* 770 * Garbage collects the physical map system for 771 * pages which are no longer used. 772 * Success need not be guaranteed -- that is, there 773 * may well be pages which are not referenced, but 774 * others may be collected. 775 * Called by the pageout daemon when pages are scarce. 776 */ 777 void 778 pmap_collect(void) 779 { 780 781 return; 782 } 783 784 /* 785 * Fill the given physical page with zeroes. 786 */ 787 void 788 pmap_zero_page(vm_offset_t pa) 789 { 790 #if 0 791 bzero((caddr_t)pa, PAGE_SIZE); 792 #else 793 int i; 794 795 for (i = PAGE_SIZE/CACHELINESIZE; i > 0; i--) { 796 __asm __volatile ("dcbz 0,%0" :: "r"(pa)); 797 pa += CACHELINESIZE; 798 } 799 #endif 800 } 801 802 void 803 pmap_zero_page_area(vm_offset_t pa, int off, int size) 804 { 805 806 bzero((caddr_t)pa + off, size); 807 } 808 809 /* 810 * Copy the given physical source page to its destination. 811 */ 812 void 813 pmap_copy_page(vm_offset_t src, vm_offset_t dst) 814 { 815 816 bcopy((caddr_t)src, (caddr_t)dst, PAGE_SIZE); 817 } 818 819 static struct pv_entry * 820 pmap_alloc_pv() 821 { 822 pv_entry_count++; 823 824 if (pv_entry_high_water && 825 (pv_entry_count > pv_entry_high_water) && 826 (pmap_pagedaemon_waken == 0)) { 827 pmap_pagedaemon_waken = 1; 828 wakeup(&vm_pages_needed); 829 } 830 831 return zalloc(pvzone); 832 } 833 834 static void 835 pmap_free_pv(struct pv_entry *pv) 836 { 837 838 pv_entry_count--; 839 zfree(pvzone, pv); 840 } 841 842 /* 843 * We really hope that we don't need overflow entries 844 * before the VM system is initialized! 845 * 846 * XXX: Should really be switched over to the zone allocator. 847 */ 848 static struct pte_ovfl * 849 poalloc() 850 { 851 struct po_page *pop; 852 struct pte_ovfl *po; 853 vm_page_t mem; 854 int i; 855 856 if (!pmap_initialized) { 857 panic("poalloc"); 858 } 859 860 if (po_nfree == 0) { 861 /* 862 * Since we cannot use maps for potable allocation, 863 * we have to steal some memory from the VM system. XXX 864 */ 865 mem = vm_page_alloc(NULL, 0, VM_ALLOC_SYSTEM); 866 po_pcnt++; 867 pop = (struct po_page *)VM_PAGE_TO_PHYS(mem); 868 pop->pop_pgi.pgi_page = mem; 869 LIST_INIT(&pop->pop_pgi.pgi_freelist); 870 for (i = NPOPPG - 1, po = pop->pop_po + 1; --i >= 0; po++) { 871 LIST_INSERT_HEAD(&pop->pop_pgi.pgi_freelist, po, 872 po_list); 873 } 874 po_nfree += pop->pop_pgi.pgi_nfree = NPOPPG - 1; 875 LIST_INSERT_HEAD(&po_page_freelist, pop, pop_pgi.pgi_list); 876 po = pop->pop_po; 877 } else { 878 po_nfree--; 879 pop = po_page_freelist.lh_first; 880 if (--pop->pop_pgi.pgi_nfree <= 0) { 881 LIST_REMOVE(pop, pop_pgi.pgi_list); 882 } 883 po = pop->pop_pgi.pgi_freelist.lh_first; 884 LIST_REMOVE(po, po_list); 885 } 886 887 return po; 888 } 889 890 static void 891 pofree(struct pte_ovfl *po, int freepage) 892 { 893 struct po_page *pop; 894 895 pop = (struct po_page *)trunc_page((vm_offset_t)po); 896 switch (++pop->pop_pgi.pgi_nfree) { 897 case NPOPPG: 898 if (!freepage) { 899 break; 900 } 901 po_nfree -= NPOPPG - 1; 902 po_pcnt--; 903 LIST_REMOVE(pop, pop_pgi.pgi_list); 904 vm_page_free(pop->pop_pgi.pgi_page); 905 return; 906 case 1: 907 LIST_INSERT_HEAD(&po_page_freelist, pop, pop_pgi.pgi_list); 908 default: 909 break; 910 } 911 LIST_INSERT_HEAD(&pop->pop_pgi.pgi_freelist, po, po_list); 912 po_nfree++; 913 } 914 915 /* 916 * This returns whether this is the first mapping of a page. 917 */ 918 static int 919 pmap_enter_pv(int pteidx, vm_offset_t va, vm_offset_t pa) 920 { 921 struct pv_entry *pv, *npv; 922 int s, first; 923 924 if (!pmap_initialized) { 925 return 0; 926 } 927 928 s = splimp(); 929 930 pv = pa_to_pv(pa); 931 first = pv->pv_idx; 932 if (pv->pv_idx == -1) { 933 /* 934 * No entries yet, use header as the first entry. 935 */ 936 pv->pv_va = va; 937 pv->pv_idx = pteidx; 938 pv->pv_next = NULL; 939 } else { 940 /* 941 * There is at least one other VA mapping this page. 942 * Place this entry after the header. 943 */ 944 npv = pmap_alloc_pv(); 945 npv->pv_va = va; 946 npv->pv_idx = pteidx; 947 npv->pv_next = pv->pv_next; 948 pv->pv_next = npv; 949 } 950 splx(s); 951 return first; 952 } 953 954 static void 955 pmap_remove_pv(int pteidx, vm_offset_t va, vm_offset_t pa, struct pte *pte) 956 { 957 struct pv_entry *pv, *npv; 958 char *attr; 959 960 /* 961 * First transfer reference/change bits to cache. 962 */ 963 attr = pa_to_attr(pa); 964 if (attr == NULL) { 965 return; 966 } 967 *attr |= (pte->pte_lo & (PTE_REF | PTE_CHG)) >> ATTRSHFT; 968 969 /* 970 * Remove from the PV table. 971 */ 972 pv = pa_to_pv(pa); 973 974 /* 975 * If it is the first entry on the list, it is actually 976 * in the header and we must copy the following entry up 977 * to the header. Otherwise we must search the list for 978 * the entry. In either case we free the now unused entry. 979 */ 980 if (pteidx == pv->pv_idx && va == pv->pv_va) { 981 npv = pv->pv_next; 982 if (npv) { 983 *pv = *npv; 984 pmap_free_pv(npv); 985 } else { 986 pv->pv_idx = -1; 987 } 988 } else { 989 for (; (npv = pv->pv_next); pv = npv) { 990 if (pteidx == npv->pv_idx && va == npv->pv_va) { 991 break; 992 } 993 } 994 if (npv) { 995 pv->pv_next = npv->pv_next; 996 pmap_free_pv(npv); 997 } 998 #ifdef DIAGNOSTIC 999 else { 1000 panic("pmap_remove_pv: not on list\n"); 1001 } 1002 #endif 1003 } 1004 } 1005 1006 /* 1007 * Insert physical page at pa into the given pmap at virtual address va. 1008 */ 1009 void 1010 pmap_enter(pmap_t pm, vm_offset_t va, vm_page_t pg, vm_prot_t prot, 1011 boolean_t wired) 1012 { 1013 sr_t sr; 1014 int idx, s; 1015 pte_t pte; 1016 struct pte_ovfl *po; 1017 struct mem_region *mp; 1018 vm_offset_t pa; 1019 1020 pa = VM_PAGE_TO_PHYS(pg) & ~PAGE_MASK; 1021 1022 /* 1023 * Have to remove any existing mapping first. 1024 */ 1025 pmap_remove(pm, va, va + PAGE_SIZE); 1026 1027 /* 1028 * Compute the HTAB index. 1029 */ 1030 idx = pteidx(sr = ptesr(pm->pm_sr, va), va); 1031 /* 1032 * Construct the PTE. 1033 * 1034 * Note: Don't set the valid bit for correct operation of tlb update. 1035 */ 1036 pte.pte_hi = ((sr & SR_VSID) << PTE_VSID_SHFT) 1037 | ((va & ADDR_PIDX) >> ADDR_API_SHFT); 1038 pte.pte_lo = (pa & PTE_RPGN) | PTE_M | PTE_I | PTE_G; 1039 1040 for (mp = mem; mp->size; mp++) { 1041 if (pa >= mp->start && pa < mp->start + mp->size) { 1042 pte.pte_lo &= ~(PTE_I | PTE_G); 1043 break; 1044 } 1045 } 1046 if (prot & VM_PROT_WRITE) { 1047 pte.pte_lo |= PTE_RW; 1048 } else { 1049 pte.pte_lo |= PTE_RO; 1050 } 1051 1052 /* 1053 * Now record mapping for later back-translation. 1054 */ 1055 if (pmap_initialized && (pg->flags & PG_FICTITIOUS) == 0) { 1056 if (pmap_enter_pv(idx, va, pa)) { 1057 /* 1058 * Flush the real memory from the cache. 1059 */ 1060 __syncicache((void *)pa, PAGE_SIZE); 1061 } 1062 } 1063 1064 s = splimp(); 1065 pm->pm_stats.resident_count++; 1066 /* 1067 * Try to insert directly into HTAB. 1068 */ 1069 if (pte_insert(idx, &pte)) { 1070 splx(s); 1071 return; 1072 } 1073 1074 /* 1075 * Have to allocate overflow entry. 1076 * 1077 * Note, that we must use real addresses for these. 1078 */ 1079 po = poalloc(); 1080 po->po_pte = pte; 1081 LIST_INSERT_HEAD(potable + idx, po, po_list); 1082 splx(s); 1083 } 1084 1085 void 1086 pmap_kenter(vm_offset_t va, vm_offset_t pa) 1087 { 1088 struct vm_page pg; 1089 1090 pg.phys_addr = pa; 1091 pmap_enter(kernel_pmap, va, &pg, VM_PROT_READ|VM_PROT_WRITE, TRUE); 1092 } 1093 1094 void 1095 pmap_kremove(vm_offset_t va) 1096 { 1097 pmap_remove(kernel_pmap, va, va + PAGE_SIZE); 1098 } 1099 1100 /* 1101 * Remove the given range of mapping entries. 1102 */ 1103 void 1104 pmap_remove(struct pmap *pm, vm_offset_t va, vm_offset_t endva) 1105 { 1106 int idx, i, s; 1107 sr_t sr; 1108 pte_t *ptp; 1109 struct pte_ovfl *po, *npo; 1110 1111 s = splimp(); 1112 while (va < endva) { 1113 idx = pteidx(sr = ptesr(pm->pm_sr, va), va); 1114 for (ptp = ptable + idx * 8, i = 8; --i >= 0; ptp++) { 1115 if (ptematch(ptp, sr, va, PTE_VALID)) { 1116 pmap_remove_pv(idx, va, ptp->pte_lo, ptp); 1117 ptp->pte_hi &= ~PTE_VALID; 1118 __asm __volatile ("sync"); 1119 tlbie(va); 1120 tlbsync(); 1121 pm->pm_stats.resident_count--; 1122 } 1123 } 1124 for (ptp = ptable + (idx ^ ptab_mask) * 8, i = 8; --i >= 0; 1125 ptp++) { 1126 if (ptematch(ptp, sr, va, PTE_VALID | PTE_HID)) { 1127 pmap_remove_pv(idx, va, ptp->pte_lo, ptp); 1128 ptp->pte_hi &= ~PTE_VALID; 1129 __asm __volatile ("sync"); 1130 tlbie(va); 1131 tlbsync(); 1132 pm->pm_stats.resident_count--; 1133 } 1134 } 1135 for (po = potable[idx].lh_first; po; po = npo) { 1136 npo = po->po_list.le_next; 1137 if (ptematch(&po->po_pte, sr, va, 0)) { 1138 pmap_remove_pv(idx, va, po->po_pte.pte_lo, 1139 &po->po_pte); 1140 LIST_REMOVE(po, po_list); 1141 pofree(po, 1); 1142 pm->pm_stats.resident_count--; 1143 } 1144 } 1145 va += PAGE_SIZE; 1146 } 1147 splx(s); 1148 } 1149 1150 static pte_t * 1151 pte_find(struct pmap *pm, vm_offset_t va) 1152 { 1153 int idx, i; 1154 sr_t sr; 1155 pte_t *ptp; 1156 struct pte_ovfl *po; 1157 1158 idx = pteidx(sr = ptesr(pm->pm_sr, va), va); 1159 for (ptp = ptable + idx * 8, i = 8; --i >= 0; ptp++) { 1160 if (ptematch(ptp, sr, va, PTE_VALID)) { 1161 return ptp; 1162 } 1163 } 1164 for (ptp = ptable + (idx ^ ptab_mask) * 8, i = 8; --i >= 0; ptp++) { 1165 if (ptematch(ptp, sr, va, PTE_VALID | PTE_HID)) { 1166 return ptp; 1167 } 1168 } 1169 for (po = potable[idx].lh_first; po; po = po->po_list.le_next) { 1170 if (ptematch(&po->po_pte, sr, va, 0)) { 1171 return &po->po_pte; 1172 } 1173 } 1174 return 0; 1175 } 1176 1177 /* 1178 * Get the physical page address for the given pmap/virtual address. 1179 */ 1180 vm_offset_t 1181 pmap_extract(pmap_t pm, vm_offset_t va) 1182 { 1183 pte_t *ptp; 1184 int s; 1185 1186 s = splimp(); 1187 1188 if (!(ptp = pte_find(pm, va))) { 1189 splx(s); 1190 return (0); 1191 } 1192 splx(s); 1193 return ((ptp->pte_lo & PTE_RPGN) | (va & ADDR_POFF)); 1194 } 1195 1196 /* 1197 * Lower the protection on the specified range of this pmap. 1198 * 1199 * There are only two cases: either the protection is going to 0, 1200 * or it is going to read-only. 1201 */ 1202 void 1203 pmap_protect(struct pmap *pm, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) 1204 { 1205 pte_t *ptp; 1206 int valid, s; 1207 1208 if (prot & VM_PROT_READ) { 1209 s = splimp(); 1210 while (sva < eva) { 1211 ptp = pte_find(pm, sva); 1212 if (ptp) { 1213 valid = ptp->pte_hi & PTE_VALID; 1214 ptp->pte_hi &= ~PTE_VALID; 1215 __asm __volatile ("sync"); 1216 tlbie(sva); 1217 tlbsync(); 1218 ptp->pte_lo &= ~PTE_PP; 1219 ptp->pte_lo |= PTE_RO; 1220 __asm __volatile ("sync"); 1221 ptp->pte_hi |= valid; 1222 } 1223 sva += PAGE_SIZE; 1224 } 1225 splx(s); 1226 return; 1227 } 1228 pmap_remove(pm, sva, eva); 1229 } 1230 1231 boolean_t 1232 ptemodify(vm_page_t pg, u_int mask, u_int val) 1233 { 1234 vm_offset_t pa; 1235 struct pv_entry *pv; 1236 pte_t *ptp; 1237 struct pte_ovfl *po; 1238 int i, s; 1239 char *attr; 1240 int rv; 1241 1242 pa = VM_PAGE_TO_PHYS(pg); 1243 1244 /* 1245 * First modify bits in cache. 1246 */ 1247 attr = pa_to_attr(pa); 1248 if (attr == NULL) { 1249 return FALSE; 1250 } 1251 1252 *attr &= ~mask >> ATTRSHFT; 1253 *attr |= val >> ATTRSHFT; 1254 1255 pv = pa_to_pv(pa); 1256 if (pv->pv_idx < 0) { 1257 return FALSE; 1258 } 1259 1260 rv = FALSE; 1261 s = splimp(); 1262 for (; pv; pv = pv->pv_next) { 1263 for (ptp = ptable + pv->pv_idx * 8, i = 8; --i >= 0; ptp++) { 1264 if ((ptp->pte_hi & PTE_VALID) 1265 && (ptp->pte_lo & PTE_RPGN) == pa) { 1266 ptp->pte_hi &= ~PTE_VALID; 1267 __asm __volatile ("sync"); 1268 tlbie(pv->pv_va); 1269 tlbsync(); 1270 rv |= ptp->pte_lo & mask; 1271 ptp->pte_lo &= ~mask; 1272 ptp->pte_lo |= val; 1273 __asm __volatile ("sync"); 1274 ptp->pte_hi |= PTE_VALID; 1275 } 1276 } 1277 for (ptp = ptable + (pv->pv_idx ^ ptab_mask) * 8, i = 8; 1278 --i >= 0; ptp++) { 1279 if ((ptp->pte_hi & PTE_VALID) 1280 && (ptp->pte_lo & PTE_RPGN) == pa) { 1281 ptp->pte_hi &= ~PTE_VALID; 1282 __asm __volatile ("sync"); 1283 tlbie(pv->pv_va); 1284 tlbsync(); 1285 rv |= ptp->pte_lo & mask; 1286 ptp->pte_lo &= ~mask; 1287 ptp->pte_lo |= val; 1288 __asm __volatile ("sync"); 1289 ptp->pte_hi |= PTE_VALID; 1290 } 1291 } 1292 for (po = potable[pv->pv_idx].lh_first; po; 1293 po = po->po_list.le_next) { 1294 if ((po->po_pte.pte_lo & PTE_RPGN) == pa) { 1295 rv |= ptp->pte_lo & mask; 1296 po->po_pte.pte_lo &= ~mask; 1297 po->po_pte.pte_lo |= val; 1298 } 1299 } 1300 } 1301 splx(s); 1302 return rv != 0; 1303 } 1304 1305 int 1306 ptebits(vm_page_t pg, int bit) 1307 { 1308 struct pv_entry *pv; 1309 pte_t *ptp; 1310 struct pte_ovfl *po; 1311 int i, s, bits; 1312 char *attr; 1313 vm_offset_t pa; 1314 1315 bits = 0; 1316 pa = VM_PAGE_TO_PHYS(pg); 1317 1318 /* 1319 * First try the cache. 1320 */ 1321 attr = pa_to_attr(pa); 1322 if (attr == NULL) { 1323 return 0; 1324 } 1325 bits |= (*attr << ATTRSHFT) & bit; 1326 if (bits == bit) { 1327 return bits; 1328 } 1329 1330 pv = pa_to_pv(pa); 1331 if (pv->pv_idx < 0) { 1332 return 0; 1333 } 1334 1335 s = splimp(); 1336 for (; pv; pv = pv->pv_next) { 1337 for (ptp = ptable + pv->pv_idx * 8, i = 8; --i >= 0; ptp++) { 1338 if ((ptp->pte_hi & PTE_VALID) 1339 && (ptp->pte_lo & PTE_RPGN) == pa) { 1340 bits |= ptp->pte_lo & bit; 1341 if (bits == bit) { 1342 splx(s); 1343 return bits; 1344 } 1345 } 1346 } 1347 for (ptp = ptable + (pv->pv_idx ^ ptab_mask) * 8, i = 8; 1348 --i >= 0; ptp++) { 1349 if ((ptp->pte_hi & PTE_VALID) 1350 && (ptp->pte_lo & PTE_RPGN) == pa) { 1351 bits |= ptp->pte_lo & bit; 1352 if (bits == bit) { 1353 splx(s); 1354 return bits; 1355 } 1356 } 1357 } 1358 for (po = potable[pv->pv_idx].lh_first; po; 1359 po = po->po_list.le_next) { 1360 if ((po->po_pte.pte_lo & PTE_RPGN) == pa) { 1361 bits |= po->po_pte.pte_lo & bit; 1362 if (bits == bit) { 1363 splx(s); 1364 return bits; 1365 } 1366 } 1367 } 1368 } 1369 splx(s); 1370 return bits; 1371 } 1372 1373 /* 1374 * Lower the protection on the specified physical page. 1375 * 1376 * There are only two cases: either the protection is going to 0, 1377 * or it is going to read-only. 1378 */ 1379 void 1380 pmap_page_protect(vm_page_t m, vm_prot_t prot) 1381 { 1382 vm_offset_t pa; 1383 vm_offset_t va; 1384 pte_t *ptp; 1385 struct pte_ovfl *po, *npo; 1386 int i, s, idx; 1387 struct pv_entry *pv; 1388 1389 pa = VM_PAGE_TO_PHYS(m); 1390 1391 pa &= ~ADDR_POFF; 1392 if (prot & VM_PROT_READ) { 1393 ptemodify(m, PTE_PP, PTE_RO); 1394 return; 1395 } 1396 1397 pv = pa_to_pv(pa); 1398 if (pv == NULL) { 1399 return; 1400 } 1401 1402 s = splimp(); 1403 while (pv->pv_idx >= 0) { 1404 idx = pv->pv_idx; 1405 va = pv->pv_va; 1406 for (ptp = ptable + idx * 8, i = 8; --i >= 0; ptp++) { 1407 if ((ptp->pte_hi & PTE_VALID) 1408 && (ptp->pte_lo & PTE_RPGN) == pa) { 1409 pmap_remove_pv(idx, va, pa, ptp); 1410 ptp->pte_hi &= ~PTE_VALID; 1411 __asm __volatile ("sync"); 1412 tlbie(va); 1413 tlbsync(); 1414 goto next; 1415 } 1416 } 1417 for (ptp = ptable + (idx ^ ptab_mask) * 8, i = 8; --i >= 0; 1418 ptp++) { 1419 if ((ptp->pte_hi & PTE_VALID) 1420 && (ptp->pte_lo & PTE_RPGN) == pa) { 1421 pmap_remove_pv(idx, va, pa, ptp); 1422 ptp->pte_hi &= ~PTE_VALID; 1423 __asm __volatile ("sync"); 1424 tlbie(va); 1425 tlbsync(); 1426 goto next; 1427 } 1428 } 1429 for (po = potable[idx].lh_first; po; po = npo) { 1430 npo = po->po_list.le_next; 1431 if ((po->po_pte.pte_lo & PTE_RPGN) == pa) { 1432 pmap_remove_pv(idx, va, pa, &po->po_pte); 1433 LIST_REMOVE(po, po_list); 1434 pofree(po, 1); 1435 goto next; 1436 } 1437 } 1438 next: 1439 } 1440 splx(s); 1441 } 1442 1443 /* 1444 * Activate the address space for the specified process. If the process 1445 * is the current process, load the new MMU context. 1446 */ 1447 void 1448 pmap_activate(struct thread *td) 1449 { 1450 struct pcb *pcb; 1451 pmap_t pmap; 1452 pmap_t rpm; 1453 int psl, i, ksr, seg; 1454 1455 pcb = td->td_pcb; 1456 pmap = vmspace_pmap(td->td_proc->p_vmspace); 1457 1458 /* 1459 * XXX Normally performed in cpu_fork(). 1460 */ 1461 if (pcb->pcb_pm != pmap) { 1462 pcb->pcb_pm = pmap; 1463 (vm_offset_t) pcb->pcb_pmreal = pmap_extract(kernel_pmap, 1464 (vm_offset_t)pcb->pcb_pm); 1465 } 1466 1467 if (td == curthread) { 1468 /* Disable interrupts while switching. */ 1469 psl = mfmsr(); 1470 mtmsr(psl & ~PSL_EE); 1471 1472 #if 0 /* XXX */ 1473 /* Store pointer to new current pmap. */ 1474 curpm = pcb->pcb_pmreal; 1475 #endif 1476 1477 /* Save kernel SR. */ 1478 __asm __volatile("mfsr %0,14" : "=r"(ksr) :); 1479 1480 /* 1481 * Set new segment registers. We use the pmap's real 1482 * address to avoid accessibility problems. 1483 */ 1484 rpm = pcb->pcb_pmreal; 1485 for (i = 0; i < 16; i++) { 1486 seg = rpm->pm_sr[i]; 1487 __asm __volatile("mtsrin %0,%1" 1488 :: "r"(seg), "r"(i << ADDR_SR_SHFT)); 1489 } 1490 1491 /* Restore kernel SR. */ 1492 __asm __volatile("mtsr 14,%0" :: "r"(ksr)); 1493 1494 /* Interrupts are OK again. */ 1495 mtmsr(psl); 1496 } 1497 } 1498 1499 /* 1500 * Add a list of wired pages to the kva 1501 * this routine is only used for temporary 1502 * kernel mappings that do not need to have 1503 * page modification or references recorded. 1504 * Note that old mappings are simply written 1505 * over. The page *must* be wired. 1506 */ 1507 void 1508 pmap_qenter(vm_offset_t va, vm_page_t *m, int count) 1509 { 1510 int i; 1511 1512 for (i = 0; i < count; i++) { 1513 vm_offset_t tva = va + i * PAGE_SIZE; 1514 pmap_kenter(tva, VM_PAGE_TO_PHYS(m[i])); 1515 } 1516 } 1517 1518 /* 1519 * this routine jerks page mappings from the 1520 * kernel -- it is meant only for temporary mappings. 1521 */ 1522 void 1523 pmap_qremove(vm_offset_t va, int count) 1524 { 1525 vm_offset_t end_va; 1526 1527 end_va = va + count*PAGE_SIZE; 1528 1529 while (va < end_va) { 1530 unsigned *pte; 1531 1532 pte = (unsigned *)vtopte(va); 1533 *pte = 0; 1534 tlbie(va); 1535 va += PAGE_SIZE; 1536 } 1537 } 1538 1539 /* 1540 * pmap_ts_referenced: 1541 * 1542 * Return the count of reference bits for a page, clearing all of them. 1543 */ 1544 int 1545 pmap_ts_referenced(vm_page_t m) 1546 { 1547 1548 /* XXX: coming soon... */ 1549 return (0); 1550 } 1551 1552 /* 1553 * this routine returns true if a physical page resides 1554 * in the given pmap. 1555 */ 1556 boolean_t 1557 pmap_page_exists(pmap_t pmap, vm_page_t m) 1558 { 1559 #if 0 /* XXX: This must go! */ 1560 register pv_entry_t pv; 1561 int s; 1562 1563 if (!pmap_initialized || (m->flags & PG_FICTITIOUS)) 1564 return FALSE; 1565 1566 s = splvm(); 1567 1568 /* 1569 * Not found, check current mappings returning immediately if found. 1570 */ 1571 for (pv = pv_table; pv; pv = pv->pv_next) { 1572 if (pv->pv_pmap == pmap) { 1573 splx(s); 1574 return TRUE; 1575 } 1576 } 1577 splx(s); 1578 #endif 1579 return (FALSE); 1580 } 1581 1582 /* 1583 * Used to map a range of physical addresses into kernel 1584 * virtual address space. 1585 * 1586 * For now, VM is already on, we only need to map the 1587 * specified memory. 1588 */ 1589 vm_offset_t 1590 pmap_map(vm_offset_t *virt, vm_offset_t start, vm_offset_t end, int prot) 1591 { 1592 vm_offset_t sva, va; 1593 1594 sva = *virt; 1595 va = sva; 1596 1597 while (start < end) { 1598 pmap_kenter(va, start); 1599 va += PAGE_SIZE; 1600 start += PAGE_SIZE; 1601 } 1602 1603 *virt = va; 1604 return (sva); 1605 } 1606 1607 vm_offset_t 1608 pmap_addr_hint(vm_object_t obj, vm_offset_t addr, vm_size_t size) 1609 { 1610 1611 return (addr); 1612 } 1613 1614 int 1615 pmap_mincore(pmap_t pmap, vm_offset_t addr) 1616 { 1617 1618 /* XXX: coming soon... */ 1619 return (0); 1620 } 1621 1622 void 1623 pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, 1624 vm_pindex_t pindex, vm_size_t size, int limit) 1625 { 1626 1627 /* XXX: coming soon... */ 1628 return; 1629 } 1630 1631 void 1632 pmap_growkernel(vm_offset_t addr) 1633 { 1634 1635 /* XXX: coming soon... */ 1636 return; 1637 } 1638 1639 /* 1640 * Initialize the address space (zone) for the pv_entries. Set a 1641 * high water mark so that the system can recover from excessive 1642 * numbers of pv entries. 1643 */ 1644 void 1645 pmap_init2() 1646 { 1647 int shpgperproc = PMAP_SHPGPERPROC; 1648 1649 TUNABLE_INT_FETCH("vm.pmap.shpgperproc", &shpgperproc); 1650 pv_entry_max = shpgperproc * maxproc + vm_page_array_size; 1651 pv_entry_high_water = 9 * (pv_entry_max / 10); 1652 zinitna(pvzone, &pvzone_obj, NULL, 0, pv_entry_max, ZONE_INTERRUPT, 1); 1653 } 1654 1655 void 1656 pmap_swapin_proc(struct proc *p) 1657 { 1658 1659 /* XXX: coming soon... */ 1660 return; 1661 } 1662 1663 void 1664 pmap_swapout_proc(struct proc *p) 1665 { 1666 1667 /* XXX: coming soon... */ 1668 return; 1669 } 1670 1671 1672 /* 1673 * Create the kernel stack (including pcb for i386) for a new thread. 1674 * This routine directly affects the fork perf for a process and 1675 * create performance for a thread. 1676 */ 1677 void 1678 pmap_new_thread(td) 1679 struct thread *td; 1680 { 1681 /* XXX: coming soon... */ 1682 return; 1683 } 1684 1685 /* 1686 * Dispose the kernel stack for a thread that has exited. 1687 * This routine directly impacts the exit perf of a process and thread. 1688 */ 1689 void 1690 pmap_dispose_thread(td) 1691 struct thread *td; 1692 { 1693 /* XXX: coming soon... */ 1694 return; 1695 } 1696 1697 /* 1698 * Allow the Kernel stack for a thread to be prejudicially paged out. 1699 */ 1700 void 1701 pmap_swapout_thread(td) 1702 struct thread *td; 1703 { 1704 int i; 1705 vm_object_t ksobj; 1706 vm_offset_t ks; 1707 vm_page_t m; 1708 1709 ksobj = td->td_kstack_obj; 1710 ks = td->td_kstack; 1711 for (i = 0; i < KSTACK_PAGES; i++) { 1712 m = vm_page_lookup(ksobj, i); 1713 if (m == NULL) 1714 panic("pmap_swapout_thread: kstack already missing?"); 1715 vm_page_dirty(m); 1716 vm_page_unwire(m, 0); 1717 pmap_kremove(ks + i * PAGE_SIZE); 1718 } 1719 } 1720 1721 /* 1722 * Bring the kernel stack for a specified thread back in. 1723 */ 1724 void 1725 pmap_swapin_thread(td) 1726 struct thread *td; 1727 { 1728 int i, rv; 1729 vm_object_t ksobj; 1730 vm_offset_t ks; 1731 vm_page_t m; 1732 1733 ksobj = td->td_kstack_obj; 1734 ks = td->td_kstack; 1735 for (i = 0; i < KSTACK_PAGES; i++) { 1736 m = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); 1737 pmap_kenter(ks + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m)); 1738 if (m->valid != VM_PAGE_BITS_ALL) { 1739 rv = vm_pager_get_pages(ksobj, &m, 1, 0); 1740 if (rv != VM_PAGER_OK) 1741 panic("pmap_swapin_thread: cannot get kstack for proc: %d\n", td->td_proc->p_pid); 1742 m = vm_page_lookup(ksobj, i); 1743 m->valid = VM_PAGE_BITS_ALL; 1744 } 1745 vm_page_wire(m); 1746 vm_page_wakeup(m); 1747 vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE); 1748 } 1749 } 1750 1751 void 1752 pmap_pageable(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, boolean_t pageable) 1753 { 1754 1755 return; 1756 } 1757 1758 void 1759 pmap_change_wiring(pmap_t pmap, vm_offset_t va, boolean_t wired) 1760 { 1761 1762 /* XXX: coming soon... */ 1763 return; 1764 } 1765 1766 void 1767 pmap_prefault(pmap_t pmap, vm_offset_t addra, vm_map_entry_t entry) 1768 { 1769 1770 /* XXX: coming soon... */ 1771 return; 1772 } 1773 1774 void 1775 pmap_remove_pages(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) 1776 { 1777 1778 /* XXX: coming soon... */ 1779 return; 1780 } 1781 1782 void 1783 pmap_pinit0(pmap_t pmap) 1784 { 1785 1786 /* XXX: coming soon... */ 1787 return; 1788 } 1789 1790 void 1791 pmap_dispose_proc(struct proc *p) 1792 { 1793 1794 /* XXX: coming soon... */ 1795 return; 1796 } 1797 1798 vm_offset_t 1799 pmap_steal_memory(vm_size_t size) 1800 { 1801 vm_size_t bank_size; 1802 vm_offset_t pa; 1803 1804 size = round_page(size); 1805 1806 bank_size = phys_avail[1] - phys_avail[0]; 1807 while (size > bank_size) { 1808 int i; 1809 for (i = 0; phys_avail[i+2]; i+= 2) { 1810 phys_avail[i] = phys_avail[i+2]; 1811 phys_avail[i+1] = phys_avail[i+3]; 1812 } 1813 phys_avail[i] = 0; 1814 phys_avail[i+1] = 0; 1815 if (!phys_avail[0]) 1816 panic("pmap_steal_memory: out of memory"); 1817 bank_size = phys_avail[1] - phys_avail[0]; 1818 } 1819 1820 pa = phys_avail[0]; 1821 phys_avail[0] += size; 1822 1823 bzero((caddr_t) pa, size); 1824 return pa; 1825 } 1826 1827 /* 1828 * Create the UAREA_PAGES for a new process. 1829 * This routine directly affects the fork perf for a process. 1830 */ 1831 void 1832 pmap_new_proc(struct proc *p) 1833 { 1834 int i; 1835 vm_object_t upobj; 1836 vm_offset_t up; 1837 vm_page_t m; 1838 pte_t pte; 1839 sr_t sr; 1840 int idx; 1841 vm_offset_t va; 1842 1843 /* 1844 * allocate object for the upages 1845 */ 1846 upobj = p->p_upages_obj; 1847 if (upobj == NULL) { 1848 upobj = vm_object_allocate(OBJT_DEFAULT, UAREA_PAGES); 1849 p->p_upages_obj = upobj; 1850 } 1851 1852 /* get a kernel virtual address for the UAREA_PAGES for this proc */ 1853 up = (vm_offset_t)p->p_uarea; 1854 if (up == 0) { 1855 up = kmem_alloc_nofault(kernel_map, UAREA_PAGES * PAGE_SIZE); 1856 if (up == 0) 1857 panic("pmap_new_proc: upage allocation failed"); 1858 p->p_uarea = (struct user *)up; 1859 } 1860 1861 for (i = 0; i < UAREA_PAGES; i++) { 1862 /* 1863 * Get a kernel stack page 1864 */ 1865 m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); 1866 1867 /* 1868 * Wire the page 1869 */ 1870 m->wire_count++; 1871 cnt.v_wire_count++; 1872 1873 /* 1874 * Enter the page into the kernel address space. 1875 */ 1876 va = up + i * PAGE_SIZE; 1877 idx = pteidx(sr = ptesr(kernel_pmap->pm_sr, va), va); 1878 1879 pte.pte_hi = ((sr & SR_VSID) << PTE_VSID_SHFT) | 1880 ((va & ADDR_PIDX) >> ADDR_API_SHFT); 1881 pte.pte_lo = (VM_PAGE_TO_PHYS(m) & PTE_RPGN) | PTE_M | PTE_I | 1882 PTE_G | PTE_RW; 1883 1884 if (!pte_insert(idx, &pte)) { 1885 struct pte_ovfl *po; 1886 1887 po = poalloc(); 1888 po->po_pte = pte; 1889 LIST_INSERT_HEAD(potable + idx, po, po_list); 1890 } 1891 1892 tlbie(va); 1893 1894 vm_page_wakeup(m); 1895 vm_page_flag_clear(m, PG_ZERO); 1896 vm_page_flag_set(m, PG_MAPPED | PG_WRITEABLE); 1897 m->valid = VM_PAGE_BITS_ALL; 1898 } 1899 } 1900 1901 void * 1902 pmap_mapdev(vm_offset_t pa, vm_size_t len) 1903 { 1904 vm_offset_t faddr; 1905 vm_offset_t taddr, va; 1906 int off; 1907 1908 faddr = trunc_page(pa); 1909 off = pa - faddr; 1910 len = round_page(off + len); 1911 1912 GIANT_REQUIRED; 1913 1914 va = taddr = kmem_alloc_pageable(kernel_map, len); 1915 1916 if (va == 0) 1917 return NULL; 1918 1919 for (; len > 0; len -= PAGE_SIZE) { 1920 pmap_kenter(taddr, faddr); 1921 faddr += PAGE_SIZE; 1922 taddr += PAGE_SIZE; 1923 } 1924 1925 return (void *)(va + off); 1926 } 1927