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