1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * the Systems Programming Group of the University of Utah Computer 7 * Science Department and William Jolitz of UUNET Technologies Inc. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)pmap.c 8.1 (Berkeley) 06/11/93 12 */ 13 14 /* 15 * Derived from hp300 version by Mike Hibler, this version by William 16 * Jolitz uses a recursive map [a pde points to the page directory] to 17 * map the page tables using the pagetables themselves. This is done to 18 * reduce the impact on kernel virtual memory for lots of sparse address 19 * space, and to reduce the cost of memory to each process. 20 * 21 * Derived from: hp300/@(#)pmap.c 7.1 (Berkeley) 12/5/90 22 */ 23 24 /* 25 * Reno i386 version, from Mike Hibler's hp300 version. 26 */ 27 28 /* 29 * Manages physical address maps. 30 * 31 * In addition to hardware address maps, this 32 * module is called upon to provide software-use-only 33 * maps which may or may not be stored in the same 34 * form as hardware maps. These pseudo-maps are 35 * used to store intermediate results from copy 36 * operations to and from address spaces. 37 * 38 * Since the information managed by this module is 39 * also stored by the logical address mapping module, 40 * this module may throw away valid virtual-to-physical 41 * mappings at almost any time. However, invalidations 42 * of virtual-to-physical mappings must be done as 43 * requested. 44 * 45 * In order to cope with hardware architectures which 46 * make virtual-to-physical map invalidates expensive, 47 * this module may delay invalidate or reduced protection 48 * operations until such time as they are actually 49 * necessary. This module is given full information as 50 * to which processors are currently using which maps, 51 * and to when physical maps must be made correct. 52 */ 53 54 #include <sys/param.h> 55 #include <sys/proc.h> 56 #include <sys/malloc.h> 57 #include <sys/user.h> 58 59 #include <vm/vm.h> 60 #include <vm/vm_kern.h> 61 #include <vm/vm_page.h> 62 63 #ifdef NOTDEF 64 include <vm/vm_pageout.h> 65 include <machine/isa.h> 66 #endif 67 68 /* 69 * Allocate various and sundry SYSMAPs used in the days of old VM 70 * and not yet converted. XXX. 71 */ 72 #define BSDVM_COMPAT 1 73 74 #ifdef DEBUG 75 struct { 76 int kernel; /* entering kernel mapping */ 77 int user; /* entering user mapping */ 78 int ptpneeded; /* needed to allocate a PT page */ 79 int pwchange; /* no mapping change, just wiring or protection */ 80 int wchange; /* no mapping change, just wiring */ 81 int mchange; /* was mapped but mapping to different page */ 82 int managed; /* a managed page */ 83 int firstpv; /* first mapping for this PA */ 84 int secondpv; /* second mapping for this PA */ 85 int ci; /* cache inhibited */ 86 int unmanaged; /* not a managed page */ 87 int flushes; /* cache flushes */ 88 } enter_stats; 89 struct { 90 int calls; 91 int removes; 92 int pvfirst; 93 int pvsearch; 94 int ptinvalid; 95 int uflushes; 96 int sflushes; 97 } remove_stats; 98 99 int debugmap = 0; 100 int pmapdebug = 0; 101 #define PDB_FOLLOW 0x0001 102 #define PDB_INIT 0x0002 103 #define PDB_ENTER 0x0004 104 #define PDB_REMOVE 0x0008 105 #define PDB_CREATE 0x0010 106 #define PDB_PTPAGE 0x0020 107 #define PDB_CACHE 0x0040 108 #define PDB_BITS 0x0080 109 #define PDB_COLLECT 0x0100 110 #define PDB_PROTECT 0x0200 111 #define PDB_PDRTAB 0x0400 112 #define PDB_PARANOIA 0x2000 113 #define PDB_WIRING 0x4000 114 #define PDB_PVDUMP 0x8000 115 116 int pmapvacflush = 0; 117 #define PVF_ENTER 0x01 118 #define PVF_REMOVE 0x02 119 #define PVF_PROTECT 0x04 120 #define PVF_TOTAL 0x80 121 #endif 122 123 /* 124 * Get PDEs and PTEs for user/kernel address space 125 */ 126 #define pmap_pde(m, v) (&((m)->pm_pdir[((vm_offset_t)(v) >> PD_SHIFT)&1023])) 127 128 #define pmap_pte_pa(pte) (*(int *)(pte) & PG_FRAME) 129 130 #define pmap_pde_v(pte) ((pte)->pd_v) 131 #define pmap_pte_w(pte) ((pte)->pg_w) 132 /* #define pmap_pte_ci(pte) ((pte)->pg_ci) */ 133 #define pmap_pte_m(pte) ((pte)->pg_m) 134 #define pmap_pte_u(pte) ((pte)->pg_u) 135 #define pmap_pte_v(pte) ((pte)->pg_v) 136 #define pmap_pte_set_w(pte, v) ((pte)->pg_w = (v)) 137 #define pmap_pte_set_prot(pte, v) ((pte)->pg_prot = (v)) 138 139 /* 140 * Given a map and a machine independent protection code, 141 * convert to a vax protection code. 142 */ 143 #define pte_prot(m, p) (protection_codes[p]) 144 int protection_codes[8]; 145 146 struct pmap kernel_pmap_store; 147 148 vm_offset_t avail_start; /* PA of first available physical page */ 149 vm_offset_t avail_end; /* PA of last available physical page */ 150 vm_size_t mem_size; /* memory size in bytes */ 151 vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/ 152 vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ 153 vm_offset_t vm_first_phys; /* PA of first managed page */ 154 vm_offset_t vm_last_phys; /* PA just past last managed page */ 155 int i386pagesperpage; /* PAGE_SIZE / I386_PAGE_SIZE */ 156 boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ 157 char *pmap_attributes; /* reference and modify bits */ 158 159 boolean_t pmap_testbit(); 160 void pmap_clear_modify(); 161 162 #if BSDVM_COMPAT 163 #include <sys/msgbuf.h> 164 165 /* 166 * All those kernel PT submaps that BSD is so fond of 167 */ 168 struct pte *CMAP1, *CMAP2, *mmap; 169 caddr_t CADDR1, CADDR2, vmmap; 170 struct pte *msgbufmap; 171 struct msgbuf *msgbufp; 172 #endif 173 174 void pmap_activate __P((pmap_t, struct pcb *)); 175 176 /* 177 * Bootstrap the system enough to run with virtual memory. 178 * Map the kernel's code and data, and allocate the system page table. 179 * 180 * On the I386 this is called after mapping has already been enabled 181 * and just syncs the pmap module with what has already been done. 182 * [We can't call it easily with mapping off since the kernel is not 183 * mapped with PA == VA, hence we would have to relocate every address 184 * from the linked base (virtual) address 0xFE000000 to the actual 185 * (physical) address starting relative to 0] 186 */ 187 struct pte *pmap_pte(); 188 189 extern vm_offset_t atdevbase; 190 void 191 pmap_bootstrap(firstaddr, loadaddr) 192 vm_offset_t firstaddr; 193 vm_offset_t loadaddr; 194 { 195 #if BSDVM_COMPAT 196 vm_offset_t va; 197 struct pte *pte; 198 #endif 199 extern vm_offset_t maxmem, physmem; 200 extern int IdlePTD; 201 202 203 /* disable pageing in basemem for all machines until this cryptic comment 204 * can be explained 205 */ 206 #if 1 || defined(ODYSSEUS) || defined(ARGO) || defined(CIRCE) 207 firstaddr=0x100000; /* for some reason, basemem screws up on this machine */ 208 #endif 209 printf("ps %x pe %x ", firstaddr, maxmem <<PG_SHIFT); 210 avail_start = firstaddr; 211 avail_end = maxmem << PG_SHIFT; 212 213 /* XXX: allow for msgbuf */ 214 avail_end -= i386_round_page(sizeof(struct msgbuf)); 215 216 mem_size = physmem << PG_SHIFT; 217 virtual_avail = atdevbase + 0x100000 - 0xa0000 + 10*NBPG; 218 virtual_end = VM_MAX_KERNEL_ADDRESS; 219 i386pagesperpage = PAGE_SIZE / I386_PAGE_SIZE; 220 221 /* 222 * Initialize protection array. 223 */ 224 i386_protection_init(); 225 226 #ifdef notdef 227 /* 228 * Create Kernel page directory table and page maps. 229 * [ currently done in locore. i have wild and crazy ideas -wfj ] 230 */ 231 bzero(firstaddr, 4*NBPG); 232 kernel_pmap->pm_pdir = firstaddr + VM_MIN_KERNEL_ADDRESS; 233 kernel_pmap->pm_ptab = firstaddr + VM_MIN_KERNEL_ADDRESS + NBPG; 234 235 firstaddr += NBPG; 236 for (x = i386_btod(VM_MIN_KERNEL_ADDRESS); 237 x < i386_btod(VM_MIN_KERNEL_ADDRESS)+3; x++) { 238 struct pde *pde; 239 pde = kernel_pmap->pm_pdir + x; 240 *(int *)pde = firstaddr + x*NBPG | PG_V | PG_KW; 241 } 242 #else 243 kernel_pmap->pm_pdir = (pd_entry_t *)(0xfe000000 + IdlePTD); 244 #endif 245 246 247 simple_lock_init(&kernel_pmap->pm_lock); 248 kernel_pmap->pm_count = 1; 249 250 #if BSDVM_COMPAT 251 /* 252 * Allocate all the submaps we need 253 */ 254 #define SYSMAP(c, p, v, n) \ 255 v = (c)va; va += ((n)*I386_PAGE_SIZE); p = pte; pte += (n); 256 257 va = virtual_avail; 258 pte = pmap_pte(kernel_pmap, va); 259 260 SYSMAP(caddr_t ,CMAP1 ,CADDR1 ,1 ) 261 SYSMAP(caddr_t ,CMAP2 ,CADDR2 ,1 ) 262 SYSMAP(caddr_t ,mmap ,vmmap ,1 ) 263 SYSMAP(struct msgbuf * ,msgbufmap ,msgbufp ,1 ) 264 virtual_avail = va; 265 #endif 266 267 /**(int *)PTD = 0; 268 load_cr3(rcr3());*/ 269 270 } 271 272 pmap_isvalidphys(addr) { 273 if (addr < 0xa0000) return (1); 274 if (addr >= 0x100000) return (1); 275 return(0); 276 } 277 278 /* 279 * Bootstrap memory allocator. This function allows for early dynamic 280 * memory allocation until the virtual memory system has been bootstrapped. 281 * After that point, either kmem_alloc or malloc should be used. This 282 * function works by stealing pages from the (to be) managed page pool, 283 * stealing virtual address space, then mapping the pages and zeroing them. 284 * 285 * It should be used from pmap_bootstrap till vm_page_startup, afterwards 286 * it cannot be used, and will generate a panic if tried. Note that this 287 * memory will never be freed, and in essence it is wired down. 288 */ 289 void * 290 pmap_bootstrap_alloc(size) { 291 vm_offset_t val; 292 int i; 293 extern boolean_t vm_page_startup_initialized; 294 295 if (vm_page_startup_initialized) 296 panic("pmap_bootstrap_alloc: called after startup initialized"); 297 size = round_page(size); 298 val = virtual_avail; 299 300 /* deal with "hole incursion" */ 301 for (i = 0; i < size; i += PAGE_SIZE) { 302 303 while (!pmap_isvalidphys(avail_start)) 304 avail_start += PAGE_SIZE; 305 306 virtual_avail = pmap_map(virtual_avail, avail_start, 307 avail_start + PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE); 308 avail_start += PAGE_SIZE; 309 } 310 311 blkclr ((caddr_t) val, size); 312 return ((void *) val); 313 } 314 315 /* 316 * Initialize the pmap module. 317 * Called by vm_init, to initialize any structures that the pmap 318 * system needs to map virtual memory. 319 */ 320 void 321 pmap_init(phys_start, phys_end) 322 vm_offset_t phys_start, phys_end; 323 { 324 vm_offset_t addr, addr2; 325 vm_size_t npg, s; 326 int rv; 327 extern int KPTphys; 328 329 #ifdef DEBUG 330 if (pmapdebug & PDB_FOLLOW) 331 printf("pmap_init(%x, %x)\n", phys_start, phys_end); 332 #endif 333 /* 334 * Now that kernel map has been allocated, we can mark as 335 * unavailable regions which we have mapped in locore. 336 */ 337 addr = atdevbase; 338 (void) vm_map_find(kernel_map, NULL, (vm_offset_t) 0, 339 &addr, (0x100000-0xa0000), FALSE); 340 341 addr = (vm_offset_t) 0xfe000000+KPTphys/* *NBPG */; 342 vm_object_reference(kernel_object); 343 (void) vm_map_find(kernel_map, kernel_object, addr, 344 &addr, 2*NBPG, FALSE); 345 346 /* 347 * Allocate memory for random pmap data structures. Includes the 348 * pv_head_table and pmap_attributes. 349 */ 350 npg = atop(phys_end - phys_start); 351 s = (vm_size_t) (sizeof(struct pv_entry) * npg + npg); 352 s = round_page(s); 353 addr = (vm_offset_t) kmem_alloc(kernel_map, s); 354 pv_table = (pv_entry_t) addr; 355 addr += sizeof(struct pv_entry) * npg; 356 pmap_attributes = (char *) addr; 357 #ifdef DEBUG 358 if (pmapdebug & PDB_INIT) 359 printf("pmap_init: %x bytes (%x pgs): tbl %x attr %x\n", 360 s, npg, pv_table, pmap_attributes); 361 #endif 362 363 /* 364 * Now it is safe to enable pv_table recording. 365 */ 366 vm_first_phys = phys_start; 367 vm_last_phys = phys_end; 368 pmap_initialized = TRUE; 369 } 370 371 /* 372 * Used to map a range of physical addresses into kernel 373 * virtual address space. 374 * 375 * For now, VM is already on, we only need to map the 376 * specified memory. 377 */ 378 vm_offset_t 379 pmap_map(virt, start, end, prot) 380 vm_offset_t virt; 381 vm_offset_t start; 382 vm_offset_t end; 383 int prot; 384 { 385 #ifdef DEBUG 386 if (pmapdebug & PDB_FOLLOW) 387 printf("pmap_map(%x, %x, %x, %x)\n", virt, start, end, prot); 388 #endif 389 while (start < end) { 390 pmap_enter(kernel_pmap, virt, start, prot, FALSE); 391 virt += PAGE_SIZE; 392 start += PAGE_SIZE; 393 } 394 return(virt); 395 } 396 397 /* 398 * Create and return a physical map. 399 * 400 * If the size specified for the map 401 * is zero, the map is an actual physical 402 * map, and may be referenced by the 403 * hardware. 404 * 405 * If the size specified is non-zero, 406 * the map will be used in software only, and 407 * is bounded by that size. 408 * 409 * [ just allocate a ptd and mark it uninitialize -- should we track 410 * with a table which process has which ptd? -wfj ] 411 */ 412 413 pmap_t 414 pmap_create(size) 415 vm_size_t size; 416 { 417 register pmap_t pmap; 418 419 #ifdef DEBUG 420 if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) 421 printf("pmap_create(%x)\n", size); 422 #endif 423 /* 424 * Software use map does not need a pmap 425 */ 426 if (size) 427 return(NULL); 428 429 /* XXX: is it ok to wait here? */ 430 pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK); 431 #ifdef notifwewait 432 if (pmap == NULL) 433 panic("pmap_create: cannot allocate a pmap"); 434 #endif 435 bzero(pmap, sizeof(*pmap)); 436 pmap_pinit(pmap); 437 return (pmap); 438 } 439 440 /* 441 * Initialize a preallocated and zeroed pmap structure, 442 * such as one in a vmspace structure. 443 */ 444 void 445 pmap_pinit(pmap) 446 register struct pmap *pmap; 447 { 448 449 #ifdef DEBUG 450 if (pmapdebug & (PDB_FOLLOW|PDB_CREATE)) 451 pg("pmap_pinit(%x)\n", pmap); 452 #endif 453 454 /* 455 * No need to allocate page table space yet but we do need a 456 * valid page directory table. 457 */ 458 pmap->pm_pdir = (pd_entry_t *) kmem_alloc(kernel_map, NBPG); 459 460 /* wire in kernel global address entries */ 461 bcopy(PTD+KPTDI_FIRST, pmap->pm_pdir+KPTDI_FIRST, 462 (KPTDI_LAST-KPTDI_FIRST+1)*4); 463 464 /* install self-referential address mapping entry */ 465 *(int *)(pmap->pm_pdir+PTDPTDI) = 466 (int)pmap_extract(kernel_pmap, (vm_offset_t)pmap->pm_pdir) | PG_V | PG_URKW; 467 468 pmap->pm_count = 1; 469 simple_lock_init(&pmap->pm_lock); 470 } 471 472 /* 473 * Retire the given physical map from service. 474 * Should only be called if the map contains 475 * no valid mappings. 476 */ 477 void 478 pmap_destroy(pmap) 479 register pmap_t pmap; 480 { 481 int count; 482 483 #ifdef DEBUG 484 if (pmapdebug & PDB_FOLLOW) 485 printf("pmap_destroy(%x)\n", pmap); 486 #endif 487 if (pmap == NULL) 488 return; 489 490 simple_lock(&pmap->pm_lock); 491 count = --pmap->pm_count; 492 simple_unlock(&pmap->pm_lock); 493 if (count == 0) { 494 pmap_release(pmap); 495 free((caddr_t)pmap, M_VMPMAP); 496 } 497 } 498 499 /* 500 * Release any resources held by the given physical map. 501 * Called when a pmap initialized by pmap_pinit is being released. 502 * Should only be called if the map contains no valid mappings. 503 */ 504 void 505 pmap_release(pmap) 506 register struct pmap *pmap; 507 { 508 509 #ifdef DEBUG 510 if (pmapdebug & PDB_FOLLOW) 511 pg("pmap_release(%x)\n", pmap); 512 #endif 513 #ifdef notdef /* DIAGNOSTIC */ 514 /* count would be 0 from pmap_destroy... */ 515 simple_lock(&pmap->pm_lock); 516 if (pmap->pm_count != 1) 517 panic("pmap_release count"); 518 #endif 519 kmem_free(kernel_map, (vm_offset_t)pmap->pm_pdir, NBPG); 520 } 521 522 /* 523 * Add a reference to the specified pmap. 524 */ 525 void 526 pmap_reference(pmap) 527 pmap_t pmap; 528 { 529 #ifdef DEBUG 530 if (pmapdebug & PDB_FOLLOW) 531 pg("pmap_reference(%x)", pmap); 532 #endif 533 if (pmap != NULL) { 534 simple_lock(&pmap->pm_lock); 535 pmap->pm_count++; 536 simple_unlock(&pmap->pm_lock); 537 } 538 } 539 540 /* 541 * Remove the given range of addresses from the specified map. 542 * 543 * It is assumed that the start and end are properly 544 * rounded to the page size. 545 */ 546 void 547 pmap_remove(pmap, sva, eva) 548 register struct pmap *pmap; 549 vm_offset_t sva, eva; 550 { 551 register vm_offset_t pa, va; 552 register pt_entry_t *pte; 553 register pv_entry_t pv, npv; 554 register int ix; 555 pmap_t ptpmap; 556 int *pde, s, bits; 557 boolean_t firstpage = TRUE; 558 boolean_t flushcache = FALSE; 559 #ifdef DEBUG 560 pt_entry_t opte; 561 562 if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) 563 printf("pmap_remove(%x, %x, %x)", pmap, sva, eva); 564 if (eva >= USRSTACK && eva <= UPT_MAX_ADDRESS) 565 nullop(); 566 #endif 567 568 if (pmap == NULL) 569 return; 570 571 #ifdef DEBUG 572 remove_stats.calls++; 573 #endif 574 for (va = sva; va < eva; va += PAGE_SIZE) { 575 /* 576 * Weed out invalid mappings. 577 * Note: we assume that the page directory table is 578 * always allocated, and in kernel virtual. 579 */ 580 if (!pmap_pde_v(pmap_pde(pmap, va))) 581 continue; 582 583 pte = pmap_pte(pmap, va); 584 if (pte == 0) 585 continue; 586 pa = pmap_pte_pa(pte); 587 if (pa == 0) 588 continue; 589 #ifdef DEBUG 590 opte = *pte; 591 remove_stats.removes++; 592 #endif 593 /* 594 * Update statistics 595 */ 596 if (pmap_pte_w(pte)) 597 pmap->pm_stats.wired_count--; 598 pmap->pm_stats.resident_count--; 599 600 /* 601 * Invalidate the PTEs. 602 * XXX: should cluster them up and invalidate as many 603 * as possible at once. 604 */ 605 #ifdef DEBUG 606 if (pmapdebug & PDB_REMOVE) 607 printf("remove: inv %x ptes at %x(%x) ", 608 i386pagesperpage, pte, *(int *)pte); 609 #endif 610 bits = ix = 0; 611 do { 612 bits |= *(int *)pte & (PG_U|PG_M); 613 *(int *)pte++ = 0; 614 /*TBIS(va + ix * I386_PAGE_SIZE);*/ 615 } while (++ix != i386pagesperpage); 616 if (pmap == &curproc->p_vmspace->vm_pmap) 617 pmap_activate(pmap, (struct pcb *)curproc->p_addr); 618 /* are we current address space or kernel? */ 619 /*if (pmap->pm_pdir[PTDPTDI].pd_pfnum == PTDpde.pd_pfnum 620 || pmap == kernel_pmap) 621 load_cr3(curpcb->pcb_ptd);*/ 622 tlbflush(); 623 624 #ifdef needednotdone 625 reduce wiring count on page table pages as references drop 626 #endif 627 628 /* 629 * Remove from the PV table (raise IPL since we 630 * may be called at interrupt time). 631 */ 632 if (pa < vm_first_phys || pa >= vm_last_phys) 633 continue; 634 pv = pa_to_pvh(pa); 635 s = splimp(); 636 /* 637 * If it is the first entry on the list, it is actually 638 * in the header and we must copy the following entry up 639 * to the header. Otherwise we must search the list for 640 * the entry. In either case we free the now unused entry. 641 */ 642 if (pmap == pv->pv_pmap && va == pv->pv_va) { 643 npv = pv->pv_next; 644 if (npv) { 645 *pv = *npv; 646 free((caddr_t)npv, M_VMPVENT); 647 } else 648 pv->pv_pmap = NULL; 649 #ifdef DEBUG 650 remove_stats.pvfirst++; 651 #endif 652 } else { 653 for (npv = pv->pv_next; npv; npv = npv->pv_next) { 654 #ifdef DEBUG 655 remove_stats.pvsearch++; 656 #endif 657 if (pmap == npv->pv_pmap && va == npv->pv_va) 658 break; 659 pv = npv; 660 } 661 #ifdef DEBUG 662 if (npv == NULL) 663 panic("pmap_remove: PA not in pv_tab"); 664 #endif 665 pv->pv_next = npv->pv_next; 666 free((caddr_t)npv, M_VMPVENT); 667 pv = pa_to_pvh(pa); 668 } 669 670 #ifdef notdef 671 [tally number of pagetable pages, if sharing of ptpages adjust here] 672 #endif 673 /* 674 * Update saved attributes for managed page 675 */ 676 pmap_attributes[pa_index(pa)] |= bits; 677 splx(s); 678 } 679 #ifdef notdef 680 [cache and tlb flushing, if needed] 681 #endif 682 } 683 684 /* 685 * Routine: pmap_remove_all 686 * Function: 687 * Removes this physical page from 688 * all physical maps in which it resides. 689 * Reflects back modify bits to the pager. 690 */ 691 void 692 pmap_remove_all(pa) 693 vm_offset_t pa; 694 { 695 register pv_entry_t pv; 696 int s; 697 698 #ifdef DEBUG 699 if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT)) 700 printf("pmap_remove_all(%x)", pa); 701 /*pmap_pvdump(pa);*/ 702 #endif 703 /* 704 * Not one of ours 705 */ 706 if (pa < vm_first_phys || pa >= vm_last_phys) 707 return; 708 709 pv = pa_to_pvh(pa); 710 s = splimp(); 711 /* 712 * Do it the easy way for now 713 */ 714 while (pv->pv_pmap != NULL) { 715 #ifdef DEBUG 716 if (!pmap_pde_v(pmap_pde(pv->pv_pmap, pv->pv_va)) || 717 pmap_pte_pa(pmap_pte(pv->pv_pmap, pv->pv_va)) != pa) 718 panic("pmap_remove_all: bad mapping"); 719 #endif 720 pmap_remove(pv->pv_pmap, pv->pv_va, pv->pv_va + PAGE_SIZE); 721 } 722 splx(s); 723 } 724 725 /* 726 * Routine: pmap_copy_on_write 727 * Function: 728 * Remove write privileges from all 729 * physical maps for this physical page. 730 */ 731 void 732 pmap_copy_on_write(pa) 733 vm_offset_t pa; 734 { 735 #ifdef DEBUG 736 if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) 737 printf("pmap_copy_on_write(%x)", pa); 738 #endif 739 pmap_changebit(pa, PG_RO, TRUE); 740 } 741 742 /* 743 * Set the physical protection on the 744 * specified range of this map as requested. 745 */ 746 void 747 pmap_protect(pmap, sva, eva, prot) 748 register pmap_t pmap; 749 vm_offset_t sva, eva; 750 vm_prot_t prot; 751 { 752 register pt_entry_t *pte; 753 register vm_offset_t va; 754 register int ix; 755 int i386prot; 756 boolean_t firstpage = TRUE; 757 758 #ifdef DEBUG 759 if (pmapdebug & (PDB_FOLLOW|PDB_PROTECT)) 760 printf("pmap_protect(%x, %x, %x, %x)", pmap, sva, eva, prot); 761 #endif 762 if (pmap == NULL) 763 return; 764 765 if ((prot & VM_PROT_READ) == VM_PROT_NONE) { 766 pmap_remove(pmap, sva, eva); 767 return; 768 } 769 if (prot & VM_PROT_WRITE) 770 return; 771 772 for (va = sva; va < eva; va += PAGE_SIZE) { 773 /* 774 * Page table page is not allocated. 775 * Skip it, we don't want to force allocation 776 * of unnecessary PTE pages just to set the protection. 777 */ 778 if (!pmap_pde_v(pmap_pde(pmap, va))) { 779 /* XXX: avoid address wrap around */ 780 if (va >= i386_trunc_pdr((vm_offset_t)-1)) 781 break; 782 va = i386_round_pdr(va + PAGE_SIZE) - PAGE_SIZE; 783 continue; 784 } else pte = pmap_pte(pmap, va); 785 786 /* 787 * Page not valid. Again, skip it. 788 * Should we do this? Or set protection anyway? 789 */ 790 if (!pmap_pte_v(pte)) 791 continue; 792 793 ix = 0; 794 i386prot = pte_prot(pmap, prot); 795 if(va < UPT_MAX_ADDRESS) 796 i386prot |= 2 /*PG_u*/; 797 do { 798 /* clear VAC here if PG_RO? */ 799 pmap_pte_set_prot(pte++, i386prot); 800 /*TBIS(va + ix * I386_PAGE_SIZE);*/ 801 } while (++ix != i386pagesperpage); 802 } 803 out: 804 if (pmap == &curproc->p_vmspace->vm_pmap) 805 pmap_activate(pmap, (struct pcb *)curproc->p_addr); 806 } 807 808 /* 809 * Insert the given physical page (p) at 810 * the specified virtual address (v) in the 811 * target physical map with the protection requested. 812 * 813 * If specified, the page will be wired down, meaning 814 * that the related pte can not be reclaimed. 815 * 816 * NB: This is the only routine which MAY NOT lazy-evaluate 817 * or lose information. That is, this routine must actually 818 * insert this page into the given map NOW. 819 */ 820 void 821 pmap_enter(pmap, va, pa, prot, wired) 822 register pmap_t pmap; 823 vm_offset_t va; 824 register vm_offset_t pa; 825 vm_prot_t prot; 826 boolean_t wired; 827 { 828 register pt_entry_t *pte; 829 register int npte, ix; 830 vm_offset_t opa; 831 boolean_t cacheable = TRUE; 832 boolean_t checkpv = TRUE; 833 834 #ifdef DEBUG 835 if (pmapdebug & (PDB_FOLLOW|PDB_ENTER)) 836 printf("pmap_enter(%x, %x, %x, %x, %x)", 837 pmap, va, pa, prot, wired); 838 if(!pmap_isvalidphys(pa)) panic("invalid phys"); 839 #endif 840 if (pmap == NULL) 841 return; 842 843 if(va > VM_MAX_KERNEL_ADDRESS)panic("pmap_enter: toobig"); 844 /* also, should not muck with PTD va! */ 845 846 #ifdef DEBUG 847 if (pmap == kernel_pmap) 848 enter_stats.kernel++; 849 else 850 enter_stats.user++; 851 #endif 852 853 /* 854 * Page Directory table entry not valid, we need a new PT page 855 */ 856 if (!pmap_pde_v(pmap_pde(pmap, va))) { 857 pg("ptdi %x", pmap->pm_pdir[PTDPTDI]); 858 } 859 860 pte = pmap_pte(pmap, va); 861 opa = pmap_pte_pa(pte); 862 #ifdef DEBUG 863 if (pmapdebug & PDB_ENTER) 864 printf("enter: pte %x, *pte %x ", pte, *(int *)pte); 865 #endif 866 867 /* 868 * Mapping has not changed, must be protection or wiring change. 869 */ 870 if (opa == pa) { 871 #ifdef DEBUG 872 enter_stats.pwchange++; 873 #endif 874 /* 875 * Wiring change, just update stats. 876 * We don't worry about wiring PT pages as they remain 877 * resident as long as there are valid mappings in them. 878 * Hence, if a user page is wired, the PT page will be also. 879 */ 880 if (wired && !pmap_pte_w(pte) || !wired && pmap_pte_w(pte)) { 881 #ifdef DEBUG 882 if (pmapdebug & PDB_ENTER) 883 pg("enter: wiring change -> %x ", wired); 884 #endif 885 if (wired) 886 pmap->pm_stats.wired_count++; 887 else 888 pmap->pm_stats.wired_count--; 889 #ifdef DEBUG 890 enter_stats.wchange++; 891 #endif 892 } 893 goto validate; 894 } 895 896 /* 897 * Mapping has changed, invalidate old range and fall through to 898 * handle validating new mapping. 899 */ 900 if (opa) { 901 #ifdef DEBUG 902 if (pmapdebug & PDB_ENTER) 903 printf("enter: removing old mapping %x pa %x ", va, opa); 904 #endif 905 pmap_remove(pmap, va, va + PAGE_SIZE); 906 #ifdef DEBUG 907 enter_stats.mchange++; 908 #endif 909 } 910 911 /* 912 * Enter on the PV list if part of our managed memory 913 * Note that we raise IPL while manipulating pv_table 914 * since pmap_enter can be called at interrupt time. 915 */ 916 if (pa >= vm_first_phys && pa < vm_last_phys) { 917 register pv_entry_t pv, npv; 918 int s; 919 920 #ifdef DEBUG 921 enter_stats.managed++; 922 #endif 923 pv = pa_to_pvh(pa); 924 s = splimp(); 925 #ifdef DEBUG 926 if (pmapdebug & PDB_ENTER) 927 printf("enter: pv at %x: %x/%x/%x ", 928 pv, pv->pv_va, pv->pv_pmap, pv->pv_next); 929 #endif 930 /* 931 * No entries yet, use header as the first entry 932 */ 933 if (pv->pv_pmap == NULL) { 934 #ifdef DEBUG 935 enter_stats.firstpv++; 936 #endif 937 pv->pv_va = va; 938 pv->pv_pmap = pmap; 939 pv->pv_next = NULL; 940 pv->pv_flags = 0; 941 } 942 /* 943 * There is at least one other VA mapping this page. 944 * Place this entry after the header. 945 */ 946 else { 947 /*printf("second time: ");*/ 948 #ifdef DEBUG 949 for (npv = pv; npv; npv = npv->pv_next) 950 if (pmap == npv->pv_pmap && va == npv->pv_va) 951 panic("pmap_enter: already in pv_tab"); 952 #endif 953 npv = (pv_entry_t) 954 malloc(sizeof *npv, M_VMPVENT, M_NOWAIT); 955 npv->pv_va = va; 956 npv->pv_pmap = pmap; 957 npv->pv_next = pv->pv_next; 958 pv->pv_next = npv; 959 #ifdef DEBUG 960 if (!npv->pv_next) 961 enter_stats.secondpv++; 962 #endif 963 splx(s); 964 } 965 } 966 /* 967 * Assumption: if it is not part of our managed memory 968 * then it must be device memory which may be volitile. 969 */ 970 if (pmap_initialized) { 971 checkpv = cacheable = FALSE; 972 #ifdef DEBUG 973 enter_stats.unmanaged++; 974 #endif 975 } 976 977 /* 978 * Increment counters 979 */ 980 pmap->pm_stats.resident_count++; 981 if (wired) 982 pmap->pm_stats.wired_count++; 983 984 validate: 985 /* 986 * Now validate mapping with desired protection/wiring. 987 * Assume uniform modified and referenced status for all 988 * I386 pages in a MACH page. 989 */ 990 npte = (pa & PG_FRAME) | pte_prot(pmap, prot) | PG_V; 991 npte |= (*(int *)pte & (PG_M|PG_U)); 992 if (wired) 993 npte |= PG_W; 994 if(va < UPT_MIN_ADDRESS) 995 npte |= PG_u; 996 else if(va < UPT_MAX_ADDRESS) 997 npte |= PG_u | PG_RW; 998 #ifdef DEBUG 999 if (pmapdebug & PDB_ENTER) 1000 printf("enter: new pte value %x ", npte); 1001 #endif 1002 ix = 0; 1003 do { 1004 *(int *)pte++ = npte; 1005 /*TBIS(va);*/ 1006 npte += I386_PAGE_SIZE; 1007 va += I386_PAGE_SIZE; 1008 } while (++ix != i386pagesperpage); 1009 pte--; 1010 #ifdef DEBUGx 1011 cache, tlb flushes 1012 #endif 1013 /*pads(pmap);*/ 1014 /*load_cr3(((struct pcb *)curproc->p_addr)->pcb_ptd);*/ 1015 tlbflush(); 1016 } 1017 1018 /* 1019 * pmap_page_protect: 1020 * 1021 * Lower the permission for all mappings to a given page. 1022 */ 1023 void 1024 pmap_page_protect(phys, prot) 1025 vm_offset_t phys; 1026 vm_prot_t prot; 1027 { 1028 switch (prot) { 1029 case VM_PROT_READ: 1030 case VM_PROT_READ|VM_PROT_EXECUTE: 1031 pmap_copy_on_write(phys); 1032 break; 1033 case VM_PROT_ALL: 1034 break; 1035 default: 1036 pmap_remove_all(phys); 1037 break; 1038 } 1039 } 1040 1041 /* 1042 * Routine: pmap_change_wiring 1043 * Function: Change the wiring attribute for a map/virtual-address 1044 * pair. 1045 * In/out conditions: 1046 * The mapping must already exist in the pmap. 1047 */ 1048 void 1049 pmap_change_wiring(pmap, va, wired) 1050 register pmap_t pmap; 1051 vm_offset_t va; 1052 boolean_t wired; 1053 { 1054 register pt_entry_t *pte; 1055 register int ix; 1056 1057 #ifdef DEBUG 1058 if (pmapdebug & PDB_FOLLOW) 1059 printf("pmap_change_wiring(%x, %x, %x)", pmap, va, wired); 1060 #endif 1061 if (pmap == NULL) 1062 return; 1063 1064 pte = pmap_pte(pmap, va); 1065 #ifdef DEBUG 1066 /* 1067 * Page table page is not allocated. 1068 * Should this ever happen? Ignore it for now, 1069 * we don't want to force allocation of unnecessary PTE pages. 1070 */ 1071 if (!pmap_pde_v(pmap_pde(pmap, va))) { 1072 if (pmapdebug & PDB_PARANOIA) 1073 pg("pmap_change_wiring: invalid PDE for %x ", va); 1074 return; 1075 } 1076 /* 1077 * Page not valid. Should this ever happen? 1078 * Just continue and change wiring anyway. 1079 */ 1080 if (!pmap_pte_v(pte)) { 1081 if (pmapdebug & PDB_PARANOIA) 1082 pg("pmap_change_wiring: invalid PTE for %x ", va); 1083 } 1084 #endif 1085 if (wired && !pmap_pte_w(pte) || !wired && pmap_pte_w(pte)) { 1086 if (wired) 1087 pmap->pm_stats.wired_count++; 1088 else 1089 pmap->pm_stats.wired_count--; 1090 } 1091 /* 1092 * Wiring is not a hardware characteristic so there is no need 1093 * to invalidate TLB. 1094 */ 1095 ix = 0; 1096 do { 1097 pmap_pte_set_w(pte++, wired); 1098 } while (++ix != i386pagesperpage); 1099 } 1100 1101 /* 1102 * Routine: pmap_pte 1103 * Function: 1104 * Extract the page table entry associated 1105 * with the given map/virtual_address pair. 1106 * [ what about induced faults -wfj] 1107 */ 1108 1109 struct pte *pmap_pte(pmap, va) 1110 register pmap_t pmap; 1111 vm_offset_t va; 1112 { 1113 1114 #ifdef DEBUGx 1115 if (pmapdebug & PDB_FOLLOW) 1116 printf("pmap_pte(%x, %x) ->\n", pmap, va); 1117 #endif 1118 if (pmap && pmap_pde_v(pmap_pde(pmap, va))) { 1119 1120 /* are we current address space or kernel? */ 1121 if (pmap->pm_pdir[PTDPTDI].pd_pfnum == PTDpde.pd_pfnum 1122 || pmap == kernel_pmap) 1123 return ((struct pte *) vtopte(va)); 1124 1125 /* otherwise, we are alternate address space */ 1126 else { 1127 if (pmap->pm_pdir[PTDPTDI].pd_pfnum 1128 != APTDpde.pd_pfnum) { 1129 APTDpde = pmap->pm_pdir[PTDPTDI]; 1130 tlbflush(); 1131 } 1132 return((struct pte *) avtopte(va)); 1133 } 1134 } 1135 return(0); 1136 } 1137 1138 /* 1139 * Routine: pmap_extract 1140 * Function: 1141 * Extract the physical page address associated 1142 * with the given map/virtual_address pair. 1143 */ 1144 1145 vm_offset_t 1146 pmap_extract(pmap, va) 1147 register pmap_t pmap; 1148 vm_offset_t va; 1149 { 1150 register vm_offset_t pa; 1151 1152 #ifdef DEBUGx 1153 if (pmapdebug & PDB_FOLLOW) 1154 pg("pmap_extract(%x, %x) -> ", pmap, va); 1155 #endif 1156 pa = 0; 1157 if (pmap && pmap_pde_v(pmap_pde(pmap, va))) { 1158 pa = *(int *) pmap_pte(pmap, va); 1159 } 1160 if (pa) 1161 pa = (pa & PG_FRAME) | (va & ~PG_FRAME); 1162 #ifdef DEBUGx 1163 if (pmapdebug & PDB_FOLLOW) 1164 printf("%x\n", pa); 1165 #endif 1166 return(pa); 1167 } 1168 1169 /* 1170 * Copy the range specified by src_addr/len 1171 * from the source map to the range dst_addr/len 1172 * in the destination map. 1173 * 1174 * This routine is only advisory and need not do anything. 1175 */ 1176 void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) 1177 pmap_t dst_pmap; 1178 pmap_t src_pmap; 1179 vm_offset_t dst_addr; 1180 vm_size_t len; 1181 vm_offset_t src_addr; 1182 { 1183 #ifdef DEBUG 1184 if (pmapdebug & PDB_FOLLOW) 1185 printf("pmap_copy(%x, %x, %x, %x, %x)", 1186 dst_pmap, src_pmap, dst_addr, len, src_addr); 1187 #endif 1188 } 1189 1190 /* 1191 * Require that all active physical maps contain no 1192 * incorrect entries NOW. [This update includes 1193 * forcing updates of any address map caching.] 1194 * 1195 * Generally used to insure that a thread about 1196 * to run will see a semantically correct world. 1197 */ 1198 void pmap_update() 1199 { 1200 #ifdef DEBUG 1201 if (pmapdebug & PDB_FOLLOW) 1202 printf("pmap_update()"); 1203 #endif 1204 tlbflush(); 1205 } 1206 1207 /* 1208 * Routine: pmap_collect 1209 * Function: 1210 * Garbage collects the physical map system for 1211 * pages which are no longer used. 1212 * Success need not be guaranteed -- that is, there 1213 * may well be pages which are not referenced, but 1214 * others may be collected. 1215 * Usage: 1216 * Called by the pageout daemon when pages are scarce. 1217 * [ needs to be written -wfj ] 1218 */ 1219 void 1220 pmap_collect(pmap) 1221 pmap_t pmap; 1222 { 1223 register vm_offset_t pa; 1224 register pv_entry_t pv; 1225 register int *pte; 1226 vm_offset_t kpa; 1227 int s; 1228 1229 #ifdef DEBUG 1230 int *pde; 1231 int opmapdebug; 1232 printf("pmap_collect(%x) ", pmap); 1233 #endif 1234 if (pmap != kernel_pmap) 1235 return; 1236 1237 } 1238 1239 /* [ macro again?, should I force kstack into user map here? -wfj ] */ 1240 void 1241 pmap_activate(pmap, pcbp) 1242 register pmap_t pmap; 1243 struct pcb *pcbp; 1244 { 1245 int x; 1246 #ifdef DEBUG 1247 if (pmapdebug & (PDB_FOLLOW|PDB_PDRTAB)) 1248 pg("pmap_activate(%x, %x) ", pmap, pcbp); 1249 #endif 1250 PMAP_ACTIVATE(pmap, pcbp); 1251 /*printf("pde "); 1252 for(x=0x3f6; x < 0x3fA; x++) 1253 printf("%x ", pmap->pm_pdir[x]);*/ 1254 /*pads(pmap);*/ 1255 /*pg(" pcb_cr3 %x", pcbp->pcb_cr3);*/ 1256 } 1257 1258 /* 1259 * pmap_zero_page zeros the specified (machine independent) 1260 * page by mapping the page into virtual memory and using 1261 * bzero to clear its contents, one machine dependent page 1262 * at a time. 1263 */ 1264 void 1265 pmap_zero_page(phys) 1266 register vm_offset_t phys; 1267 { 1268 register int ix; 1269 1270 #ifdef DEBUG 1271 if (pmapdebug & PDB_FOLLOW) 1272 printf("pmap_zero_page(%x)", phys); 1273 #endif 1274 phys >>= PG_SHIFT; 1275 ix = 0; 1276 do { 1277 clearseg(phys++); 1278 } while (++ix != i386pagesperpage); 1279 } 1280 1281 /* 1282 * pmap_copy_page copies the specified (machine independent) 1283 * page by mapping the page into virtual memory and using 1284 * bcopy to copy the page, one machine dependent page at a 1285 * time. 1286 */ 1287 void 1288 pmap_copy_page(src, dst) 1289 register vm_offset_t src, dst; 1290 { 1291 register int ix; 1292 1293 #ifdef DEBUG 1294 if (pmapdebug & PDB_FOLLOW) 1295 printf("pmap_copy_page(%x, %x)", src, dst); 1296 #endif 1297 src >>= PG_SHIFT; 1298 dst >>= PG_SHIFT; 1299 ix = 0; 1300 do { 1301 physcopyseg(src++, dst++); 1302 } while (++ix != i386pagesperpage); 1303 } 1304 1305 1306 /* 1307 * Routine: pmap_pageable 1308 * Function: 1309 * Make the specified pages (by pmap, offset) 1310 * pageable (or not) as requested. 1311 * 1312 * A page which is not pageable may not take 1313 * a fault; therefore, its page table entry 1314 * must remain valid for the duration. 1315 * 1316 * This routine is merely advisory; pmap_enter 1317 * will specify that these pages are to be wired 1318 * down (or not) as appropriate. 1319 */ 1320 void 1321 pmap_pageable(pmap, sva, eva, pageable) 1322 pmap_t pmap; 1323 vm_offset_t sva, eva; 1324 boolean_t pageable; 1325 { 1326 #ifdef DEBUG 1327 if (pmapdebug & PDB_FOLLOW) 1328 printf("pmap_pageable(%x, %x, %x, %x)", 1329 pmap, sva, eva, pageable); 1330 #endif 1331 /* 1332 * If we are making a PT page pageable then all valid 1333 * mappings must be gone from that page. Hence it should 1334 * be all zeros and there is no need to clean it. 1335 * Assumptions: 1336 * - we are called with only one page at a time 1337 * - PT pages have only one pv_table entry 1338 */ 1339 if (pmap == kernel_pmap && pageable && sva + PAGE_SIZE == eva) { 1340 register pv_entry_t pv; 1341 register vm_offset_t pa; 1342 1343 #ifdef DEBUG 1344 if ((pmapdebug & (PDB_FOLLOW|PDB_PTPAGE)) == PDB_PTPAGE) 1345 printf("pmap_pageable(%x, %x, %x, %x)", 1346 pmap, sva, eva, pageable); 1347 #endif 1348 /*if (!pmap_pde_v(pmap_pde(pmap, sva))) 1349 return;*/ 1350 if(pmap_pte(pmap, sva) == 0) 1351 return; 1352 pa = pmap_pte_pa(pmap_pte(pmap, sva)); 1353 if (pa < vm_first_phys || pa >= vm_last_phys) 1354 return; 1355 pv = pa_to_pvh(pa); 1356 /*if (!ispt(pv->pv_va)) 1357 return;*/ 1358 #ifdef DEBUG 1359 if (pv->pv_va != sva || pv->pv_next) { 1360 pg("pmap_pageable: bad PT page va %x next %x\n", 1361 pv->pv_va, pv->pv_next); 1362 return; 1363 } 1364 #endif 1365 /* 1366 * Mark it unmodified to avoid pageout 1367 */ 1368 pmap_clear_modify(pa); 1369 #ifdef needsomethinglikethis 1370 if (pmapdebug & PDB_PTPAGE) 1371 pg("pmap_pageable: PT page %x(%x) unmodified\n", 1372 sva, *(int *)pmap_pte(pmap, sva)); 1373 if (pmapdebug & PDB_WIRING) 1374 pmap_check_wiring("pageable", sva); 1375 #endif 1376 } 1377 } 1378 1379 /* 1380 * Clear the modify bits on the specified physical page. 1381 */ 1382 1383 void 1384 pmap_clear_modify(pa) 1385 vm_offset_t pa; 1386 { 1387 #ifdef DEBUG 1388 if (pmapdebug & PDB_FOLLOW) 1389 printf("pmap_clear_modify(%x)", pa); 1390 #endif 1391 pmap_changebit(pa, PG_M, FALSE); 1392 } 1393 1394 /* 1395 * pmap_clear_reference: 1396 * 1397 * Clear the reference bit on the specified physical page. 1398 */ 1399 1400 void pmap_clear_reference(pa) 1401 vm_offset_t pa; 1402 { 1403 #ifdef DEBUG 1404 if (pmapdebug & PDB_FOLLOW) 1405 printf("pmap_clear_reference(%x)", pa); 1406 #endif 1407 pmap_changebit(pa, PG_U, FALSE); 1408 } 1409 1410 /* 1411 * pmap_is_referenced: 1412 * 1413 * Return whether or not the specified physical page is referenced 1414 * by any physical maps. 1415 */ 1416 1417 boolean_t 1418 pmap_is_referenced(pa) 1419 vm_offset_t pa; 1420 { 1421 #ifdef DEBUG 1422 if (pmapdebug & PDB_FOLLOW) { 1423 boolean_t rv = pmap_testbit(pa, PG_U); 1424 printf("pmap_is_referenced(%x) -> %c", pa, "FT"[rv]); 1425 return(rv); 1426 } 1427 #endif 1428 return(pmap_testbit(pa, PG_U)); 1429 } 1430 1431 /* 1432 * pmap_is_modified: 1433 * 1434 * Return whether or not the specified physical page is modified 1435 * by any physical maps. 1436 */ 1437 1438 boolean_t 1439 pmap_is_modified(pa) 1440 vm_offset_t pa; 1441 { 1442 #ifdef DEBUG 1443 if (pmapdebug & PDB_FOLLOW) { 1444 boolean_t rv = pmap_testbit(pa, PG_M); 1445 printf("pmap_is_modified(%x) -> %c", pa, "FT"[rv]); 1446 return(rv); 1447 } 1448 #endif 1449 return(pmap_testbit(pa, PG_M)); 1450 } 1451 1452 vm_offset_t 1453 pmap_phys_address(ppn) 1454 int ppn; 1455 { 1456 return(i386_ptob(ppn)); 1457 } 1458 1459 /* 1460 * Miscellaneous support routines follow 1461 */ 1462 1463 i386_protection_init() 1464 { 1465 register int *kp, prot; 1466 1467 kp = protection_codes; 1468 for (prot = 0; prot < 8; prot++) { 1469 switch (prot) { 1470 case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE: 1471 *kp++ = 0; 1472 break; 1473 case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE: 1474 case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE: 1475 case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE: 1476 *kp++ = PG_RO; 1477 break; 1478 case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE: 1479 case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE: 1480 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE: 1481 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 1482 *kp++ = PG_RW; 1483 break; 1484 } 1485 } 1486 } 1487 1488 static 1489 boolean_t 1490 pmap_testbit(pa, bit) 1491 register vm_offset_t pa; 1492 int bit; 1493 { 1494 register pv_entry_t pv; 1495 register int *pte, ix; 1496 int s; 1497 1498 if (pa < vm_first_phys || pa >= vm_last_phys) 1499 return(FALSE); 1500 1501 pv = pa_to_pvh(pa); 1502 s = splimp(); 1503 /* 1504 * Check saved info first 1505 */ 1506 if (pmap_attributes[pa_index(pa)] & bit) { 1507 splx(s); 1508 return(TRUE); 1509 } 1510 /* 1511 * Not found, check current mappings returning 1512 * immediately if found. 1513 */ 1514 if (pv->pv_pmap != NULL) { 1515 for (; pv; pv = pv->pv_next) { 1516 pte = (int *) pmap_pte(pv->pv_pmap, pv->pv_va); 1517 ix = 0; 1518 do { 1519 if (*pte++ & bit) { 1520 splx(s); 1521 return(TRUE); 1522 } 1523 } while (++ix != i386pagesperpage); 1524 } 1525 } 1526 splx(s); 1527 return(FALSE); 1528 } 1529 1530 pmap_changebit(pa, bit, setem) 1531 register vm_offset_t pa; 1532 int bit; 1533 boolean_t setem; 1534 { 1535 register pv_entry_t pv; 1536 register int *pte, npte, ix; 1537 vm_offset_t va; 1538 int s; 1539 boolean_t firstpage = TRUE; 1540 1541 #ifdef DEBUG 1542 if (pmapdebug & PDB_BITS) 1543 printf("pmap_changebit(%x, %x, %s)", 1544 pa, bit, setem ? "set" : "clear"); 1545 #endif 1546 if (pa < vm_first_phys || pa >= vm_last_phys) 1547 return; 1548 1549 pv = pa_to_pvh(pa); 1550 s = splimp(); 1551 /* 1552 * Clear saved attributes (modify, reference) 1553 */ 1554 if (!setem) 1555 pmap_attributes[pa_index(pa)] &= ~bit; 1556 /* 1557 * Loop over all current mappings setting/clearing as appropos 1558 * If setting RO do we need to clear the VAC? 1559 */ 1560 if (pv->pv_pmap != NULL) { 1561 #ifdef DEBUG 1562 int toflush = 0; 1563 #endif 1564 for (; pv; pv = pv->pv_next) { 1565 #ifdef DEBUG 1566 toflush |= (pv->pv_pmap == kernel_pmap) ? 2 : 1; 1567 #endif 1568 va = pv->pv_va; 1569 1570 /* 1571 * XXX don't write protect pager mappings 1572 */ 1573 if (bit == PG_RO) { 1574 extern vm_offset_t pager_sva, pager_eva; 1575 1576 if (va >= pager_sva && va < pager_eva) 1577 continue; 1578 } 1579 1580 pte = (int *) pmap_pte(pv->pv_pmap, va); 1581 ix = 0; 1582 do { 1583 if (setem) 1584 npte = *pte | bit; 1585 else 1586 npte = *pte & ~bit; 1587 if (*pte != npte) { 1588 *pte = npte; 1589 /*TBIS(va);*/ 1590 } 1591 va += I386_PAGE_SIZE; 1592 pte++; 1593 } while (++ix != i386pagesperpage); 1594 1595 if (pv->pv_pmap == &curproc->p_vmspace->vm_pmap) 1596 pmap_activate(pv->pv_pmap, (struct pcb *)curproc->p_addr); 1597 } 1598 #ifdef somethinglikethis 1599 if (setem && bit == PG_RO && (pmapvacflush & PVF_PROTECT)) { 1600 if ((pmapvacflush & PVF_TOTAL) || toflush == 3) 1601 DCIA(); 1602 else if (toflush == 2) 1603 DCIS(); 1604 else 1605 DCIU(); 1606 } 1607 #endif 1608 } 1609 splx(s); 1610 } 1611 1612 #ifdef DEBUG 1613 pmap_pvdump(pa) 1614 vm_offset_t pa; 1615 { 1616 register pv_entry_t pv; 1617 1618 printf("pa %x", pa); 1619 for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next) { 1620 printf(" -> pmap %x, va %x, flags %x", 1621 pv->pv_pmap, pv->pv_va, pv->pv_flags); 1622 pads(pv->pv_pmap); 1623 } 1624 printf(" "); 1625 } 1626 1627 #ifdef notyet 1628 pmap_check_wiring(str, va) 1629 char *str; 1630 vm_offset_t va; 1631 { 1632 vm_map_entry_t entry; 1633 register int count, *pte; 1634 1635 va = trunc_page(va); 1636 if (!pmap_pde_v(pmap_pde(kernel_pmap, va)) || 1637 !pmap_pte_v(pmap_pte(kernel_pmap, va))) 1638 return; 1639 1640 if (!vm_map_lookup_entry(pt_map, va, &entry)) { 1641 pg("wired_check: entry for %x not found\n", va); 1642 return; 1643 } 1644 count = 0; 1645 for (pte = (int *)va; pte < (int *)(va+PAGE_SIZE); pte++) 1646 if (*pte) 1647 count++; 1648 if (entry->wired_count != count) 1649 pg("*%s*: %x: w%d/a%d\n", 1650 str, va, entry->wired_count, count); 1651 } 1652 #endif 1653 1654 /* print address space of pmap*/ 1655 pads(pm) pmap_t pm; { 1656 unsigned va, i, j; 1657 struct pte *ptep; 1658 1659 if(pm == kernel_pmap) return; 1660 for (i = 0; i < 1024; i++) 1661 if(pm->pm_pdir[i].pd_v) 1662 for (j = 0; j < 1024 ; j++) { 1663 va = (i<<22)+(j<<12); 1664 if (pm == kernel_pmap && va < 0xfe000000) 1665 continue; 1666 if (pm != kernel_pmap && va > UPT_MAX_ADDRESS) 1667 continue; 1668 ptep = pmap_pte(pm, va); 1669 if(pmap_pte_v(ptep)) 1670 printf("%x:%x ", va, *(int *)ptep); 1671 } ; 1672 1673 } 1674 #endif 1675