1 /* $NetBSD: pmap.c,v 1.113 2002/04/04 16:40:15 ragge Exp $ */ 2 /* 3 * Copyright (c) 1994, 1998, 1999 Ludd, University of Lule}, Sweden. 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 at Ludd, University of Lule}. 17 * 4. The name of the author 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 THE AUTHOR ``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 THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include "opt_ddb.h" 33 #include "opt_cputype.h" 34 #include "opt_multiprocessor.h" 35 #include "opt_lockdebug.h" 36 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include <sys/queue.h> 40 #include <sys/malloc.h> 41 #include <sys/extent.h> 42 #include <sys/proc.h> 43 #include <sys/user.h> 44 #include <sys/systm.h> 45 #include <sys/device.h> 46 #include <sys/buf.h> 47 48 #include <uvm/uvm_extern.h> 49 50 #ifdef PMAPDEBUG 51 #include <dev/cons.h> 52 #endif 53 54 #include <uvm/uvm.h> 55 56 #include <machine/pte.h> 57 #include <machine/pcb.h> 58 #include <machine/mtpr.h> 59 #include <machine/macros.h> 60 #include <machine/sid.h> 61 #include <machine/cpu.h> 62 #include <machine/scb.h> 63 #include <machine/rpb.h> 64 65 /* QDSS console mapping hack */ 66 #include "qd.h" 67 void qdearly(void); 68 69 #define ISTACK_SIZE NBPG 70 vaddr_t istack; 71 /* 72 * This code uses bitfield operators for most page table entries. 73 */ 74 #define PROTSHIFT 27 75 #define PROT_KW (PG_KW >> PROTSHIFT) 76 #define PROT_KR (PG_KR >> PROTSHIFT) 77 #define PROT_RW (PG_RW >> PROTSHIFT) 78 #define PROT_RO (PG_RO >> PROTSHIFT) 79 #define PROT_URKW (PG_URKW >> PROTSHIFT) 80 81 /* 82 * Scratch pages usage: 83 * Page 1: initial frame pointer during autoconfig. Stack and pcb for 84 * processes during exit on boot cpu only. 85 * Page 2: cpu_info struct for any cpu. 86 * Page 3: unused 87 * Page 4: unused 88 */ 89 long scratch; 90 #define SCRATCHPAGES 4 91 92 93 struct pmap kernel_pmap_store; 94 95 struct pte *Sysmap; /* System page table */ 96 struct pv_entry *pv_table; /* array of entries, one per LOGICAL page */ 97 int pventries; 98 vaddr_t iospace; 99 100 vaddr_t ptemapstart, ptemapend; 101 struct extent *ptemap; 102 #define PTMAPSZ EXTENT_FIXED_STORAGE_SIZE(100) 103 char ptmapstorage[PTMAPSZ]; 104 105 extern caddr_t msgbufaddr; 106 107 #define IOSPACE(p) (((u_long)(p)) & 0xe0000000) 108 #define NPTEPROCSPC 0x1000 /* # of virtual PTEs per process space */ 109 #define NPTEPG 0x80 /* # of PTEs per page (logical or physical) */ 110 #define PPTESZ sizeof(struct pte) 111 #define NOVADDR 0xffffffff /* Illegal virtual address */ 112 #define WAITOK M_WAITOK 113 #define NOWAIT M_NOWAIT 114 #define NPTEPERREG 0x200000 115 116 #ifdef PMAPDEBUG 117 volatile int recurse; 118 #define RECURSESTART { \ 119 if (recurse) \ 120 printf("enter at %d, previous %d\n", __LINE__, recurse);\ 121 recurse = __LINE__; \ 122 } 123 #define RECURSEEND {recurse = 0; } 124 #define PMDEBUG(x) if (startpmapdebug)printf x 125 #else 126 #define RECURSESTART 127 #define RECURSEEND 128 #define PMDEBUG(x) 129 #endif 130 131 #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 132 static struct simplelock pvtable_lock; 133 #define PVTABLE_LOCK simple_lock(&pvtable_lock); 134 #define PVTABLE_UNLOCK simple_unlock(&pvtable_lock); 135 #else 136 #define PVTABLE_LOCK 137 #define PVTABLE_UNLOCK 138 #endif 139 140 #ifdef PMAPDEBUG 141 int startpmapdebug = 0; 142 #endif 143 144 vaddr_t avail_start, avail_end; 145 vaddr_t virtual_avail, virtual_end; /* Available virtual memory */ 146 147 struct pv_entry *get_pventry(void); 148 void free_pventry(struct pv_entry *); 149 void more_pventries(void); 150 151 /* 152 * Calculation of the System Page Table is somewhat a pain, because it 153 * must be in contiguous physical memory and all size calculations must 154 * be done before memory management is turned on. 155 * Arg is usrptsize in ptes. 156 */ 157 static vsize_t 158 calc_kvmsize(vsize_t usrptsize) 159 { 160 extern int bufcache; 161 vsize_t kvmsize; 162 int n, s, bp, bc; 163 164 /* All physical memory */ 165 kvmsize = avail_end; 166 /* User Page table area. This may be large */ 167 kvmsize += (usrptsize * sizeof(struct pte)); 168 /* Kernel stacks per process */ 169 kvmsize += (USPACE * maxproc); 170 /* kernel malloc arena */ 171 kvmsize += (NKMEMPAGES_MAX_DEFAULT * NBPG + 172 NKMEMPAGES_MAX_DEFAULT * sizeof(struct kmemusage)); 173 /* IO device register space */ 174 kvmsize += (IOSPSZ * VAX_NBPG); 175 /* Pager allocations */ 176 kvmsize += (PAGER_MAP_SIZE + MAXBSIZE); 177 /* Anon pool structures */ 178 kvmsize += (physmem * sizeof(struct vm_anon)); 179 180 /* allocated buffer space etc... This is a hack */ 181 n = nbuf; s = nswbuf; bp = bufpages; bc = bufcache; 182 kvmsize += (int)allocsys(NULL, NULL); 183 /* Buffer space */ 184 kvmsize += (MAXBSIZE * nbuf); 185 nbuf = n; nswbuf = s; bufpages = bp; bufcache = bc; 186 187 /* UBC submap space */ 188 kvmsize += (UBC_NWINS << UBC_WINSHIFT); 189 190 /* Exec arg space */ 191 kvmsize += NCARGS; 192 #if VAX46 || VAX48 || VAX49 || VAX53 || VAXANY 193 /* Physmap */ 194 kvmsize += VM_PHYS_SIZE; 195 #endif 196 #ifdef LKM 197 /* LKMs are allocated out of kernel_map */ 198 #define MAXLKMSIZ 0x100000 /* XXX */ 199 kvmsize += MAXLKMSIZ; 200 #endif 201 return kvmsize; 202 } 203 204 /* 205 * pmap_bootstrap(). 206 * Called as part of vm bootstrap, allocates internal pmap structures. 207 * Assumes that nothing is mapped, and that kernel stack is located 208 * immediately after end. 209 */ 210 void 211 pmap_bootstrap() 212 { 213 unsigned int sysptsize, i; 214 extern unsigned int etext, proc0paddr; 215 struct pcb *pcb = (struct pcb *)proc0paddr; 216 pmap_t pmap = pmap_kernel(); 217 vsize_t kvmsize, usrptsize; 218 219 /* Set logical page size */ 220 uvmexp.pagesize = NBPG; 221 uvm_setpagesize(); 222 223 physmem = btoc(avail_end); 224 225 usrptsize = PROCPTSIZE * maxproc; 226 if (vax_btop(usrptsize)* PPTESZ > avail_end/20) 227 usrptsize = (avail_end/(20 * PPTESZ)) * VAX_NBPG; 228 229 kvmsize = calc_kvmsize(usrptsize); 230 sysptsize = kvmsize >> VAX_PGSHIFT; 231 /* 232 * Virtual_* and avail_* is used for mapping of system page table. 233 * The need for kernel virtual memory is linear dependent of the 234 * amount of physical memory also, therefore sysptsize is 235 * a variable here that is changed dependent of the physical 236 * memory size. 237 */ 238 virtual_avail = avail_end + KERNBASE; 239 virtual_end = KERNBASE + sysptsize * VAX_NBPG; 240 memset(Sysmap, 0, sysptsize * 4); /* clear SPT before using it */ 241 242 /* 243 * The first part of Kernel Virtual memory is the physical 244 * memory mapped in. This makes some mm routines both simpler 245 * and faster, but takes ~0.75% more memory. 246 */ 247 pmap_map(KERNBASE, 0, avail_end, VM_PROT_READ|VM_PROT_WRITE); 248 /* 249 * Kernel code is always readable for user, it must be because 250 * of the emulation code that is somewhere in there. 251 * And it doesn't hurt, /netbsd is also public readable. 252 * There are also a couple of other things that must be in 253 * physical memory and that isn't managed by the vm system. 254 */ 255 for (i = 0; i < ((unsigned)&etext ^ KERNBASE) >> VAX_PGSHIFT; i++) 256 Sysmap[i].pg_prot = PROT_URKW; 257 258 /* Map System Page Table and zero it, Sysmap already set. */ 259 mtpr((unsigned)Sysmap - KERNBASE, PR_SBR); 260 261 /* Map Interrupt stack and set red zone */ 262 istack = (unsigned)Sysmap + round_page(sysptsize * 4); 263 mtpr(istack + ISTACK_SIZE, PR_ISP); 264 kvtopte(istack)->pg_v = 0; 265 266 /* Some scratch pages */ 267 scratch = istack + ISTACK_SIZE; 268 269 /* Physical-to-virtual translation table */ 270 pv_table = (struct pv_entry *)(scratch + 4 * VAX_NBPG); 271 272 avail_start = (vaddr_t)pv_table + (round_page(avail_end >> PGSHIFT)) * 273 sizeof(struct pv_entry) - KERNBASE; 274 275 /* Kernel message buffer */ 276 avail_end -= MSGBUFSIZE; 277 msgbufaddr = (void *)(avail_end + KERNBASE); 278 279 /* zero all mapped physical memory from Sysmap to here */ 280 memset((void *)istack, 0, (avail_start + KERNBASE) - istack); 281 282 /* QDSS console mapping hack */ 283 #if NQD > 0 284 qdearly(); 285 #endif 286 287 /* User page table map. This is big. */ 288 MAPVIRT(ptemapstart, vax_btoc(usrptsize * sizeof(struct pte))); 289 ptemapend = virtual_avail; 290 291 MAPVIRT(iospace, IOSPSZ); /* Device iospace mapping area */ 292 293 /* Init SCB and set up stray vectors. */ 294 avail_start = scb_init(avail_start); 295 bcopy((caddr_t)proc0paddr + REDZONEADDR, 0, sizeof(struct rpb)); 296 297 if (dep_call->cpu_steal_pages) 298 (*dep_call->cpu_steal_pages)(); 299 300 avail_start = round_page(avail_start); 301 virtual_avail = round_page(virtual_avail); 302 virtual_end = trunc_page(virtual_end); 303 304 305 #if 0 /* Breaks cninit() on some machines */ 306 cninit(); 307 printf("Sysmap %p, istack %lx, scratch %lx\n",Sysmap,istack,scratch); 308 printf("etext %p, kvmsize %lx\n", &etext, kvmsize); 309 printf("SYSPTSIZE %x PROCPTSIZE %x usrptsize %lx\n", 310 sysptsize, PROCPTSIZE, usrptsize * sizeof(struct pte)); 311 printf("pv_table %p, ptemapstart %lx ptemapend %lx\n", 312 pv_table, ptemapstart, ptemapend); 313 printf("avail_start %lx, avail_end %lx\n",avail_start,avail_end); 314 printf("virtual_avail %lx,virtual_end %lx\n", 315 virtual_avail, virtual_end); 316 printf("startpmapdebug %p\n",&startpmapdebug); 317 #endif 318 319 320 /* Init kernel pmap */ 321 pmap->pm_p1br = (struct pte *)KERNBASE; 322 pmap->pm_p0br = (struct pte *)KERNBASE; 323 pmap->pm_p1lr = NPTEPERREG; 324 pmap->pm_p0lr = 0; 325 pmap->pm_stats.wired_count = pmap->pm_stats.resident_count = 0; 326 /* btop(virtual_avail - KERNBASE); */ 327 328 pmap->pm_count = 1; 329 simple_lock_init(&pmap->pm_lock); 330 331 /* Activate the kernel pmap. */ 332 mtpr(pcb->P1BR = pmap->pm_p1br, PR_P1BR); 333 mtpr(pcb->P0BR = pmap->pm_p0br, PR_P0BR); 334 mtpr(pcb->P1LR = pmap->pm_p1lr, PR_P1LR); 335 mtpr(pcb->P0LR = (pmap->pm_p0lr|AST_PCB), PR_P0LR); 336 337 /* cpu_info struct */ 338 pcb->SSP = scratch + VAX_NBPG; 339 mtpr(pcb->SSP, PR_SSP); 340 bzero((caddr_t)pcb->SSP, 341 sizeof(struct cpu_info) + sizeof(struct device)); 342 curcpu()->ci_exit = scratch; 343 curcpu()->ci_dev = (void *)(pcb->SSP + sizeof(struct cpu_info)); 344 #if defined(MULTIPROCESSOR) 345 curcpu()->ci_flags = CI_MASTERCPU|CI_RUNNING; 346 #endif 347 #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) 348 simple_lock_init(&pvtable_lock); 349 #endif 350 351 /* 352 * Now everything should be complete, start virtual memory. 353 */ 354 uvm_page_physload(avail_start >> PGSHIFT, avail_end >> PGSHIFT, 355 avail_start >> PGSHIFT, avail_end >> PGSHIFT, 356 VM_FREELIST_DEFAULT); 357 mtpr(sysptsize, PR_SLR); 358 rpb.sbr = mfpr(PR_SBR); 359 rpb.slr = mfpr(PR_SLR); 360 rpb.wait = 0; /* DDB signal */ 361 mtpr(1, PR_MAPEN); 362 } 363 364 /* 365 * Define the initial bounds of the kernel virtual address space. 366 */ 367 void 368 pmap_virtual_space(vaddr_t *vstartp, vaddr_t *vendp) 369 { 370 371 *vstartp = virtual_avail; 372 *vendp = virtual_end; 373 } 374 375 /* 376 * Let the VM system do early memory allocation from the direct-mapped 377 * physical memory instead. 378 */ 379 vaddr_t 380 pmap_steal_memory(size, vstartp, vendp) 381 vsize_t size; 382 vaddr_t *vstartp, *vendp; 383 { 384 vaddr_t v; 385 int npgs; 386 387 PMDEBUG(("pmap_steal_memory: size 0x%lx start %p end %p\n", 388 size, vstartp, vendp)); 389 390 size = round_page(size); 391 npgs = btoc(size); 392 393 #ifdef DIAGNOSTIC 394 if (uvm.page_init_done == TRUE) 395 panic("pmap_steal_memory: called _after_ bootstrap"); 396 #endif 397 398 /* 399 * A vax only have one segment of memory. 400 */ 401 402 v = (vm_physmem[0].avail_start << PGSHIFT) | KERNBASE; 403 vm_physmem[0].avail_start += npgs; 404 vm_physmem[0].start += npgs; 405 bzero((caddr_t)v, size); 406 return v; 407 } 408 409 /* 410 * pmap_init() is called as part of vm init after memory management 411 * is enabled. It is meant to do machine-specific allocations. 412 * Here is the resource map for the user page tables inited. 413 */ 414 void 415 pmap_init() 416 { 417 /* 418 * Create the extent map used to manage the page table space. 419 * XXX - M_HTABLE is bogus. 420 */ 421 ptemap = extent_create("ptemap", ptemapstart, ptemapend, 422 M_HTABLE, ptmapstorage, PTMAPSZ, EX_NOCOALESCE); 423 if (ptemap == NULL) 424 panic("pmap_init"); 425 } 426 427 static u_long 428 pmap_extwrap(vsize_t nsize) 429 { 430 int res; 431 u_long rv; 432 433 for (;;) { 434 res = extent_alloc(ptemap, nsize, PAGE_SIZE, 0, 435 EX_WAITOK|EX_MALLOCOK, &rv); 436 if (res == EAGAIN) 437 return 0; 438 if (res == 0) 439 return rv; 440 } 441 } 442 443 /* 444 * Do a page removal from the pv table. A page is identified by its 445 * virtual address combined with its struct pmap in the pv table. 446 */ 447 static void 448 rmpage(pmap_t pm, int *br) 449 { 450 struct pv_entry *pv, *pl, *pf; 451 vaddr_t vaddr; 452 int found = 0; 453 454 if (pm == pmap_kernel()) 455 vaddr = (br - (int *)Sysmap) * VAX_NBPG + 0x80000000; 456 else if ((br >= (int *)pm->pm_p0br) && 457 (br < ((int *)pm->pm_p0br + pm->pm_p0lr))) 458 vaddr = (br - (int *)pm->pm_p0br) * VAX_NBPG; 459 else 460 vaddr = (br - (int *)pm->pm_p1br) * VAX_NBPG + 0x40000000; 461 462 pv = pv_table + ((br[0] & PG_FRAME) >> LTOHPS); 463 if (((br[0] & PG_PROT) == PG_RW) && 464 ((pv->pv_attr & PG_M) != PG_M)) 465 pv->pv_attr |= br[0]|br[1]|br[2]|br[3]|br[4]|br[5]|br[6]|br[7]; 466 simple_lock(&pm->pm_lock); 467 pm->pm_stats.resident_count--; 468 if (br[0] & PG_W) 469 pm->pm_stats.wired_count--; 470 simple_unlock(&pm->pm_lock); 471 if (pv->pv_pmap == pm && pv->pv_vaddr == vaddr) { 472 pv->pv_vaddr = NOVADDR; 473 pv->pv_pmap = 0; 474 found++; 475 } else 476 for (pl = pv; pl->pv_next; pl = pl->pv_next) { 477 if (pl->pv_next->pv_pmap != pm || 478 pl->pv_next->pv_vaddr != vaddr) 479 continue; 480 pf = pl->pv_next; 481 pl->pv_next = pl->pv_next->pv_next; 482 free_pventry(pf); 483 found++; 484 break; 485 } 486 if (found == 0) 487 panic("rmpage: pm %p br %p", pm, br); 488 } 489 /* 490 * Update the PCBs using this pmap after a change. 491 */ 492 static void 493 update_pcbs(struct pmap *pm) 494 { 495 struct pm_share *ps; 496 497 ps = pm->pm_share; 498 while (ps != NULL) { 499 ps->ps_pcb->P0BR = pm->pm_p0br; 500 ps->ps_pcb->P0LR = pm->pm_p0lr|AST_PCB; 501 ps->ps_pcb->P1BR = pm->pm_p1br; 502 ps->ps_pcb->P1LR = pm->pm_p1lr; 503 ps = ps->ps_next; 504 } 505 506 /* If curproc uses this pmap update the regs too */ 507 if (pm == curproc->p_vmspace->vm_map.pmap) { 508 mtpr(pm->pm_p0br, PR_P0BR); 509 mtpr(pm->pm_p0lr|AST_PCB, PR_P0LR); 510 mtpr(pm->pm_p1br, PR_P1BR); 511 mtpr(pm->pm_p1lr, PR_P1LR); 512 } 513 #if defined(MULTIPROCESSOR) && defined(notyet) 514 /* If someone else is using this pmap, be sure to reread */ 515 cpu_send_ipi(IPI_DEST_ALL, IPI_NEWPTE); 516 #endif 517 } 518 519 /* 520 * Allocate a page through direct-mapped segment. 521 */ 522 static vaddr_t 523 getpage(int w) 524 { 525 struct vm_page *pg; 526 527 for (;;) { 528 pg = uvm_pagealloc(NULL, 0, NULL, UVM_PGA_ZERO); 529 if (pg != NULL) 530 break; 531 if (w == NOWAIT) 532 return 0; 533 uvm_wait("getpage"); 534 } 535 return (VM_PAGE_TO_PHYS(pg)|KERNBASE); 536 } 537 538 /* 539 * Free the page allocated above. 540 */ 541 static void 542 freepage(vaddr_t v) 543 { 544 paddr_t paddr = (kvtopte(v)->pg_pfn << VAX_PGSHIFT); 545 uvm_pagefree(PHYS_TO_VM_PAGE(paddr)); 546 } 547 548 /* 549 * Remove a full process space. Update all processes pcbs. 550 */ 551 static void 552 rmspace(struct pmap *pm) 553 { 554 int lr, i, j, *br; 555 556 if (pm->pm_p0lr == 0 && pm->pm_p1lr == NPTEPERREG) 557 return; /* Already free */ 558 559 lr = pm->pm_p0lr/1024; 560 for (i = 0; i < lr; i++) { 561 if (pm->pm_pref[i] == 0) 562 continue; 563 br = (int *)&pm->pm_p0br[i*1024]; 564 for (j = 0; j < 1024; j+=8) { 565 if (br[j] == 0) 566 continue; 567 rmpage(pm, &br[j]); 568 if (--pm->pm_pref[i] == 0) { 569 freepage((vaddr_t)br); 570 break; 571 } 572 } 573 } 574 lr = pm->pm_p1lr/1024; 575 for (i = lr; i < 0x800; i++) { 576 if (pm->pm_pref[i+0x800] == 0) 577 continue; 578 br = (int *)&pm->pm_p1br[i*1024]; 579 for (j = 0; j < 1024; j+=8) { 580 if (br[j] == 0) 581 continue; 582 rmpage(pm, &br[j]); 583 if (--pm->pm_pref[i+0x800] == 0) { 584 freepage((vaddr_t)br); 585 break; 586 } 587 } 588 } 589 590 if (pm->pm_p0lr != 0) 591 extent_free(ptemap, (u_long)pm->pm_p0br, 592 pm->pm_p0lr * PPTESZ, EX_WAITOK); 593 if (pm->pm_p1lr != NPTEPERREG) 594 extent_free(ptemap, (u_long)pm->pm_p1ap, 595 (NPTEPERREG - pm->pm_p1lr) * PPTESZ, EX_WAITOK); 596 pm->pm_p0br = pm->pm_p1br = (struct pte *)KERNBASE; 597 pm->pm_p0lr = 0; 598 pm->pm_p1lr = NPTEPERREG; 599 pm->pm_p1ap = NULL; 600 update_pcbs(pm); 601 } 602 603 /* 604 * Find a process to remove the process space for. 605 * This is based on uvm_swapout_threads(). 606 * Avoid to remove ourselves. 607 */ 608 609 #define swappable(p, pm) \ 610 (((p)->p_flag & (P_SYSTEM | P_INMEM | P_WEXIT)) == P_INMEM && \ 611 ((p)->p_holdcnt == 0) && ((p)->p_vmspace->vm_map.pmap != pm)) 612 613 static int 614 pmap_rmproc(struct pmap *pm) 615 { 616 struct pmap *ppm; 617 struct proc *p; 618 struct proc *outp, *outp2; 619 int outpri, outpri2; 620 int didswap = 0; 621 extern int maxslp; 622 623 outp = outp2 = NULL; 624 outpri = outpri2 = 0; 625 proclist_lock_read(); 626 LIST_FOREACH(p, &allproc, p_list) { 627 if (!swappable(p, pm)) 628 continue; 629 ppm = p->p_vmspace->vm_map.pmap; 630 if (ppm->pm_p0lr == 0 && ppm->pm_p1lr == NPTEPERREG) 631 continue; /* Already swapped */ 632 switch (p->p_stat) { 633 case SRUN: 634 case SONPROC: 635 if (p->p_swtime > outpri2) { 636 outp2 = p; 637 outpri2 = p->p_swtime; 638 } 639 continue; 640 case SSLEEP: 641 case SSTOP: 642 if (p->p_slptime >= maxslp) { 643 rmspace(p->p_vmspace->vm_map.pmap); 644 didswap++; 645 } else if (p->p_slptime > outpri) { 646 outp = p; 647 outpri = p->p_slptime; 648 } 649 continue; 650 } 651 } 652 proclist_unlock_read(); 653 if (didswap == 0) { 654 if ((p = outp) == NULL) 655 p = outp2; 656 if (p) { 657 rmspace(p->p_vmspace->vm_map.pmap); 658 didswap++; 659 } 660 } 661 return didswap; 662 } 663 664 /* 665 * Allocate space for user page tables, from ptemap. 666 * This routine should never fail; use the same algorithm as when processes 667 * are swapped. 668 * Argument is needed space, in bytes. 669 * Returns a pointer to the newly allocated space. 670 */ 671 static vaddr_t 672 pmap_getusrptes(pmap_t pm, vsize_t nsize) 673 { 674 u_long rv; 675 676 #ifdef DEBUG 677 if (nsize & PAGE_MASK) 678 panic("pmap_getusrptes: bad size %lx", nsize); 679 #endif 680 while (((rv = pmap_extwrap(nsize)) == 0) && (pmap_rmproc(pm) != 0)) 681 ; 682 if (rv) 683 return rv; 684 panic("usrptmap space leakage"); 685 } 686 687 /* 688 * Remove a pte page when all references are gone. 689 */ 690 static void 691 rmptep(struct pte *pte) 692 { 693 pte = (struct pte *)trunc_page((vaddr_t)pte); 694 #ifdef DEBUG 695 { int i, *ptr = (int *)pte; 696 for (i = 0; i < 1024; i++) 697 if (ptr[i] != 0) 698 panic("rmptep: ptr[%d] != 0", i); 699 } 700 #endif 701 freepage((vaddr_t)pte); 702 bzero(kvtopte(pte), sizeof(struct pte) * LTOHPN); 703 } 704 705 static void 706 grow_p0(struct pmap *pm, int reqlen) 707 { 708 vaddr_t nptespc; 709 char *from, *to; 710 int srclen, dstlen; 711 int inuse, len, p0lr; 712 u_long p0br; 713 714 PMDEBUG(("grow_p0: pmap %p reqlen %d\n", pm, reqlen)); 715 716 /* Get new pte space */ 717 p0lr = pm->pm_p0lr; 718 inuse = p0lr != 0; 719 len = round_page((reqlen+1) * PPTESZ); 720 RECURSEEND; 721 nptespc = pmap_getusrptes(pm, len); 722 RECURSESTART; 723 724 /* 725 * Copy the old ptes to the new space. 726 * Done by moving on system page table. 727 */ 728 srclen = vax_btop(p0lr * PPTESZ) * PPTESZ; 729 dstlen = vax_btoc(len)*PPTESZ; 730 from = (char *)kvtopte(pm->pm_p0br); 731 to = (char *)kvtopte(nptespc); 732 733 PMDEBUG(("grow_p0: from %p to %p src %d dst %d\n", 734 from, to, srclen, dstlen)); 735 736 if (inuse) 737 bcopy(from, to, srclen); 738 bzero(to+srclen, dstlen-srclen); 739 p0br = (u_long)pm->pm_p0br; 740 pm->pm_p0br = (struct pte *)nptespc; 741 pm->pm_p0lr = (len/PPTESZ); 742 update_pcbs(pm); 743 744 /* Remove the old after update_pcbs() (for multicpu propagation) */ 745 if (inuse) 746 extent_free(ptemap, p0br, p0lr*PPTESZ, EX_WAITOK); 747 } 748 749 750 static void 751 grow_p1(struct pmap *pm, int len) 752 { 753 vaddr_t nptespc, optespc; 754 int nlen, olen; 755 756 PMDEBUG(("grow_p1: pm %p len %x\n", pm, len)); 757 758 /* Get new pte space */ 759 nlen = 0x800000 - trunc_page(len * PPTESZ); 760 RECURSEEND; 761 nptespc = pmap_getusrptes(pm, nlen); 762 RECURSESTART; 763 olen = 0x800000 - (pm->pm_p1lr * PPTESZ); 764 optespc = (vaddr_t)pm->pm_p1ap; 765 766 /* 767 * Copy the old ptes to the new space. 768 * Done by moving on system page table. 769 */ 770 bzero(kvtopte(nptespc), vax_btop(nlen-olen) * PPTESZ); 771 if (optespc) 772 bcopy(kvtopte(optespc), kvtopte(nptespc+nlen-olen), 773 vax_btop(olen)); 774 775 pm->pm_p1ap = (struct pte *)nptespc; 776 pm->pm_p1br = (struct pte *)(nptespc+nlen-0x800000); 777 pm->pm_p1lr = NPTEPERREG - nlen/PPTESZ; 778 update_pcbs(pm); 779 780 if (optespc) 781 extent_free(ptemap, optespc, olen, EX_WAITOK); 782 } 783 784 /* 785 * Initialize a preallocated an zeroed pmap structure, 786 */ 787 static void 788 pmap_pinit(pmap_t pmap) 789 { 790 791 /* 792 * Do not allocate any pte's here, we don't know the size and 793 * we'll get a page pault anyway when some page is referenced, 794 * so do it then. 795 */ 796 pmap->pm_p0br = (struct pte *)KERNBASE; 797 pmap->pm_p1br = (struct pte *)KERNBASE; 798 pmap->pm_p0lr = 0; 799 pmap->pm_p1lr = NPTEPERREG; 800 pmap->pm_p1ap = NULL; 801 802 PMDEBUG(("pmap_pinit(%p): p0br=%p p0lr=0x%lx p1br=%p p1lr=0x%lx\n", 803 pmap, pmap->pm_p0br, pmap->pm_p0lr, pmap->pm_p1br, pmap->pm_p1lr)); 804 805 pmap->pm_pref = (u_char *)getpage(WAITOK); 806 pmap->pm_count = 1; 807 pmap->pm_stats.resident_count = pmap->pm_stats.wired_count = 0; 808 } 809 810 /* 811 * pmap_create() creates a pmap for a new task. 812 * If not already allocated, malloc space for one. 813 */ 814 struct pmap * 815 pmap_create() 816 { 817 struct pmap *pmap; 818 819 MALLOC(pmap, struct pmap *, sizeof(*pmap), M_VMPMAP, M_WAITOK); 820 bzero(pmap, sizeof(struct pmap)); 821 pmap_pinit(pmap); 822 simple_lock_init(&pmap->pm_lock); 823 return (pmap); 824 } 825 826 /* 827 * Release any resources held by the given physical map. 828 * Called when a pmap initialized by pmap_pinit is being released. 829 * Should only be called if the map contains no valid mappings. 830 */ 831 static void 832 pmap_release(struct pmap *pmap) 833 { 834 #ifdef DEBUG 835 vaddr_t saddr, eaddr; 836 int i; 837 #endif 838 839 PMDEBUG(("pmap_release: pmap %p\n",pmap)); 840 841 if (pmap->pm_p0br == 0) 842 return; 843 844 #ifdef DEBUG 845 for (i = 0; i < NPTEPROCSPC; i++) 846 if (pmap->pm_pref[i]) 847 panic("pmap_release: refcnt %d index %d", 848 pmap->pm_pref[i], i); 849 850 saddr = (vaddr_t)pmap->pm_p0br; 851 eaddr = saddr + pmap->pm_p0lr * PPTESZ; 852 for (; saddr < eaddr; saddr += NBPG) 853 if (kvtopte(saddr)->pg_pfn) 854 panic("pmap_release: P0 page mapped"); 855 saddr = (vaddr_t)pmap->pm_p1br + pmap->pm_p1lr * PPTESZ; 856 eaddr = KERNBASE; 857 for (; saddr < eaddr; saddr += NBPG) 858 if (kvtopte(saddr)->pg_pfn) 859 panic("pmap_release: P1 page mapped"); 860 #endif 861 freepage((vaddr_t)pmap->pm_pref); 862 863 if (pmap->pm_p0lr != 0) 864 extent_free(ptemap, (u_long)pmap->pm_p0br, 865 pmap->pm_p0lr * PPTESZ, EX_WAITOK); 866 if (pmap->pm_p1lr != NPTEPERREG) 867 extent_free(ptemap, (u_long)pmap->pm_p1ap, 868 (NPTEPERREG - pmap->pm_p1lr) * PPTESZ, EX_WAITOK); 869 } 870 871 /* 872 * pmap_destroy(pmap): Remove a reference from the pmap. 873 * If the pmap is NULL then just return else decrese pm_count. 874 * If this was the last reference we call's pmap_relaese to release this pmap. 875 * OBS! remember to set pm_lock 876 */ 877 878 void 879 pmap_destroy(pmap_t pmap) 880 { 881 int count; 882 883 PMDEBUG(("pmap_destroy: pmap %p\n",pmap)); 884 885 simple_lock(&pmap->pm_lock); 886 count = --pmap->pm_count; 887 simple_unlock(&pmap->pm_lock); 888 889 if (count == 0) { 890 #ifdef DEBUG 891 if (pmap->pm_share) 892 panic("pmap_destroy used pmap"); 893 #endif 894 pmap_release(pmap); 895 FREE(pmap, M_VMPMAP); 896 } 897 } 898 899 static struct pte * 900 vaddrtopte(struct pv_entry *pv) 901 { 902 struct pmap *pm; 903 if (pv->pv_pmap == NULL || pv->pv_vaddr == NOVADDR) 904 return NULL; 905 if (pv->pv_vaddr & KERNBASE) 906 return &Sysmap[(pv->pv_vaddr & ~KERNBASE) >> VAX_PGSHIFT]; 907 pm = pv->pv_pmap; 908 if (pv->pv_vaddr & 0x40000000) 909 return &pm->pm_p1br[vax_btop(pv->pv_vaddr & ~0x40000000)]; 910 else 911 return &pm->pm_p0br[vax_btop(pv->pv_vaddr)]; 912 } 913 914 /* 915 * New (real nice!) function that allocates memory in kernel space 916 * without tracking it in the MD code. 917 */ 918 void 919 pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot) 920 { 921 int *ptp, opte; 922 923 ptp = (int *)kvtopte(va); 924 PMDEBUG(("pmap_kenter_pa: va: %lx, pa %lx, prot %x ptp %p\n", 925 va, pa, prot, ptp)); 926 opte = ptp[0]; 927 ptp[0] = PG_V | ((prot & VM_PROT_WRITE)? PG_KW : PG_KR) | 928 PG_PFNUM(pa) | PG_SREF; 929 ptp[1] = ptp[0] + 1; 930 ptp[2] = ptp[0] + 2; 931 ptp[3] = ptp[0] + 3; 932 ptp[4] = ptp[0] + 4; 933 ptp[5] = ptp[0] + 5; 934 ptp[6] = ptp[0] + 6; 935 ptp[7] = ptp[0] + 7; 936 if (opte & PG_V) { 937 #if defined(MULTIPROCESSOR) 938 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA); 939 #endif 940 mtpr(0, PR_TBIA); 941 } 942 } 943 944 void 945 pmap_kremove(vaddr_t va, vsize_t len) 946 { 947 struct pte *pte; 948 #ifdef PMAPDEBUG 949 int i; 950 #endif 951 952 PMDEBUG(("pmap_kremove: va: %lx, len %lx, ptp %p\n", 953 va, len, kvtopte(va))); 954 955 pte = kvtopte(va); 956 957 #ifdef PMAPDEBUG 958 /* 959 * Check if any pages are on the pv list. 960 * This shouldn't happen anymore. 961 */ 962 len >>= PGSHIFT; 963 for (i = 0; i < len; i++) { 964 if (pte->pg_pfn == 0) 965 continue; 966 if (pte->pg_sref == 0) 967 panic("pmap_kremove"); 968 bzero(pte, LTOHPN * sizeof(struct pte)); 969 pte += LTOHPN; 970 } 971 #else 972 len >>= VAX_PGSHIFT; 973 bzero(pte, len * sizeof(struct pte)); 974 #endif 975 #if defined(MULTIPROCESSOR) 976 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA); 977 #endif 978 mtpr(0, PR_TBIA); 979 } 980 981 /* 982 * pmap_enter() is the main routine that puts in mappings for pages, or 983 * upgrades mappings to more "rights". 984 */ 985 int 986 pmap_enter(pmap, v, p, prot, flags) 987 pmap_t pmap; 988 vaddr_t v; 989 paddr_t p; 990 vm_prot_t prot; 991 int flags; 992 { 993 struct pv_entry *pv, *tmp; 994 int i, s, newpte, oldpte, *patch, idx = 0; /* XXX gcc */ 995 #ifdef PMAPDEBUG 996 boolean_t wired = (flags & PMAP_WIRED) != 0; 997 #endif 998 999 PMDEBUG(("pmap_enter: pmap %p v %lx p %lx prot %x wired %d access %x\n", 1000 pmap, v, p, prot, wired, flags & VM_PROT_ALL)); 1001 1002 RECURSESTART; 1003 /* Find address of correct pte */ 1004 if (v & KERNBASE) { 1005 patch = (int *)Sysmap; 1006 i = (v - KERNBASE) >> VAX_PGSHIFT; 1007 newpte = (p>>VAX_PGSHIFT)|(prot&VM_PROT_WRITE?PG_KW:PG_KR); 1008 } else { 1009 #ifdef DIAGNOSTIC 1010 if (pmap == pmap_kernel()) 1011 panic("pmap_enter in userspace"); 1012 #endif 1013 if (v < 0x40000000) { 1014 i = vax_btop(v); 1015 if (i >= pmap->pm_p0lr) 1016 grow_p0(pmap, i); 1017 patch = (int *)pmap->pm_p0br; 1018 } else { 1019 i = vax_btop(v - 0x40000000); 1020 if (i < pmap->pm_p1lr) 1021 grow_p1(pmap, i); 1022 patch = (int *)pmap->pm_p1br; 1023 } 1024 newpte = (p >> VAX_PGSHIFT) | 1025 (prot & VM_PROT_WRITE ? PG_RW : PG_RO); 1026 1027 /* 1028 * Check if a pte page must be mapped in. 1029 */ 1030 if (pmap->pm_pref == NULL) 1031 panic("pmap->pm_pref"); 1032 idx = (v >> PGSHIFT)/NPTEPG; 1033 1034 if (pmap->pm_pref[idx] == 0) { 1035 vaddr_t ptaddr = trunc_page((vaddr_t)&patch[i]); 1036 paddr_t phys; 1037 #ifdef DEBUG 1038 if (kvtopte(&patch[i])->pg_pfn) 1039 panic("pmap_enter: refcnt == 0"); 1040 #endif 1041 /* 1042 * It seems to be legal to sleep here to wait for 1043 * pages; at least some other ports do so. 1044 */ 1045 phys = getpage(NOWAIT); 1046 if ((phys == 0) && (flags & PMAP_CANFAIL)) { 1047 RECURSEEND; 1048 return ENOMEM; 1049 } 1050 pmap_kenter_pa(ptaddr,phys,VM_PROT_READ|VM_PROT_WRITE); 1051 pmap_update(pmap_kernel()); 1052 } 1053 } 1054 /* 1055 * Do not keep track of anything if mapping IO space. 1056 */ 1057 if (IOSPACE(p)) { 1058 patch[i] = newpte; 1059 patch[i+1] = newpte+1; 1060 patch[i+2] = newpte+2; 1061 patch[i+3] = newpte+3; 1062 patch[i+4] = newpte+4; 1063 patch[i+5] = newpte+5; 1064 patch[i+6] = newpte+6; 1065 patch[i+7] = newpte+7; 1066 if (pmap != pmap_kernel()) 1067 pmap->pm_pref[idx]++; /* New mapping */ 1068 RECURSEEND; 1069 return 0; 1070 } 1071 1072 if (flags & PMAP_WIRED) 1073 newpte |= PG_W; 1074 1075 oldpte = patch[i] & ~(PG_V|PG_M); 1076 pv = pv_table + (p >> PGSHIFT); 1077 1078 /* just a wiring change? */ 1079 if (newpte == (oldpte | PG_W)) { 1080 patch[i] |= PG_W; 1081 pmap->pm_stats.wired_count++; 1082 RECURSEEND; 1083 return 0; 1084 } 1085 1086 /* mapping unchanged? just return. */ 1087 if (newpte == oldpte) { 1088 RECURSEEND; 1089 return 0; 1090 } 1091 1092 /* Changing mapping? */ 1093 1094 if ((newpte & PG_FRAME) == (oldpte & PG_FRAME)) { 1095 /* prot change. resident_count will be increased later */ 1096 pmap->pm_stats.resident_count--; 1097 if (oldpte & PG_W) { 1098 pmap->pm_stats.wired_count--; 1099 } 1100 } else { 1101 1102 /* 1103 * Mapped before? Remove it then. 1104 */ 1105 1106 if (oldpte & PG_FRAME) { 1107 RECURSEEND; 1108 if ((oldpte & PG_SREF) == 0) 1109 rmpage(pmap, &patch[i]); 1110 else 1111 panic("pmap_enter on PG_SREF page"); 1112 RECURSESTART; 1113 } else if (pmap != pmap_kernel()) 1114 pmap->pm_pref[idx]++; /* New mapping */ 1115 1116 s = splvm(); 1117 PVTABLE_LOCK; 1118 if (pv->pv_pmap == NULL) { 1119 pv->pv_vaddr = v; 1120 pv->pv_pmap = pmap; 1121 } else { 1122 tmp = get_pventry(); 1123 tmp->pv_vaddr = v; 1124 tmp->pv_pmap = pmap; 1125 tmp->pv_next = pv->pv_next; 1126 pv->pv_next = tmp; 1127 } 1128 PVTABLE_UNLOCK; 1129 splx(s); 1130 } 1131 pmap->pm_stats.resident_count++; 1132 if (flags & PMAP_WIRED) { 1133 pmap->pm_stats.wired_count++; 1134 } 1135 1136 PVTABLE_LOCK; 1137 if (flags & (VM_PROT_READ|VM_PROT_WRITE)) { 1138 pv->pv_attr |= PG_V; 1139 newpte |= PG_V; 1140 } 1141 if (flags & VM_PROT_WRITE) 1142 pv->pv_attr |= PG_M; 1143 PVTABLE_UNLOCK; 1144 1145 if (flags & PMAP_WIRED) 1146 newpte |= PG_V; /* Not allowed to be invalid */ 1147 1148 patch[i] = newpte; 1149 patch[i+1] = newpte+1; 1150 patch[i+2] = newpte+2; 1151 patch[i+3] = newpte+3; 1152 patch[i+4] = newpte+4; 1153 patch[i+5] = newpte+5; 1154 patch[i+6] = newpte+6; 1155 patch[i+7] = newpte+7; 1156 RECURSEEND; 1157 #ifdef DEBUG 1158 if (pmap != pmap_kernel()) 1159 if (pmap->pm_pref[idx] > VAX_NBPG/sizeof(struct pte)) 1160 panic("pmap_enter: refcnt %d", pmap->pm_pref[idx]); 1161 #endif 1162 if (pventries < 10) 1163 more_pventries(); 1164 1165 mtpr(0, PR_TBIA); /* Always; safety belt */ 1166 return 0; 1167 } 1168 1169 vaddr_t 1170 pmap_map(virtuell, pstart, pend, prot) 1171 vaddr_t virtuell; 1172 paddr_t pstart, pend; 1173 int prot; 1174 { 1175 vaddr_t count; 1176 int *pentry; 1177 1178 PMDEBUG(("pmap_map: virt %lx, pstart %lx, pend %lx, Sysmap %p\n", 1179 virtuell, pstart, pend, Sysmap)); 1180 1181 pstart=(uint)pstart &0x7fffffff; 1182 pend=(uint)pend &0x7fffffff; 1183 virtuell=(uint)virtuell &0x7fffffff; 1184 (uint)pentry= (((uint)(virtuell)>>VAX_PGSHIFT)*4)+(uint)Sysmap; 1185 for(count=pstart;count<pend;count+=VAX_NBPG){ 1186 *pentry++ = (count>>VAX_PGSHIFT)|PG_V| 1187 (prot & VM_PROT_WRITE ? PG_KW : PG_KR); 1188 } 1189 return(virtuell+(count-pstart)+0x80000000); 1190 } 1191 1192 #if 0 1193 boolean_t 1194 pmap_extract(pmap, va, pap) 1195 pmap_t pmap; 1196 vaddr_t va; 1197 paddr_t *pap; 1198 { 1199 paddr_t pa = 0; 1200 int *pte, sva; 1201 1202 PMDEBUG(("pmap_extract: pmap %p, va %lx\n",pmap, va)); 1203 1204 if (va & KERNBASE) { 1205 pa = kvtophys(va); /* Is 0 if not mapped */ 1206 if (pap) 1207 *pap = pa; 1208 if (pa) 1209 return (TRUE); 1210 return (FALSE); 1211 } 1212 1213 sva = PG_PFNUM(va); 1214 if (va < 0x40000000) { 1215 if (sva > pmap->pm_p0lr) 1216 return FALSE; 1217 pte = (int *)pmap->pm_p0br; 1218 } else { 1219 if (sva < pmap->pm_p1lr) 1220 return FALSE; 1221 pte = (int *)pmap->pm_p1br; 1222 } 1223 if (kvtopte(&pte[sva])->pg_pfn) { 1224 if (pap) 1225 *pap = (pte[sva] & PG_FRAME) << VAX_PGSHIFT; 1226 return (TRUE); 1227 } 1228 return (FALSE); 1229 } 1230 #endif 1231 /* 1232 * Sets protection for a given region to prot. If prot == none then 1233 * unmap region. pmap_remove is implemented as pmap_protect with 1234 * protection none. 1235 */ 1236 void 1237 pmap_protect_long(pmap_t pmap, vaddr_t start, vaddr_t end, vm_prot_t prot) 1238 { 1239 struct pte *pt, *pts, *ptd; 1240 int pr, off, idx; 1241 1242 PMDEBUG(("pmap_protect: pmap %p, start %lx, end %lx, prot %x\n", 1243 pmap, start, end,prot)); 1244 1245 RECURSESTART; 1246 if (start & KERNBASE) { /* System space */ 1247 pt = Sysmap; 1248 #ifdef DIAGNOSTIC 1249 if (((end & 0x3fffffff) >> VAX_PGSHIFT) > mfpr(PR_SLR)) 1250 panic("pmap_protect: outside SLR: %lx", end); 1251 #endif 1252 start &= ~KERNBASE; 1253 end &= ~KERNBASE; 1254 pr = (prot & VM_PROT_WRITE ? PROT_KW : PROT_KR); 1255 } else { 1256 if (start & 0x40000000) { /* P1 space */ 1257 if (vax_btop(end - 0x40000000) <= pmap->pm_p1lr) { 1258 RECURSEEND; 1259 return; 1260 } 1261 if (vax_btop(start - 0x40000000) < pmap->pm_p1lr) 1262 start = pmap->pm_p1lr * VAX_NBPG; 1263 pt = pmap->pm_p1br; 1264 start &= 0x3fffffff; 1265 end = (end == KERNBASE ? end >> 1 : end & 0x3fffffff); 1266 off = 0x800; 1267 } else { /* P0 space */ 1268 int lr = pmap->pm_p0lr; 1269 1270 /* Anything to care about at all? */ 1271 if (vax_btop(start) > lr) { 1272 RECURSEEND; 1273 return; 1274 } 1275 if (vax_btop(end) > lr) 1276 end = lr * VAX_NBPG; 1277 pt = pmap->pm_p0br; 1278 off = 0; 1279 } 1280 pr = (prot & VM_PROT_WRITE ? PROT_RW : PROT_RO); 1281 } 1282 pts = &pt[start >> VAX_PGSHIFT]; 1283 ptd = &pt[end >> VAX_PGSHIFT]; 1284 #ifdef DEBUG 1285 if (((int)pts - (int)pt) & 7) 1286 panic("pmap_remove: pts not even"); 1287 if (((int)ptd - (int)pt) & 7) 1288 panic("pmap_remove: ptd not even"); 1289 #endif 1290 1291 while (pts < ptd) { 1292 if (kvtopte(pts)->pg_pfn && *(int *)pts) { 1293 if (prot == VM_PROT_NONE) { 1294 RECURSEEND; 1295 if ((*(int *)pts & PG_SREF) == 0) 1296 rmpage(pmap, (u_int *)pts); 1297 #ifdef DEBUG 1298 else 1299 panic("pmap_remove PG_SREF page"); 1300 #endif 1301 RECURSESTART; 1302 bzero(pts, sizeof(struct pte) * LTOHPN); 1303 if (pt != Sysmap) { 1304 idx = ((pts - pt) >> LTOHPS)/NPTEPG + off; 1305 if (--pmap->pm_pref[idx] == 0) 1306 rmptep(pts); 1307 } 1308 } else { 1309 pts[0].pg_prot = pr; 1310 pts[1].pg_prot = pr; 1311 pts[2].pg_prot = pr; 1312 pts[3].pg_prot = pr; 1313 pts[4].pg_prot = pr; 1314 pts[5].pg_prot = pr; 1315 pts[6].pg_prot = pr; 1316 pts[7].pg_prot = pr; 1317 } 1318 } 1319 pts += LTOHPN; 1320 } 1321 RECURSEEND; 1322 #ifdef MULTIPROCESSOR 1323 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA); 1324 #endif 1325 mtpr(0, PR_TBIA); 1326 } 1327 1328 int pmap_simulref(int bits, int addr); 1329 /* 1330 * Called from interrupt vector routines if we get a page invalid fault. 1331 * Note: the save mask must be or'ed with 0x3f for this function. 1332 * Returns 0 if normal call, 1 if CVAX bug detected. 1333 */ 1334 int 1335 pmap_simulref(int bits, int addr) 1336 { 1337 u_int *pte; 1338 struct pv_entry *pv; 1339 paddr_t pa; 1340 1341 PMDEBUG(("pmap_simulref: bits %x addr %x\n", bits, addr)); 1342 1343 #ifdef DEBUG 1344 if (bits & 1) 1345 panic("pte trans len"); 1346 #endif 1347 /* Set addess on logical page boundary */ 1348 addr &= ~PGOFSET; 1349 /* First decode userspace addr */ 1350 if (addr >= 0) { 1351 if ((addr << 1) < 0) 1352 pte = (u_int *)mfpr(PR_P1BR); 1353 else 1354 pte = (u_int *)mfpr(PR_P0BR); 1355 pte += PG_PFNUM(addr); 1356 if (bits & 2) { /* PTE reference */ 1357 pte = (u_int *)kvtopte(trunc_page((vaddr_t)pte)); 1358 if (pte[0] == 0) /* Check for CVAX bug */ 1359 return 1; 1360 pa = (u_int)pte & ~KERNBASE; 1361 } else 1362 pa = Sysmap[PG_PFNUM(pte)].pg_pfn << VAX_PGSHIFT; 1363 } else { 1364 pte = (u_int *)kvtopte(addr); 1365 pa = (u_int)pte & ~KERNBASE; 1366 } 1367 pte[0] |= PG_V; 1368 pte[1] |= PG_V; 1369 pte[2] |= PG_V; 1370 pte[3] |= PG_V; 1371 pte[4] |= PG_V; 1372 pte[5] |= PG_V; 1373 pte[6] |= PG_V; 1374 pte[7] |= PG_V; 1375 if (IOSPACE(pa) == 0) { /* No pv_table fiddling in iospace */ 1376 PVTABLE_LOCK; 1377 pv = pv_table + (pa >> PGSHIFT); 1378 pv->pv_attr |= PG_V; /* Referenced */ 1379 if (bits & 4) /* (will be) modified. XXX page tables */ 1380 pv->pv_attr |= PG_M; 1381 PVTABLE_UNLOCK; 1382 } 1383 return 0; 1384 } 1385 1386 /* 1387 * Clears valid bit in all ptes referenced to this physical page. 1388 */ 1389 boolean_t 1390 pmap_clear_reference_long(struct pv_entry *pv) 1391 { 1392 struct pte *pte; 1393 int ref = 0; 1394 1395 PMDEBUG(("pmap_clear_reference: pv_entry %p\n", pv)); 1396 1397 RECURSESTART; 1398 PVTABLE_LOCK; 1399 if (pv->pv_pmap != NULL) { 1400 pte = vaddrtopte(pv); 1401 if (pte->pg_w == 0) { 1402 pte[0].pg_v = pte[1].pg_v = pte[2].pg_v = 1403 pte[3].pg_v = pte[4].pg_v = pte[5].pg_v = 1404 pte[6].pg_v = pte[7].pg_v = 0; 1405 } 1406 } 1407 1408 while ((pv = pv->pv_next)) { 1409 pte = vaddrtopte(pv); 1410 if (pte[0].pg_w == 0) { 1411 pte[0].pg_v = pte[1].pg_v = 1412 pte[2].pg_v = pte[3].pg_v = 1413 pte[4].pg_v = pte[5].pg_v = 1414 pte[6].pg_v = pte[7].pg_v = 0; 1415 } 1416 } 1417 PVTABLE_UNLOCK; 1418 RECURSEEND; 1419 #ifdef MULTIPROCESSOR 1420 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA); 1421 #endif 1422 mtpr(0, PR_TBIA); 1423 return ref; 1424 } 1425 1426 /* 1427 * Checks if page is modified; returns true or false depending on result. 1428 */ 1429 boolean_t 1430 pmap_is_modified_long(struct pv_entry *pv) 1431 { 1432 struct pte *pte; 1433 1434 PMDEBUG(("pmap_is_modified: pv_entry %p ", pv)); 1435 1436 PVTABLE_LOCK; 1437 if (pv->pv_pmap != NULL) { 1438 pte = vaddrtopte(pv); 1439 if ((pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m | 1440 pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m)) { 1441 PMDEBUG(("Yes: (1)\n")); 1442 PVTABLE_UNLOCK; 1443 return 1; 1444 } 1445 } 1446 1447 while ((pv = pv->pv_next)) { 1448 pte = vaddrtopte(pv); 1449 if ((pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m 1450 | pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m)) { 1451 PMDEBUG(("Yes: (2)\n")); 1452 PVTABLE_UNLOCK; 1453 return 1; 1454 } 1455 } 1456 PVTABLE_UNLOCK; 1457 PMDEBUG(("No\n")); 1458 return 0; 1459 } 1460 1461 /* 1462 * Clears modify bit in all ptes referenced to this physical page. 1463 */ 1464 boolean_t 1465 pmap_clear_modify_long(struct pv_entry *pv) 1466 { 1467 struct pte *pte; 1468 boolean_t rv = FALSE; 1469 1470 PMDEBUG(("pmap_clear_modify: pv_entry %p\n", pv)); 1471 1472 PVTABLE_LOCK; 1473 if (pv->pv_pmap != NULL) { 1474 pte = vaddrtopte(pv); 1475 if (pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m | 1476 pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m) { 1477 rv = TRUE; 1478 } 1479 pte[0].pg_m = pte[1].pg_m = pte[2].pg_m = pte[3].pg_m = 1480 pte[4].pg_m = pte[5].pg_m = pte[6].pg_m = pte[7].pg_m = 0; 1481 } 1482 1483 while ((pv = pv->pv_next)) { 1484 pte = vaddrtopte(pv); 1485 if (pte[0].pg_m | pte[1].pg_m | pte[2].pg_m | pte[3].pg_m | 1486 pte[4].pg_m | pte[5].pg_m | pte[6].pg_m | pte[7].pg_m) { 1487 rv = TRUE; 1488 } 1489 pte[0].pg_m = pte[1].pg_m = pte[2].pg_m = pte[3].pg_m = 1490 pte[4].pg_m = pte[5].pg_m = pte[6].pg_m = pte[7].pg_m = 0; 1491 } 1492 PVTABLE_UNLOCK; 1493 return rv; 1494 } 1495 1496 /* 1497 * Lower the permission for all mappings to a given page. 1498 * Lower permission can only mean setting protection to either read-only 1499 * or none; where none is unmapping of the page. 1500 */ 1501 void 1502 pmap_page_protect_long(struct pv_entry *pv, vm_prot_t prot) 1503 { 1504 struct pte *pt; 1505 struct pv_entry *opv, *pl; 1506 int s, *g; 1507 1508 PMDEBUG(("pmap_page_protect: pv %p, prot %x\n", pv, prot)); 1509 1510 1511 if (prot == VM_PROT_ALL) /* 'cannot happen' */ 1512 return; 1513 1514 RECURSESTART; 1515 PVTABLE_LOCK; 1516 if (prot == VM_PROT_NONE) { 1517 s = splvm(); 1518 g = (int *)vaddrtopte(pv); 1519 if (g) { 1520 int idx; 1521 1522 simple_lock(&pv->pv_pmap->pm_lock); 1523 pv->pv_pmap->pm_stats.resident_count--; 1524 if (g[0] & PG_W) { 1525 pv->pv_pmap->pm_stats.wired_count--; 1526 } 1527 simple_unlock(&pv->pv_pmap->pm_lock); 1528 if ((pv->pv_attr & (PG_V|PG_M)) != (PG_V|PG_M)) 1529 pv->pv_attr |= 1530 g[0]|g[1]|g[2]|g[3]|g[4]|g[5]|g[6]|g[7]; 1531 bzero(g, sizeof(struct pte) * LTOHPN); 1532 if (pv->pv_pmap != pmap_kernel()) { 1533 idx = pv->pv_vaddr/(VAX_NBPG*NPTEPG*LTOHPN); 1534 if (--pv->pv_pmap->pm_pref[idx] == 0) 1535 rmptep((void *)g); 1536 } 1537 pv->pv_vaddr = NOVADDR; 1538 pv->pv_pmap = NULL; 1539 } 1540 pl = pv->pv_next; 1541 pv->pv_pmap = 0; 1542 pv->pv_next = 0; 1543 while (pl) { 1544 int idx; 1545 1546 g = (int *)vaddrtopte(pl); 1547 simple_lock(&pl->pv_pmap->pm_lock); 1548 pl->pv_pmap->pm_stats.resident_count--; 1549 if (g[0] & PG_W) { 1550 pl->pv_pmap->pm_stats.wired_count--; 1551 } 1552 simple_unlock(&pl->pv_pmap->pm_lock); 1553 if ((pv->pv_attr & (PG_V|PG_M)) != (PG_V|PG_M)) 1554 pv->pv_attr |= 1555 g[0]|g[1]|g[2]|g[3]|g[4]|g[5]|g[6]|g[7]; 1556 bzero(g, sizeof(struct pte) * LTOHPN); 1557 if (pl->pv_pmap != pmap_kernel()) { 1558 idx = pl->pv_vaddr/(VAX_NBPG*NPTEPG*LTOHPN); 1559 if (--pl->pv_pmap->pm_pref[idx] == 0) 1560 rmptep((void *)g); 1561 } 1562 opv = pl; 1563 pl = pl->pv_next; 1564 free_pventry(opv); 1565 } 1566 splx(s); 1567 } else { /* read-only */ 1568 do { 1569 pt = vaddrtopte(pv); 1570 if (pt == 0) 1571 continue; 1572 pt[0].pg_prot = pt[1].pg_prot = 1573 pt[2].pg_prot = pt[3].pg_prot = 1574 pt[4].pg_prot = pt[5].pg_prot = 1575 pt[6].pg_prot = pt[7].pg_prot = 1576 ((vaddr_t)pt < ptemapstart ? PROT_KR : PROT_RO); 1577 } while ((pv = pv->pv_next)); 1578 } 1579 PVTABLE_UNLOCK; 1580 RECURSEEND; 1581 #ifdef MULTIPROCESSOR 1582 cpu_send_ipi(IPI_DEST_ALL, IPI_TBIA); 1583 #endif 1584 mtpr(0, PR_TBIA); 1585 } 1586 1587 /* 1588 * Activate the address space for the specified process. 1589 * Note that if the process to activate is the current process, then 1590 * the processor internal registers must also be loaded; otherwise 1591 * the current process will have wrong pagetables. 1592 */ 1593 void 1594 pmap_activate(struct proc *p) 1595 { 1596 struct pm_share *ps; 1597 pmap_t pmap; 1598 struct pcb *pcb; 1599 1600 PMDEBUG(("pmap_activate: p %p\n", p)); 1601 1602 pmap = p->p_vmspace->vm_map.pmap; 1603 pcb = &p->p_addr->u_pcb; 1604 1605 pcb->P0BR = pmap->pm_p0br; 1606 pcb->P0LR = pmap->pm_p0lr|AST_PCB; 1607 pcb->P1BR = pmap->pm_p1br; 1608 pcb->P1LR = pmap->pm_p1lr; 1609 1610 ps = (struct pm_share *)get_pventry(); 1611 ps->ps_next = pmap->pm_share; 1612 pmap->pm_share = ps; 1613 ps->ps_pcb = pcb; 1614 1615 if (p == curproc) { 1616 mtpr(pmap->pm_p0br, PR_P0BR); 1617 mtpr(pmap->pm_p0lr|AST_PCB, PR_P0LR); 1618 mtpr(pmap->pm_p1br, PR_P1BR); 1619 mtpr(pmap->pm_p1lr, PR_P1LR); 1620 mtpr(0, PR_TBIA); 1621 } 1622 } 1623 1624 void 1625 pmap_deactivate(struct proc *p) 1626 { 1627 struct pm_share *ps, *ops; 1628 pmap_t pmap; 1629 struct pcb *pcb; 1630 1631 PMDEBUG(("pmap_deactivate: p %p\n", p)); 1632 1633 pmap = p->p_vmspace->vm_map.pmap; 1634 pcb = &p->p_addr->u_pcb; 1635 1636 ps = pmap->pm_share; 1637 if (ps->ps_pcb == pcb) { 1638 pmap->pm_share = ps->ps_next; 1639 free_pventry((struct pv_entry *)ps); 1640 return; 1641 } 1642 ops = ps; 1643 ps = ps->ps_next; 1644 while (ps != NULL) { 1645 if (ps->ps_pcb == pcb) { 1646 ops->ps_next = ps->ps_next; 1647 free_pventry((struct pv_entry *)ps); 1648 return; 1649 } 1650 ops = ps; 1651 ps = ps->ps_next; 1652 } 1653 #ifdef DEBUG 1654 panic("pmap_deactivate: not in list"); 1655 #endif 1656 } 1657 1658 /* 1659 * removes the wired bit from a bunch of PTE's. 1660 */ 1661 void 1662 pmap_unwire(pmap_t pmap, vaddr_t v) 1663 { 1664 int *pte; 1665 1666 PMDEBUG(("pmap_unwire: pmap %p v %lx\n", pmap, v)); 1667 1668 RECURSESTART; 1669 if (v & KERNBASE) { 1670 pte = (int *)kvtopte(v); 1671 } else { 1672 if (v < 0x40000000) 1673 pte = (int *)&pmap->pm_p0br[PG_PFNUM(v)]; 1674 else 1675 pte = (int *)&pmap->pm_p1br[PG_PFNUM(v)]; 1676 } 1677 pte[0] &= ~PG_W; 1678 RECURSEEND; 1679 pmap->pm_stats.wired_count--; 1680 } 1681 1682 /* 1683 * pv_entry functions. 1684 */ 1685 struct pv_entry *pv_list; 1686 1687 /* 1688 * get_pventry(). 1689 * The pv_table lock must be held before calling this. 1690 */ 1691 struct pv_entry * 1692 get_pventry() 1693 { 1694 struct pv_entry *tmp; 1695 1696 if (pventries == 0) 1697 panic("get_pventry"); 1698 1699 tmp = pv_list; 1700 pv_list = tmp->pv_next; 1701 pventries--; 1702 return tmp; 1703 } 1704 1705 /* 1706 * free_pventry(). 1707 * The pv_table lock must be held before calling this. 1708 */ 1709 void 1710 free_pventry(pv) 1711 struct pv_entry *pv; 1712 { 1713 pv->pv_next = pv_list; 1714 pv_list = pv; 1715 pventries++; 1716 } 1717 1718 /* 1719 * more_pventries(). 1720 * The pv_table lock must _not_ be held before calling this. 1721 */ 1722 void 1723 more_pventries() 1724 { 1725 struct pv_entry *pv; 1726 int s, i, count; 1727 1728 pv = (struct pv_entry *)getpage(NOWAIT); 1729 if (pv == NULL) 1730 return; 1731 count = NBPG/sizeof(struct pv_entry); 1732 1733 for (i = 0; i < count; i++) 1734 pv[i].pv_next = &pv[i + 1]; 1735 1736 s = splvm(); 1737 PVTABLE_LOCK; 1738 pv[count - 1].pv_next = pv_list; 1739 pv_list = pv; 1740 pventries += count; 1741 PVTABLE_UNLOCK; 1742 splx(s); 1743 } 1744 1745 1746 /* 1747 * Called when a process is about to be swapped, to remove the page tables. 1748 */ 1749 void 1750 cpu_swapout(struct proc *p) 1751 { 1752 pmap_t pm; 1753 1754 PMDEBUG(("Swapout pid %d\n", p->p_pid)); 1755 1756 pm = p->p_vmspace->vm_map.pmap; 1757 rmspace(pm); 1758 pmap_deactivate(p); 1759 } 1760 1761 /* 1762 * Kernel stack red zone need to be set when a process is swapped in. 1763 * Be sure that all pages are valid. 1764 */ 1765 void 1766 cpu_swapin(struct proc *p) 1767 { 1768 struct pte *pte; 1769 int i; 1770 1771 PMDEBUG(("Swapin pid %d\n", p->p_pid)); 1772 1773 pte = kvtopte((vaddr_t)p->p_addr); 1774 for (i = 0; i < (USPACE/VAX_NBPG); i ++) 1775 pte[i].pg_v = 1; 1776 kvtopte((vaddr_t)p->p_addr + REDZONEADDR)->pg_v = 0; 1777 pmap_activate(p); 1778 } 1779 1780