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