pmap.c revision 14867
1/* 2 * Copyright (c) 1991 Regents of the University of California. 3 * All rights reserved. 4 * Copyright (c) 1994 John S. Dyson 5 * All rights reserved. 6 * Copyright (c) 1994 David Greenman 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * the Systems Programming Group of the University of Utah Computer 11 * Science Department and William Jolitz of UUNET Technologies Inc. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: @(#)pmap.c 7.7 (Berkeley) 5/12/91 42 * $Id: pmap.c,v 1.81 1996/03/13 00:39:45 dyson Exp $ 43 */ 44 45/* 46 * Derived from hp300 version by Mike Hibler, this version by William 47 * Jolitz uses a recursive map [a pde points to the page directory] to 48 * map the page tables using the pagetables themselves. This is done to 49 * reduce the impact on kernel virtual memory for lots of sparse address 50 * space, and to reduce the cost of memory to each process. 51 * 52 * Derived from: hp300/@(#)pmap.c 7.1 (Berkeley) 12/5/90 53 */ 54 55/* 56 * Manages physical address maps. 57 * 58 * In addition to hardware address maps, this 59 * module is called upon to provide software-use-only 60 * maps which may or may not be stored in the same 61 * form as hardware maps. These pseudo-maps are 62 * used to store intermediate results from copy 63 * operations to and from address spaces. 64 * 65 * Since the information managed by this module is 66 * also stored by the logical address mapping module, 67 * this module may throw away valid virtual-to-physical 68 * mappings at almost any time. However, invalidations 69 * of virtual-to-physical mappings must be done as 70 * requested. 71 * 72 * In order to cope with hardware architectures which 73 * make virtual-to-physical map invalidates expensive, 74 * this module may delay invalidate or reduced protection 75 * operations until such time as they are actually 76 * necessary. This module is given full information as 77 * to which processors are currently using which maps, 78 * and to when physical maps must be made correct. 79 */ 80 81#include <sys/param.h> 82#include <sys/systm.h> 83#include <sys/proc.h> 84#include <sys/malloc.h> 85#include <sys/msgbuf.h> 86#include <sys/queue.h> 87#include <sys/vmmeter.h> 88 89#include <vm/vm.h> 90#include <vm/vm_param.h> 91#include <vm/vm_prot.h> 92#include <vm/lock.h> 93#include <vm/vm_kern.h> 94#include <vm/vm_page.h> 95#include <vm/vm_map.h> 96#include <vm/vm_object.h> 97#include <vm/vm_extern.h> 98 99#include <machine/pcb.h> 100#include <machine/cputypes.h> 101#include <machine/md_var.h> 102 103#include <i386/isa/isa.h> 104 105#define PMAP_KEEP_PDIRS 106 107#if defined(DIAGNOSTIC) 108#define PMAP_DIAGNOSTIC 109#endif 110 111static void init_pv_entries __P((int)); 112 113/* 114 * Get PDEs and PTEs for user/kernel address space 115 */ 116#define pmap_pde(m, v) (&((m)->pm_pdir[((vm_offset_t)(v) >> PD_SHIFT)&1023])) 117#define pdir_pde(m, v) (m[((vm_offset_t)(v) >> PD_SHIFT)&1023]) 118 119#define pmap_pte_pa(pte) (*(int *)(pte) & PG_FRAME) 120 121#define pmap_pde_v(pte) ((*(int *)pte & PG_V) != 0) 122#define pmap_pte_w(pte) ((*(int *)pte & PG_W) != 0) 123#define pmap_pte_m(pte) ((*(int *)pte & PG_M) != 0) 124#define pmap_pte_u(pte) ((*(int *)pte & PG_U) != 0) 125#define pmap_pte_v(pte) ((*(int *)pte & PG_V) != 0) 126 127#define pmap_pte_set_w(pte, v) ((v)?(*(int *)pte |= PG_W):(*(int *)pte &= ~PG_W)) 128#define pmap_pte_set_prot(pte, v) ((*(int *)pte &= ~PG_PROT), (*(int *)pte |= (v))) 129 130/* 131 * Given a map and a machine independent protection code, 132 * convert to a vax protection code. 133 */ 134#define pte_prot(m, p) (protection_codes[p]) 135static int protection_codes[8]; 136 137static struct pmap kernel_pmap_store; 138pmap_t kernel_pmap; 139 140vm_offset_t avail_start; /* PA of first available physical page */ 141vm_offset_t avail_end; /* PA of last available physical page */ 142vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss) */ 143vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ 144static boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ 145static vm_offset_t vm_first_phys; 146 147static int nkpt; 148 149extern vm_offset_t clean_sva, clean_eva; 150extern int cpu_class; 151 152/* 153 * All those kernel PT submaps that BSD is so fond of 154 */ 155pt_entry_t *CMAP1; 156static pt_entry_t *CMAP2, *ptmmap; 157static pv_entry_t pv_table; 158caddr_t CADDR1, ptvmmap; 159static caddr_t CADDR2; 160static pt_entry_t *msgbufmap; 161struct msgbuf *msgbufp; 162 163static void free_pv_entry __P((pv_entry_t pv)); 164pt_entry_t * 165 get_pt_entry __P((pmap_t pmap)); 166static pv_entry_t 167 get_pv_entry __P((void)); 168static void i386_protection_init __P((void)); 169static void pmap_alloc_pv_entry __P((void)); 170static void pmap_changebit __P((vm_offset_t pa, int bit, boolean_t setem)); 171static void pmap_enter_quick __P((pmap_t pmap, vm_offset_t va, 172 vm_offset_t pa)); 173static int pmap_is_managed __P((vm_offset_t pa)); 174static void pmap_remove_all __P((vm_offset_t pa)); 175static void pmap_remove_page __P((struct pmap *pmap, vm_offset_t va)); 176static __inline void pmap_remove_entry __P((struct pmap *pmap, pv_entry_t pv, 177 vm_offset_t va)); 178static int pmap_remove_pte __P((struct pmap *pmap, pt_entry_t *ptq, 179 vm_offset_t sva)); 180static vm_page_t 181 pmap_pte_vm_page __P((pmap_t pmap, vm_offset_t pt)); 182static boolean_t 183 pmap_testbit __P((vm_offset_t pa, int bit)); 184static void * pmap_getpdir __P((void)); 185void pmap_prefault __P((pmap_t pmap, vm_offset_t addra, 186 vm_map_entry_t entry, vm_object_t object)); 187 188 189#if defined(PMAP_DIAGNOSTIC) 190 191/* 192 * This code checks for non-writeable/modified pages. 193 * This should be an invalid condition. 194 */ 195static int 196pmap_nw_modified(pt_entry_t ptea) { 197 int pte; 198 199 pte = (int) ptea; 200 201 if ((pte & (PG_M|PG_RW)) == PG_M) 202 return 1; 203 else 204 return 0; 205} 206#endif 207 208/* 209 * The below are finer grained pmap_update routines. These eliminate 210 * the gratuitious tlb flushes on non-i386 architectures. 211 */ 212static __inline void 213pmap_update_1pg( vm_offset_t va) { 214#if defined(I386_CPU) 215 if (cpu_class == CPUCLASS_386) 216 pmap_update(); 217 else 218#endif 219 __asm __volatile(".byte 0xf,0x1,0x38": :"a" (va)); 220} 221 222static __inline void 223pmap_update_2pg( vm_offset_t va1, vm_offset_t va2) { 224#if defined(I386_CPU) 225 if (cpu_class == CPUCLASS_386) { 226 pmap_update(); 227 } else 228#endif 229 { 230 __asm __volatile(".byte 0xf,0x1,0x38": :"a" (va1)); 231 __asm __volatile(".byte 0xf,0x1,0x38": :"a" (va2)); 232 } 233} 234 235/* 236 * Routine: pmap_pte 237 * Function: 238 * Extract the page table entry associated 239 * with the given map/virtual_address pair. 240 * [ what about induced faults -wfj] 241 */ 242 243__inline pt_entry_t * __pure 244pmap_pte(pmap, va) 245 register pmap_t pmap; 246 vm_offset_t va; 247{ 248 249 if (pmap && *pmap_pde(pmap, va)) { 250 vm_offset_t frame = (int) pmap->pm_pdir[PTDPTDI] & PG_FRAME; 251 252 /* are we current address space or kernel? */ 253 if ((pmap == kernel_pmap) || (frame == ((int) PTDpde & PG_FRAME))) 254 return ((pt_entry_t *) vtopte(va)); 255 /* otherwise, we are alternate address space */ 256 else { 257 if (frame != ((int) APTDpde & PG_FRAME)) { 258 APTDpde = pmap->pm_pdir[PTDPTDI]; 259 pmap_update(); 260 } 261 return ((pt_entry_t *) avtopte(va)); 262 } 263 } 264 return (0); 265} 266 267/* 268 * Routine: pmap_extract 269 * Function: 270 * Extract the physical page address associated 271 * with the given map/virtual_address pair. 272 */ 273 274vm_offset_t 275pmap_extract(pmap, va) 276 register pmap_t pmap; 277 vm_offset_t va; 278{ 279 vm_offset_t pa; 280 281 if (pmap && *pmap_pde(pmap, va)) { 282 vm_offset_t frame = (int) pmap->pm_pdir[PTDPTDI] & PG_FRAME; 283 284 /* are we current address space or kernel? */ 285 if ((pmap == kernel_pmap) 286 || (frame == ((int) PTDpde & PG_FRAME))) { 287 pa = *(int *) vtopte(va); 288 /* otherwise, we are alternate address space */ 289 } else { 290 if (frame != ((int) APTDpde & PG_FRAME)) { 291 APTDpde = pmap->pm_pdir[PTDPTDI]; 292 pmap_update(); 293 } 294 pa = *(int *) avtopte(va); 295 } 296 return ((pa & PG_FRAME) | (va & ~PG_FRAME)); 297 } 298 return 0; 299 300} 301 302/* 303 * determine if a page is managed (memory vs. device) 304 */ 305static __inline int 306pmap_is_managed(pa) 307 vm_offset_t pa; 308{ 309 int i; 310 311 if (!pmap_initialized) 312 return 0; 313 314 for (i = 0; phys_avail[i + 1]; i += 2) { 315 if (pa < phys_avail[i + 1] && pa >= phys_avail[i]) 316 return 1; 317 } 318 return 0; 319} 320 321vm_page_t 322pmap_use_pt(pmap, va) 323 pmap_t pmap; 324 vm_offset_t va; 325{ 326 vm_offset_t ptepa; 327 vm_page_t mpte; 328 329 if (va >= UPT_MIN_ADDRESS) 330 return NULL; 331 332 ptepa = ((vm_offset_t) *pmap_pde(pmap, va)) & PG_FRAME; 333#if defined(PMAP_DIAGNOSTIC) 334 if (!ptepa) 335 panic("pmap_use_pt: pagetable page missing, va: 0x%x", va); 336#endif 337 338 mpte = PHYS_TO_VM_PAGE(ptepa); 339 ++mpte->hold_count; 340 return mpte; 341} 342 343#if !defined(PMAP_DIAGNOSTIC) 344__inline 345#endif 346void 347pmap_unuse_pt(pmap, va, mpte) 348 pmap_t pmap; 349 vm_offset_t va; 350 vm_page_t mpte; 351{ 352 if (va >= UPT_MIN_ADDRESS) 353 return; 354 355 if (mpte == NULL) { 356 vm_offset_t ptepa; 357 ptepa = ((vm_offset_t) *pmap_pde(pmap, va)) & PG_FRAME; 358#if defined(PMAP_DIAGNOSTIC) 359 if (!ptepa) 360 panic("pmap_unuse_pt: pagetable page missing, va: 0x%x", va); 361#endif 362 mpte = PHYS_TO_VM_PAGE(ptepa); 363 } 364 365#if defined(PMAP_DIAGNOSTIC) 366 if (mpte->hold_count == 0) { 367 panic("pmap_unuse_pt: hold count < 0, va: 0x%x", va); 368 } 369#endif 370 371 vm_page_unhold(mpte); 372 373 if ((mpte->hold_count == 0) && 374 (mpte->wire_count == 0) && 375 (pmap != kernel_pmap) && 376 (va < KPT_MIN_ADDRESS)) { 377/* 378 * We don't free page-table-pages anymore because it can have a negative 379 * impact on perf at times. Now we just deactivate, and it'll get cleaned 380 * up if needed... Also, if the page ends up getting used, it will fault 381 * back into the process address space and be reactivated. 382 */ 383#if defined(PMAP_FREE_OLD_PTES) 384 pmap_page_protect(VM_PAGE_TO_PHYS(mpte), VM_PROT_NONE); 385 vm_page_free(mpte); 386#else 387 mpte->dirty = 0; 388 vm_page_deactivate(mpte); 389#endif 390 } 391} 392 393/* 394 * Bootstrap the system enough to run with virtual memory. 395 * 396 * On the i386 this is called after mapping has already been enabled 397 * and just syncs the pmap module with what has already been done. 398 * [We can't call it easily with mapping off since the kernel is not 399 * mapped with PA == VA, hence we would have to relocate every address 400 * from the linked base (virtual) address "KERNBASE" to the actual 401 * (physical) address starting relative to 0] 402 */ 403void 404pmap_bootstrap(firstaddr, loadaddr) 405 vm_offset_t firstaddr; 406 vm_offset_t loadaddr; 407{ 408 vm_offset_t va; 409 pt_entry_t *pte; 410 411 avail_start = firstaddr; 412 413 /* 414 * XXX The calculation of virtual_avail is wrong. It's NKPT*PAGE_SIZE too 415 * large. It should instead be correctly calculated in locore.s and 416 * not based on 'first' (which is a physical address, not a virtual 417 * address, for the start of unused physical memory). The kernel 418 * page tables are NOT double mapped and thus should not be included 419 * in this calculation. 420 */ 421 virtual_avail = (vm_offset_t) KERNBASE + firstaddr; 422 virtual_end = VM_MAX_KERNEL_ADDRESS; 423 424 /* 425 * Initialize protection array. 426 */ 427 i386_protection_init(); 428 429 /* 430 * The kernel's pmap is statically allocated so we don't have to use 431 * pmap_create, which is unlikely to work correctly at this part of 432 * the boot sequence (XXX and which no longer exists). 433 */ 434 kernel_pmap = &kernel_pmap_store; 435 436 kernel_pmap->pm_pdir = (pd_entry_t *) (KERNBASE + IdlePTD); 437 438 kernel_pmap->pm_count = 1; 439 nkpt = NKPT; 440 441 /* 442 * Reserve some special page table entries/VA space for temporary 443 * mapping of pages. 444 */ 445#define SYSMAP(c, p, v, n) \ 446 v = (c)va; va += ((n)*PAGE_SIZE); p = pte; pte += (n); 447 448 va = virtual_avail; 449 pte = pmap_pte(kernel_pmap, va); 450 451 /* 452 * CMAP1/CMAP2 are used for zeroing and copying pages. 453 */ 454 SYSMAP(caddr_t, CMAP1, CADDR1, 1) 455 SYSMAP(caddr_t, CMAP2, CADDR2, 1) 456 457 /* 458 * ptmmap is used for reading arbitrary physical pages via /dev/mem. 459 */ 460 SYSMAP(caddr_t, ptmmap, ptvmmap, 1) 461 462 /* 463 * msgbufmap is used to map the system message buffer. 464 */ 465 SYSMAP(struct msgbuf *, msgbufmap, msgbufp, 1) 466 467 virtual_avail = va; 468 469 *(int *) CMAP1 = *(int *) CMAP2 = *(int *) PTD = 0; 470 pmap_update(); 471} 472 473/* 474 * Initialize the pmap module. 475 * Called by vm_init, to initialize any structures that the pmap 476 * system needs to map virtual memory. 477 * pmap_init has been enhanced to support in a fairly consistant 478 * way, discontiguous physical memory. 479 */ 480void 481pmap_init(phys_start, phys_end) 482 vm_offset_t phys_start, phys_end; 483{ 484 vm_offset_t addr; 485 vm_size_t npg, s; 486 int i; 487 488 /* 489 * calculate the number of pv_entries needed 490 */ 491 vm_first_phys = phys_avail[0]; 492 for (i = 0; phys_avail[i + 1]; i += 2); 493 npg = (phys_avail[(i - 2) + 1] - vm_first_phys) / PAGE_SIZE; 494 495 /* 496 * Allocate memory for random pmap data structures. Includes the 497 * pv_head_table. 498 */ 499 s = (vm_size_t) (sizeof(struct pv_entry) * npg); 500 s = round_page(s); 501 addr = (vm_offset_t) kmem_alloc(kernel_map, s); 502 pv_table = (pv_entry_t) addr; 503 504 /* 505 * init the pv free list 506 */ 507 init_pv_entries(npg); 508 /* 509 * Now it is safe to enable pv_table recording. 510 */ 511 pmap_initialized = TRUE; 512} 513 514/* 515 * Used to map a range of physical addresses into kernel 516 * virtual address space. 517 * 518 * For now, VM is already on, we only need to map the 519 * specified memory. 520 */ 521vm_offset_t 522pmap_map(virt, start, end, prot) 523 vm_offset_t virt; 524 vm_offset_t start; 525 vm_offset_t end; 526 int prot; 527{ 528 while (start < end) { 529 pmap_enter(kernel_pmap, virt, start, prot, FALSE); 530 virt += PAGE_SIZE; 531 start += PAGE_SIZE; 532 } 533 return (virt); 534} 535 536#if defined(PMAP_KEEP_PDIRS) 537int nfreepdir; 538caddr_t *pdirlist; 539#define NFREEPDIR 3 540 541static void * 542pmap_getpdir() { 543 caddr_t *pdir; 544 if (pdirlist) { 545 --nfreepdir; 546 pdir = pdirlist; 547 pdirlist = (caddr_t *) *pdir; 548#if 0 /* Not needed anymore */ 549 bzero( (caddr_t) pdir, PAGE_SIZE); 550#endif 551 } else { 552 pdir = (caddr_t *) kmem_alloc(kernel_map, PAGE_SIZE); 553 } 554 555 return (void *) pdir; 556} 557 558static void 559pmap_freepdir(void *pdir) { 560 if (nfreepdir > NFREEPDIR) { 561 kmem_free(kernel_map, (vm_offset_t) pdir, PAGE_SIZE); 562 } else { 563 int i; 564 pt_entry_t *s; 565 s = (pt_entry_t *) pdir; 566 567 /* 568 * remove wired in kernel mappings 569 */ 570 bzero(s + KPTDI, nkpt * PTESIZE); 571 s[APTDPTDI] = 0; 572 s[PTDPTDI] = 0; 573 574#if defined(PMAP_DIAGNOSTIC) 575 for(i=0;i<PAGE_SIZE/4;i++,s++) { 576 if (*s) { 577 printf("pmap_freepdir: index %d not zero: %lx\n", i, *s); 578 } 579 } 580#endif 581 * (caddr_t *) pdir = (caddr_t) pdirlist; 582 pdirlist = (caddr_t *) pdir; 583 ++nfreepdir; 584 } 585} 586#endif 587 588/* 589 * Initialize a preallocated and zeroed pmap structure, 590 * such as one in a vmspace structure. 591 */ 592void 593pmap_pinit(pmap) 594 register struct pmap *pmap; 595{ 596 /* 597 * No need to allocate page table space yet but we do need a valid 598 * page directory table. 599 */ 600 601#if defined(PMAP_KEEP_PDIRS) 602 pmap->pm_pdir = pmap_getpdir(); 603#else 604 pmap->pm_pdir = (pd_entry_t *) kmem_alloc(kernel_map, PAGE_SIZE); 605#endif 606 607 /* wire in kernel global address entries */ 608 bcopy(PTD + KPTDI, pmap->pm_pdir + KPTDI, nkpt * PTESIZE); 609 610 /* install self-referential address mapping entry */ 611 *(int *) (pmap->pm_pdir + PTDPTDI) = 612 ((int) pmap_kextract((vm_offset_t) pmap->pm_pdir)) | PG_V | PG_KW; 613 614 pmap->pm_count = 1; 615} 616 617/* 618 * grow the number of kernel page table entries, if needed 619 */ 620 621static vm_page_t nkpg; 622vm_offset_t kernel_vm_end; 623 624void 625pmap_growkernel(vm_offset_t addr) 626{ 627 struct proc *p; 628 struct pmap *pmap; 629 int s; 630 631 s = splhigh(); 632 if (kernel_vm_end == 0) { 633 kernel_vm_end = KERNBASE; 634 nkpt = 0; 635 while (pdir_pde(PTD, kernel_vm_end)) { 636 kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); 637 ++nkpt; 638 } 639 } 640 addr = (addr + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); 641 while (kernel_vm_end < addr) { 642 if (pdir_pde(PTD, kernel_vm_end)) { 643 kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); 644 continue; 645 } 646 ++nkpt; 647 if (!nkpg) { 648 nkpg = vm_page_alloc(kernel_object, 0, VM_ALLOC_SYSTEM); 649 if (!nkpg) 650 panic("pmap_growkernel: no memory to grow kernel"); 651 vm_page_wire(nkpg); 652 vm_page_remove(nkpg); 653 pmap_zero_page(VM_PAGE_TO_PHYS(nkpg)); 654 } 655 pdir_pde(PTD, kernel_vm_end) = (pd_entry_t) (VM_PAGE_TO_PHYS(nkpg) | PG_V | PG_KW); 656 nkpg = NULL; 657 658 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 659 if (p->p_vmspace) { 660 pmap = &p->p_vmspace->vm_pmap; 661 *pmap_pde(pmap, kernel_vm_end) = pdir_pde(PTD, kernel_vm_end); 662 } 663 } 664 *pmap_pde(kernel_pmap, kernel_vm_end) = pdir_pde(PTD, kernel_vm_end); 665 kernel_vm_end = (kernel_vm_end + PAGE_SIZE * NPTEPG) & ~(PAGE_SIZE * NPTEPG - 1); 666 } 667 splx(s); 668} 669 670/* 671 * Retire the given physical map from service. 672 * Should only be called if the map contains 673 * no valid mappings. 674 */ 675void 676pmap_destroy(pmap) 677 register pmap_t pmap; 678{ 679 int count; 680 681 if (pmap == NULL) 682 return; 683 684 count = --pmap->pm_count; 685 if (count == 0) { 686 pmap_release(pmap); 687 free((caddr_t) pmap, M_VMPMAP); 688 } 689} 690 691/* 692 * Release any resources held by the given physical map. 693 * Called when a pmap initialized by pmap_pinit is being released. 694 * Should only be called if the map contains no valid mappings. 695 */ 696void 697pmap_release(pmap) 698 register struct pmap *pmap; 699{ 700#if defined(PMAP_KEEP_PDIRS) 701 pmap_freepdir( (void *)pmap->pm_pdir); 702#else 703 kmem_free(kernel_map, (vm_offset_t) pmap->pm_pdir, PAGE_SIZE); 704#endif 705} 706 707/* 708 * Add a reference to the specified pmap. 709 */ 710void 711pmap_reference(pmap) 712 pmap_t pmap; 713{ 714 if (pmap != NULL) { 715 pmap->pm_count++; 716 } 717} 718 719#define PV_FREELIST_MIN ((PAGE_SIZE / sizeof (struct pv_entry)) / 2) 720 721/* 722 * Data for the pv entry allocation mechanism 723 */ 724static int pv_freelistcnt; 725static pv_entry_t pv_freelist; 726static vm_offset_t pvva; 727static int npvvapg; 728 729/* 730 * free the pv_entry back to the free list 731 */ 732static __inline void 733free_pv_entry(pv) 734 pv_entry_t pv; 735{ 736 if (!pv) 737 return; 738 ++pv_freelistcnt; 739 pv->pv_next = pv_freelist; 740 pv_freelist = pv; 741} 742 743/* 744 * get a new pv_entry, allocating a block from the system 745 * when needed. 746 * the memory allocation is performed bypassing the malloc code 747 * because of the possibility of allocations at interrupt time. 748 */ 749static __inline pv_entry_t 750get_pv_entry() 751{ 752 pv_entry_t tmp; 753 754 /* 755 * get more pv_entry pages if needed 756 */ 757 if (pv_freelistcnt < PV_FREELIST_MIN || pv_freelist == 0) { 758 pmap_alloc_pv_entry(); 759 } 760 /* 761 * get a pv_entry off of the free list 762 */ 763 --pv_freelistcnt; 764 tmp = pv_freelist; 765 pv_freelist = tmp->pv_next; 766 return tmp; 767} 768 769/* 770 * this *strange* allocation routine *statistically* eliminates the 771 * *possibility* of a malloc failure (*FATAL*) for a pv_entry_t data structure. 772 * also -- this code is MUCH MUCH faster than the malloc equiv... 773 */ 774static void 775pmap_alloc_pv_entry() 776{ 777 /* 778 * do we have any pre-allocated map-pages left? 779 */ 780 if (npvvapg) { 781 vm_page_t m; 782 783 /* 784 * we do this to keep recursion away 785 */ 786 pv_freelistcnt += PV_FREELIST_MIN; 787 /* 788 * allocate a physical page out of the vm system 789 */ 790 m = vm_page_alloc(kernel_object, 791 OFF_TO_IDX(pvva - vm_map_min(kernel_map)), 792 VM_ALLOC_INTERRUPT); 793 if (m) { 794 int newentries; 795 int i; 796 pv_entry_t entry; 797 798 newentries = (PAGE_SIZE / sizeof(struct pv_entry)); 799 /* 800 * wire the page 801 */ 802 vm_page_wire(m); 803 m->flags &= ~PG_BUSY; 804 /* 805 * let the kernel see it 806 */ 807 pmap_kenter(pvva, VM_PAGE_TO_PHYS(m)); 808 809 entry = (pv_entry_t) pvva; 810 /* 811 * update the allocation pointers 812 */ 813 pvva += PAGE_SIZE; 814 --npvvapg; 815 816 /* 817 * free the entries into the free list 818 */ 819 for (i = 0; i < newentries; i++) { 820 free_pv_entry(entry); 821 entry++; 822 } 823 } 824 pv_freelistcnt -= PV_FREELIST_MIN; 825 } 826 if (!pv_freelist) 827 panic("get_pv_entry: cannot get a pv_entry_t"); 828} 829 830 831 832/* 833 * init the pv_entry allocation system 834 */ 835#define PVSPERPAGE 64 836void 837init_pv_entries(npg) 838 int npg; 839{ 840 /* 841 * allocate enough kvm space for PVSPERPAGE entries per page (lots) 842 * kvm space is fairly cheap, be generous!!! (the system can panic if 843 * this is too small.) 844 */ 845 npvvapg = ((npg * PVSPERPAGE) * sizeof(struct pv_entry) 846 + PAGE_SIZE - 1) / PAGE_SIZE; 847 pvva = kmem_alloc_pageable(kernel_map, npvvapg * PAGE_SIZE); 848 /* 849 * get the first batch of entries 850 */ 851 free_pv_entry(get_pv_entry()); 852} 853 854__inline pt_entry_t * 855get_pt_entry(pmap) 856 pmap_t pmap; 857{ 858 vm_offset_t frame = (int) pmap->pm_pdir[PTDPTDI] & PG_FRAME; 859 860 /* are we current address space or kernel? */ 861 if (pmap == kernel_pmap || frame == ((int) PTDpde & PG_FRAME)) { 862 return PTmap; 863 } 864 /* otherwise, we are alternate address space */ 865 if (frame != ((int) APTDpde & PG_FRAME)) { 866 APTDpde = pmap->pm_pdir[PTDPTDI]; 867 pmap_update(); 868 } 869 return APTmap; 870} 871 872/* 873 * If it is the first entry on the list, it is actually 874 * in the header and we must copy the following entry up 875 * to the header. Otherwise we must search the list for 876 * the entry. In either case we free the now unused entry. 877 */ 878static __inline void 879pmap_remove_entry(pmap, pv, va) 880 struct pmap *pmap; 881 pv_entry_t pv; 882 vm_offset_t va; 883{ 884 pv_entry_t npv; 885 int s; 886 s = splhigh(); 887 if (pmap == pv->pv_pmap && va == pv->pv_va) { 888 pmap_unuse_pt(pmap, va, pv->pv_ptem); 889 npv = pv->pv_next; 890 if (npv) { 891 *pv = *npv; 892 free_pv_entry(npv); 893 } else { 894 pv->pv_pmap = NULL; 895 } 896 } else { 897 for (npv = pv->pv_next; npv; (pv = npv, npv = pv->pv_next)) { 898 if (pmap == npv->pv_pmap && va == npv->pv_va) { 899 pmap_unuse_pt(pmap, va, npv->pv_ptem); 900 pv->pv_next = npv->pv_next; 901 free_pv_entry(npv); 902 break; 903 } 904 } 905 } 906 splx(s); 907} 908 909/* 910 * pmap_remove_pte: do the things to unmap a page to mapped into a process 911 */ 912static int 913pmap_remove_pte(pmap, ptq, sva) 914 struct pmap *pmap; 915 pt_entry_t *ptq; 916 vm_offset_t sva; 917{ 918 pt_entry_t oldpte; 919 vm_offset_t pa; 920 pv_entry_t pv; 921 922 oldpte = *ptq; 923 if (((int)oldpte) & PG_W) 924 pmap->pm_stats.wired_count--; 925 pmap->pm_stats.resident_count--; 926 927 pa = ((vm_offset_t)oldpte) & PG_FRAME; 928 if (pmap_is_managed(pa)) { 929 if ((int) oldpte & PG_M) { 930#if defined(PMAP_DIAGNOSTIC) 931 if (pmap_nw_modified(oldpte)) { 932 printf("pmap_remove: modified page not writable: va: 0x%lx, pte: 0x%lx\n", sva, (int) oldpte); 933 } 934#endif 935 936 if (sva < USRSTACK + (UPAGES * PAGE_SIZE) || 937 (sva >= KERNBASE && (sva < clean_sva || sva >= clean_eva))) { 938 PHYS_TO_VM_PAGE(pa)->dirty = VM_PAGE_BITS_ALL; 939 } 940 } 941 pv = pa_to_pvh(pa); 942 pmap_remove_entry(pmap, pv, sva); 943 } else { 944 pmap_unuse_pt(pmap, sva, NULL); 945 } 946 947 *ptq = 0; 948 return 1; 949} 950 951/* 952 * Scan pmap for non-null entry up to the entry pointed to 953 * by pdnxt. Return the va corresponding to the entry. 954 */ 955static __inline vm_offset_t 956pmap_scan( vm_offset_t sva, vm_offset_t pdnxt, pt_entry_t *ptp) { 957 pt_entry_t *ptt, *ptnxt; 958 959 ptnxt = &ptp[pdnxt]; 960 ptt = &ptp[sva]; 961 962loop: 963 if ((ptt != ptnxt) && (*ptt == 0)) { 964 ptt++; 965 goto loop; 966 } 967 return ptt - ptp; 968} 969 970/* 971 * Remove a single page from a process address space 972 */ 973static __inline void 974pmap_remove_page(pmap, va) 975 struct pmap *pmap; 976 register vm_offset_t va; 977{ 978 register pt_entry_t *ptp, *ptq; 979 /* 980 * if there is no pte for this address, just skip it!!! 981 */ 982 if (*pmap_pde(pmap, va) == 0) 983 return; 984 /* 985 * get a local va for mappings for this pmap. 986 */ 987 ptp = get_pt_entry(pmap); 988 ptq = ptp + i386_btop(va); 989 if ( *ptq && pmap_remove_pte( pmap, ptq, va)) 990 pmap_update_1pg(va); 991 return; 992} 993 994/* 995 * Remove the given range of addresses from the specified map. 996 * 997 * It is assumed that the start and end are properly 998 * rounded to the page size. 999 */ 1000void 1001pmap_remove(pmap, sva, eva) 1002 struct pmap *pmap; 1003 register vm_offset_t sva; 1004 register vm_offset_t eva; 1005{ 1006 register pt_entry_t *ptp; 1007 vm_offset_t va; 1008 vm_offset_t pdnxt; 1009 vm_offset_t ptepaddr; 1010 int update_needed; 1011 vm_page_t mpte; 1012 1013 if (pmap == NULL) 1014 return; 1015 1016 /* 1017 * special handling of removing one page. a very 1018 * common operation and easy to short circuit some 1019 * code. 1020 */ 1021 if ((sva + PAGE_SIZE) == eva) { 1022 pmap_remove_page(pmap, sva); 1023 return; 1024 } 1025 1026 /* 1027 * Get a local virtual address for the mappings that are being 1028 * worked with. 1029 */ 1030 1031 update_needed = 0; 1032 va = sva; 1033 sva = i386_btop(va); 1034 1035 pdnxt = ((sva + NPTEPG) & ~(NPTEPG - 1)); 1036 ptepaddr = (vm_offset_t) *pmap_pde(pmap, va); 1037 eva = i386_btop(eva); 1038 mpte = NULL; 1039 ptp = NULL; 1040 1041 while (sva < eva) { 1042 1043 /* 1044 * pointers for page table hold count and wire counts. 1045 */ 1046 short *hc; 1047 u_short *wc; 1048 1049 /* 1050 * On a new page table page, we need to calculate the 1051 * end va for that page, and it's physical address. 1052 */ 1053 if (sva >= pdnxt) { 1054 pdnxt = ((sva + NPTEPG) & ~(NPTEPG - 1)); 1055 ptepaddr = 1056 (vm_offset_t) *pmap_pde(pmap, i386_ptob(sva)); 1057 mpte = NULL; 1058 } 1059 1060 /* 1061 * Weed out invalid mappings. Note: we assume that the page 1062 * directory table is always allocated, and in kernel virtual. 1063 */ 1064 if (ptepaddr == 0) { 1065 sva = pdnxt; 1066 continue; 1067 } 1068 1069 ptepaddr &= PG_FRAME; 1070 /* 1071 * get the vm_page_t for the page table page 1072 */ 1073 if (mpte == NULL) 1074 mpte = PHYS_TO_VM_PAGE(ptepaddr); 1075 1076 /* 1077 * get the address of the hold and wire counts for the 1078 * page table page. 1079 */ 1080 hc = &(mpte->hold_count); 1081 wc = &(mpte->wire_count); 1082 1083 /* 1084 * if the pte isn't wired or held, just skip it. 1085 */ 1086 if ((*hc == 0) && (*wc == 0)) { 1087 sva = pdnxt; 1088 continue; 1089 } 1090 1091 /* 1092 * Limit our scan to either the end of the va represented 1093 * by the current page table page, or to the end of the 1094 * range being removed. 1095 */ 1096 if (pdnxt > eva) { 1097 pdnxt = eva; 1098 } 1099 1100 /* 1101 * get get the ptp only if we need to 1102 */ 1103 if (ptp == NULL) 1104 ptp = get_pt_entry(pmap); 1105quickloop: 1106 sva = pmap_scan(sva, pdnxt, ptp); 1107 if (sva == pdnxt) 1108 goto endmainloop; 1109 /* 1110 * Remove the found entry. 1111 */ 1112 va = i386_ptob(sva); 1113quickloop1: 1114 if (pmap_remove_pte( pmap, ptp + sva, va)) 1115 update_needed = 1; 1116 1117 /* 1118 * If the wire count and the hold count for the page table page 1119 * are both zero, then we are done. 1120 */ 1121 if ((*hc != 0) || (*wc != 0)) { 1122 ++sva; 1123 if (pdnxt == sva) 1124 goto endmainloop; 1125 if (ptp[sva]) { 1126 va += PAGE_SIZE; 1127 goto quickloop1; 1128 } 1129 goto quickloop; 1130 } 1131 1132 /* 1133 * We are done with the current page table page if we get here 1134 */ 1135 sva = pdnxt; 1136 1137endmainloop: 1138 } 1139 if (update_needed) 1140 pmap_update(); 1141} 1142 1143/* 1144 * Routine: pmap_remove_all 1145 * Function: 1146 * Removes this physical page from 1147 * all physical maps in which it resides. 1148 * Reflects back modify bits to the pager. 1149 * 1150 * Notes: 1151 * Original versions of this routine were very 1152 * inefficient because they iteratively called 1153 * pmap_remove (slow...) 1154 */ 1155static void 1156pmap_remove_all(pa) 1157 vm_offset_t pa; 1158{ 1159 register pv_entry_t pv, opv, npv; 1160 register pt_entry_t *pte, *ptp; 1161 vm_offset_t va; 1162 struct pmap *pmap; 1163 vm_page_t m; 1164 int s; 1165 int anyvalid = 0; 1166 1167#if defined(PMAP_DIAGNOSTIC) 1168 /* 1169 * XXX this makes pmap_page_protect(NONE) illegal for non-managed 1170 * pages! 1171 */ 1172 if (!pmap_is_managed(pa)) { 1173 panic("pmap_page_protect: illegal for unmanaged page, va: 0x%lx", pa); 1174 } 1175#endif 1176 1177 pa = pa & PG_FRAME; 1178 opv = pa_to_pvh(pa); 1179 if (opv->pv_pmap == NULL) 1180 return; 1181 1182 m = PHYS_TO_VM_PAGE(pa); 1183 s = splhigh(); 1184 pv = opv; 1185 while (pv && ((pmap = pv->pv_pmap) != NULL)) { 1186 int tpte; 1187 ptp = get_pt_entry(pmap); 1188 va = pv->pv_va; 1189 pte = ptp + i386_btop(va); 1190 if (tpte = ((int) *pte)) { 1191 *pte = 0; 1192 if (tpte & PG_W) 1193 pmap->pm_stats.wired_count--; 1194 pmap->pm_stats.resident_count--; 1195 anyvalid = 1; 1196 1197 /* 1198 * Update the vm_page_t clean and reference bits. 1199 */ 1200 if ((tpte & PG_M) != 0) { 1201#if defined(PMAP_DIAGNOSTIC) 1202 if (pmap_nw_modified((pt_entry_t) tpte)) { 1203 printf("pmap_remove_all: modified page not writable: va: 0x%lx, pte: 0x%lx\n", va, tpte); 1204 } 1205#endif 1206 if (va < USRSTACK + (UPAGES * PAGE_SIZE) || 1207 (va >= KERNBASE && (va < clean_sva || va >= clean_eva))) { 1208 m->dirty = VM_PAGE_BITS_ALL; 1209 } 1210 } 1211 } 1212 pv = pv->pv_next; 1213 } 1214 1215 if (opv->pv_pmap != NULL) { 1216 pmap_unuse_pt(opv->pv_pmap, opv->pv_va, opv->pv_ptem); 1217 for (pv = opv->pv_next; pv; pv = npv) { 1218 npv = pv->pv_next; 1219 pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem); 1220 free_pv_entry(pv); 1221 } 1222 } 1223 1224 opv->pv_pmap = NULL; 1225 opv->pv_next = NULL; 1226 1227 splx(s); 1228 if (anyvalid) 1229 pmap_update(); 1230} 1231 1232 1233/* 1234 * Set the physical protection on the 1235 * specified range of this map as requested. 1236 */ 1237void 1238pmap_protect(pmap, sva, eva, prot) 1239 register pmap_t pmap; 1240 vm_offset_t sva, eva; 1241 vm_prot_t prot; 1242{ 1243 register pt_entry_t *pte; 1244 register vm_offset_t va; 1245 int i386prot; 1246 register pt_entry_t *ptp; 1247 vm_offset_t pdnxt; 1248 vm_offset_t ptepaddr; 1249 vm_page_t mpte; 1250 1251 int anychanged = 0; 1252 1253 if (pmap == NULL) 1254 return; 1255 1256 if ((prot & VM_PROT_READ) == VM_PROT_NONE) { 1257 pmap_remove(pmap, sva, eva); 1258 return; 1259 } 1260 if (prot & VM_PROT_WRITE) 1261 return; 1262 1263 ptp = get_pt_entry(pmap); 1264 1265 eva = i386_btop(eva); 1266 1267 sva = i386_btop(va = sva); 1268 pdnxt = ((sva + NPTEPG) & ~(NPTEPG - 1)); 1269 ptepaddr = (vm_offset_t) *pmap_pde(pmap, va); 1270 mpte = NULL; 1271 1272 while (sva < eva) { 1273 int pprot; 1274 int pbits; 1275 /* 1276 * Weed out invalid mappings. Note: we assume that the page 1277 * directory table is always allocated, and in kernel virtual. 1278 */ 1279 if (sva >= pdnxt) { 1280 pdnxt = ((sva + NPTEPG) & ~(NPTEPG - 1)); 1281 ptepaddr = 1282 (vm_offset_t) *pmap_pde(pmap, i386_ptob(sva)); 1283 mpte = NULL; 1284 } 1285 1286 if (ptepaddr == 0) { 1287 sva = pdnxt; 1288 continue; 1289 } 1290 1291 ptepaddr &= PG_FRAME; 1292 if (mpte == NULL) 1293 mpte = PHYS_TO_VM_PAGE(ptepaddr); 1294 1295 if ((mpte->hold_count == 0) && (mpte->wire_count == 0)) { 1296 sva = pdnxt; 1297 continue; 1298 } 1299 1300 if (pdnxt > eva) { 1301 pdnxt = eva; 1302 } 1303 1304quickloop: 1305 sva = pmap_scan( sva, pdnxt, ptp); 1306 if (sva == pdnxt) { 1307 continue; 1308 } 1309 1310 pte = ptp + sva; 1311 pbits = *(int *)pte; 1312 1313 if (pbits & PG_RW) { 1314 if (pbits & PG_M) { 1315 vm_page_t m; 1316 vm_offset_t pa = pbits & PG_FRAME; 1317 m = PHYS_TO_VM_PAGE(pa); 1318 m->dirty = VM_PAGE_BITS_ALL; 1319 } 1320 *(int *)pte &= ~(PG_M|PG_RW); 1321 anychanged=1; 1322 } 1323 ++sva; 1324 if ( sva < pdnxt) 1325 goto quickloop; 1326 } 1327 if (anychanged) 1328 pmap_update(); 1329} 1330 1331/* 1332 * Insert the given physical page (p) at 1333 * the specified virtual address (v) in the 1334 * target physical map with the protection requested. 1335 * 1336 * If specified, the page will be wired down, meaning 1337 * that the related pte can not be reclaimed. 1338 * 1339 * NB: This is the only routine which MAY NOT lazy-evaluate 1340 * or lose information. That is, this routine must actually 1341 * insert this page into the given map NOW. 1342 */ 1343void 1344pmap_enter(pmap, va, pa, prot, wired) 1345 register pmap_t pmap; 1346 vm_offset_t va; 1347 register vm_offset_t pa; 1348 vm_prot_t prot; 1349 boolean_t wired; 1350{ 1351 register pt_entry_t *pte; 1352 vm_offset_t opa; 1353 register pv_entry_t pv, npv; 1354 int ptevalid; 1355 vm_offset_t origpte, newpte; 1356 1357 if (pmap == NULL) 1358 return; 1359 1360 pv = NULL; 1361 1362 va = va & PG_FRAME; 1363 if (va > VM_MAX_KERNEL_ADDRESS) 1364 panic("pmap_enter: toobig"); 1365 1366#ifdef NO_HANDLE_LOCKED_PTES 1367 /* 1368 * Page Directory table entry not valid, we need a new PT page 1369 */ 1370 pte = pmap_pte(pmap, va); 1371 if (pte == NULL) { 1372 printf("kernel page directory invalid pdir=%p, va=0x%lx\n", 1373 pmap->pm_pdir[PTDPTDI], va); 1374 panic("invalid kernel page directory"); 1375 } 1376#else 1377 /* 1378 * This is here in the case that a page table page is not 1379 * resident, but we are inserting a page there. 1380 */ 1381 if ((va < VM_MIN_KERNEL_ADDRESS) && 1382 (curproc != NULL) && 1383 (pmap == &curproc->p_vmspace->vm_pmap)) { 1384 vm_offset_t v; 1385 v = (vm_offset_t) vtopte(va); 1386 1387 /* Fault the pte only if needed: */ 1388 if (*((int *)vtopte(v)) == 0) 1389 (void) vm_fault(&curproc->p_vmspace->vm_map, 1390 trunc_page(v), VM_PROT_WRITE, FALSE); 1391 } 1392 1393 /* 1394 * Page Directory table entry not valid, we need a new PT page 1395 */ 1396 pte = pmap_pte(pmap, va); 1397 if (pte == NULL) { 1398 printf("kernel page directory invalid pdir=%p, va=0x%lx\n", 1399 pmap->pm_pdir[PTDPTDI], va); 1400 panic("invalid kernel page directory"); 1401 } 1402#endif 1403 1404 origpte = *(vm_offset_t *)pte; 1405 opa = origpte & PG_FRAME; 1406 1407 pa = pa & PG_FRAME; 1408 1409 /* 1410 * Mapping has not changed, must be protection or wiring change. 1411 */ 1412 if (opa == pa) { 1413 /* 1414 * Wiring change, just update stats. We don't worry about 1415 * wiring PT pages as they remain resident as long as there 1416 * are valid mappings in them. Hence, if a user page is wired, 1417 * the PT page will be also. 1418 */ 1419 if (wired && ((origpte & PG_W) == 0)) 1420 pmap->pm_stats.wired_count++; 1421 else if (!wired && (origpte & PG_W)) 1422 pmap->pm_stats.wired_count--; 1423 1424#if defined(PMAP_DIAGNOSTIC) 1425 if (pmap_nw_modified((pt_entry_t) origpte)) { 1426 printf("pmap_enter: modified page not writable: va: 0x%lx, pte: 0x%lx\n", va, origpte); 1427 } 1428#endif 1429 1430 /* 1431 * We might be turning off write access to the page, 1432 * so we go ahead and sense modify status. 1433 */ 1434 if (origpte & PG_M) { 1435 vm_page_t m; 1436 m = PHYS_TO_VM_PAGE(pa); 1437 m->dirty = VM_PAGE_BITS_ALL; 1438 } 1439 goto validate; 1440 } 1441 /* 1442 * Mapping has changed, invalidate old range and fall through to 1443 * handle validating new mapping. 1444 */ 1445 if (opa) { 1446 pmap_remove_page(pmap, va); 1447 opa = 0; 1448 origpte = 0; 1449 } 1450 /* 1451 * Enter on the PV list if part of our managed memory Note that we 1452 * raise IPL while manipulating pv_table since pmap_enter can be 1453 * called at interrupt time. 1454 */ 1455 if (pmap_is_managed(pa)) { 1456 int s; 1457 1458 pv = pa_to_pvh(pa); 1459 s = splhigh(); 1460 /* 1461 * No entries yet, use header as the first entry 1462 */ 1463 if (pv->pv_pmap == NULL) { 1464 pv->pv_va = va; 1465 pv->pv_pmap = pmap; 1466 pv->pv_next = NULL; 1467 pv->pv_ptem = NULL; 1468 } 1469 /* 1470 * There is at least one other VA mapping this page. Place 1471 * this entry after the header. 1472 */ 1473 else { 1474 npv = get_pv_entry(); 1475 npv->pv_va = va; 1476 npv->pv_pmap = pmap; 1477 npv->pv_next = pv->pv_next; 1478 pv->pv_next = npv; 1479 pv = npv; 1480 pv->pv_ptem = NULL; 1481 } 1482 splx(s); 1483 } 1484 1485 /* 1486 * Increment counters 1487 */ 1488 pmap->pm_stats.resident_count++; 1489 if (wired) 1490 pmap->pm_stats.wired_count++; 1491 1492validate: 1493 /* 1494 * Now validate mapping with desired protection/wiring. 1495 */ 1496 newpte = (vm_offset_t) (pa | pte_prot(pmap, prot) | PG_V); 1497 1498 if (wired) 1499 newpte |= PG_W; 1500 if (va < UPT_MIN_ADDRESS) 1501 newpte |= PG_u; 1502 else if (va < UPT_MAX_ADDRESS) 1503 newpte |= PG_u | PG_RW; 1504 1505 /* 1506 * if the mapping or permission bits are different, we need 1507 * to update the pte. 1508 */ 1509 if ((origpte & ~(PG_M|PG_U)) != newpte) { 1510 *pte = (pt_entry_t) newpte; 1511 if (origpte) 1512 pmap_update_1pg(va); 1513 } 1514 1515 if (origpte == 0) { 1516 vm_page_t mpte; 1517 mpte = pmap_use_pt(pmap, va); 1518 if (pv) 1519 pv->pv_ptem = mpte; 1520 } 1521} 1522 1523/* 1524 * Add a list of wired pages to the kva 1525 * this routine is only used for temporary 1526 * kernel mappings that do not need to have 1527 * page modification or references recorded. 1528 * Note that old mappings are simply written 1529 * over. The page *must* be wired. 1530 */ 1531void 1532pmap_qenter(va, m, count) 1533 vm_offset_t va; 1534 vm_page_t *m; 1535 int count; 1536{ 1537 int i; 1538 int anyvalid = 0; 1539 register pt_entry_t *pte; 1540 1541 for (i = 0; i < count; i++) { 1542 vm_offset_t tva = va + i * PAGE_SIZE; 1543 pt_entry_t npte = (pt_entry_t) ((int) (VM_PAGE_TO_PHYS(m[i]) | PG_RW | PG_V)); 1544 pt_entry_t opte; 1545 pte = vtopte(tva); 1546 opte = *pte; 1547 *pte = npte; 1548 if (opte) pmap_update_1pg(tva); 1549 } 1550} 1551/* 1552 * this routine jerks page mappings from the 1553 * kernel -- it is meant only for temporary mappings. 1554 */ 1555void 1556pmap_qremove(va, count) 1557 vm_offset_t va; 1558 int count; 1559{ 1560 int i; 1561 register pt_entry_t *pte; 1562 1563 for (i = 0; i < count; i++) { 1564 vm_offset_t tva = va + i * PAGE_SIZE; 1565 pte = vtopte(tva); 1566 *pte = 0; 1567 pmap_update_1pg(tva); 1568 } 1569} 1570 1571/* 1572 * add a wired page to the kva 1573 * note that in order for the mapping to take effect -- you 1574 * should do a pmap_update after doing the pmap_kenter... 1575 */ 1576void 1577pmap_kenter(va, pa) 1578 vm_offset_t va; 1579 register vm_offset_t pa; 1580{ 1581 register pt_entry_t *pte; 1582 pt_entry_t npte, opte; 1583 1584 npte = (pt_entry_t) ((int) (pa | PG_RW | PG_V)); 1585 pte = vtopte(va); 1586 opte = *pte; 1587 *pte = npte; 1588 if (opte) pmap_update_1pg(va); 1589} 1590 1591/* 1592 * remove a page from the kernel pagetables 1593 */ 1594void 1595pmap_kremove(va) 1596 vm_offset_t va; 1597{ 1598 register pt_entry_t *pte; 1599 1600 pte = vtopte(va); 1601 *pte = (pt_entry_t) 0; 1602 pmap_update_1pg(va); 1603} 1604 1605/* 1606 * this code makes some *MAJOR* assumptions: 1607 * 1. Current pmap & pmap exists. 1608 * 2. Not wired. 1609 * 3. Read access. 1610 * 4. No page table pages. 1611 * 5. Tlbflush is deferred to calling procedure. 1612 * 6. Page IS managed. 1613 * but is *MUCH* faster than pmap_enter... 1614 */ 1615 1616static void 1617pmap_enter_quick(pmap, va, pa) 1618 register pmap_t pmap; 1619 vm_offset_t va; 1620 register vm_offset_t pa; 1621{ 1622 register pt_entry_t *pte; 1623 register pv_entry_t pv, npv; 1624 int s; 1625 1626 /* 1627 * Enter on the PV list if part of our managed memory Note that we 1628 * raise IPL while manipulating pv_table since pmap_enter can be 1629 * called at interrupt time. 1630 */ 1631 1632 pte = vtopte(va); 1633 /* a fault on the page table might occur here */ 1634 if (*pte) { 1635 pmap_remove_page(pmap, va); 1636 } 1637 1638 pv = pa_to_pvh(pa); 1639 s = splhigh(); 1640 /* 1641 * No entries yet, use header as the first entry 1642 */ 1643 if (pv->pv_pmap == NULL) { 1644 pv->pv_pmap = pmap; 1645 pv->pv_va = va; 1646 pv->pv_next = NULL; 1647 } 1648 /* 1649 * There is at least one other VA mapping this page. Place this entry 1650 * after the header. 1651 */ 1652 else { 1653 npv = get_pv_entry(); 1654 npv->pv_va = va; 1655 npv->pv_pmap = pmap; 1656 npv->pv_next = pv->pv_next; 1657 pv->pv_next = npv; 1658 pv = npv; 1659 } 1660 splx(s); 1661 pv->pv_ptem = pmap_use_pt(pmap, va); 1662 1663 /* 1664 * Increment counters 1665 */ 1666 pmap->pm_stats.resident_count++; 1667 1668 /* 1669 * Now validate mapping with RO protection 1670 */ 1671 *pte = (pt_entry_t) ((int) (pa | PG_V | PG_u)); 1672 1673 return; 1674} 1675 1676#define MAX_INIT_PT (96) 1677/* 1678 * pmap_object_init_pt preloads the ptes for a given object 1679 * into the specified pmap. This eliminates the blast of soft 1680 * faults on process startup and immediately after an mmap. 1681 */ 1682void 1683pmap_object_init_pt(pmap, addr, object, pindex, size) 1684 pmap_t pmap; 1685 vm_offset_t addr; 1686 vm_object_t object; 1687 vm_pindex_t pindex; 1688 vm_size_t size; 1689{ 1690 vm_offset_t tmpidx; 1691 int psize; 1692 vm_page_t p; 1693 int objpgs; 1694 1695 psize = (size >> PAGE_SHIFT); 1696 1697 if (!pmap || (object->type != OBJT_VNODE) || 1698 ((psize > MAX_INIT_PT) && 1699 (object->resident_page_count > MAX_INIT_PT))) { 1700 return; 1701 } 1702 1703 /* 1704 * remove any already used mappings 1705 */ 1706 pmap_remove( pmap, trunc_page(addr), round_page(addr + size)); 1707 1708 /* 1709 * if we are processing a major portion of the object, then scan the 1710 * entire thing. 1711 */ 1712 if (psize > (object->size >> 2)) { 1713 objpgs = psize; 1714 1715 for (p = object->memq.tqh_first; 1716 ((objpgs > 0) && (p != NULL)); 1717 p = p->listq.tqe_next) { 1718 1719 tmpidx = p->pindex; 1720 if (tmpidx < pindex) { 1721 continue; 1722 } 1723 tmpidx -= pindex; 1724 if (tmpidx >= psize) { 1725 continue; 1726 } 1727 if (((p->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && 1728 (p->busy == 0) && 1729 (p->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { 1730 if (p->queue == PQ_CACHE) 1731 vm_page_deactivate(p); 1732 vm_page_hold(p); 1733 p->flags |= PG_MAPPED; 1734 pmap_enter_quick(pmap, 1735 addr + (tmpidx << PAGE_SHIFT), 1736 VM_PAGE_TO_PHYS(p)); 1737 vm_page_unhold(p); 1738 } 1739 objpgs -= 1; 1740 } 1741 } else { 1742 /* 1743 * else lookup the pages one-by-one. 1744 */ 1745 for (tmpidx = 0; tmpidx < psize; tmpidx += 1) { 1746 p = vm_page_lookup(object, tmpidx + pindex); 1747 if (p && (p->busy == 0) && 1748 ((p->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && 1749 (p->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { 1750 if (p->queue == PQ_CACHE) 1751 vm_page_deactivate(p); 1752 vm_page_hold(p); 1753 p->flags |= PG_MAPPED; 1754 pmap_enter_quick(pmap, 1755 addr + (tmpidx << PAGE_SHIFT), 1756 VM_PAGE_TO_PHYS(p)); 1757 vm_page_unhold(p); 1758 } 1759 } 1760 } 1761 return; 1762} 1763 1764/* 1765 * pmap_prefault provides a quick way of clustering 1766 * pagefaults into a processes address space. It is a "cousin" 1767 * of pmap_object_init_pt, except it runs at page fault time instead 1768 * of mmap time. 1769 */ 1770#define PFBAK 2 1771#define PFFOR 2 1772#define PAGEORDER_SIZE (PFBAK+PFFOR) 1773 1774static int pmap_prefault_pageorder[] = { 1775 -NBPG, NBPG, -2 * NBPG, 2 * NBPG 1776}; 1777 1778void 1779pmap_prefault(pmap, addra, entry, object) 1780 pmap_t pmap; 1781 vm_offset_t addra; 1782 vm_map_entry_t entry; 1783 vm_object_t object; 1784{ 1785 int i; 1786 vm_offset_t starta; 1787 vm_offset_t addr; 1788 vm_pindex_t pindex; 1789 vm_page_t m; 1790 int pageorder_index; 1791 1792 if (entry->object.vm_object != object) 1793 return; 1794 1795 if (!curproc || (pmap != &curproc->p_vmspace->vm_pmap)) 1796 return; 1797 1798 starta = addra - PFBAK * PAGE_SIZE; 1799 if (starta < entry->start) { 1800 starta = entry->start; 1801 } else if (starta > addra) { 1802 starta = 0; 1803 } 1804 1805 for (i = 0; i < PAGEORDER_SIZE; i++) { 1806 vm_object_t lobject; 1807 pt_entry_t *pte; 1808 1809 addr = addra + pmap_prefault_pageorder[i]; 1810 if (addr < starta || addr >= entry->end) 1811 continue; 1812 1813 pte = vtopte(addr); 1814 if (*pte) 1815 continue; 1816 1817 pindex = ((addr - entry->start) + entry->offset) >> PAGE_SHIFT; 1818 lobject = object; 1819 for (m = vm_page_lookup(lobject, pindex); 1820 (!m && (lobject->type == OBJT_DEFAULT) && (lobject->backing_object)); 1821 lobject = lobject->backing_object) { 1822 if (lobject->backing_object_offset & PAGE_MASK) 1823 break; 1824 pindex += (lobject->backing_object_offset >> PAGE_SHIFT); 1825 m = vm_page_lookup(lobject->backing_object, pindex); 1826 } 1827 1828 /* 1829 * give-up when a page is not in memory 1830 */ 1831 if (m == NULL) 1832 break; 1833 1834 if (((m->valid & VM_PAGE_BITS_ALL) == VM_PAGE_BITS_ALL) && 1835 (m->busy == 0) && 1836 (m->flags & (PG_BUSY | PG_FICTITIOUS)) == 0) { 1837 1838 if (m->queue == PQ_CACHE) { 1839 if ((cnt.v_free_count + cnt.v_cache_count) < 1840 cnt.v_free_min) 1841 break; 1842 vm_page_deactivate(m); 1843 } 1844 vm_page_hold(m); 1845 m->flags |= PG_MAPPED; 1846 pmap_enter_quick(pmap, addr, VM_PAGE_TO_PHYS(m)); 1847 vm_page_unhold(m); 1848 1849 } 1850 } 1851} 1852 1853/* 1854 * Routine: pmap_change_wiring 1855 * Function: Change the wiring attribute for a map/virtual-address 1856 * pair. 1857 * In/out conditions: 1858 * The mapping must already exist in the pmap. 1859 */ 1860void 1861pmap_change_wiring(pmap, va, wired) 1862 register pmap_t pmap; 1863 vm_offset_t va; 1864 boolean_t wired; 1865{ 1866 register pt_entry_t *pte; 1867 1868 if (pmap == NULL) 1869 return; 1870 1871 pte = pmap_pte(pmap, va); 1872 1873 if (wired && !pmap_pte_w(pte)) 1874 pmap->pm_stats.wired_count++; 1875 else if (!wired && pmap_pte_w(pte)) 1876 pmap->pm_stats.wired_count--; 1877 1878 /* 1879 * Wiring is not a hardware characteristic so there is no need to 1880 * invalidate TLB. 1881 */ 1882 pmap_pte_set_w(pte, wired); 1883} 1884 1885 1886 1887/* 1888 * Copy the range specified by src_addr/len 1889 * from the source map to the range dst_addr/len 1890 * in the destination map. 1891 * 1892 * This routine is only advisory and need not do anything. 1893 */ 1894void 1895pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) 1896 pmap_t dst_pmap, src_pmap; 1897 vm_offset_t dst_addr; 1898 vm_size_t len; 1899 vm_offset_t src_addr; 1900{ 1901} 1902 1903/* 1904 * Routine: pmap_kernel 1905 * Function: 1906 * Returns the physical map handle for the kernel. 1907 */ 1908pmap_t 1909pmap_kernel() 1910{ 1911 return (kernel_pmap); 1912} 1913 1914/* 1915 * pmap_zero_page zeros the specified (machine independent) 1916 * page by mapping the page into virtual memory and using 1917 * bzero to clear its contents, one machine dependent page 1918 * at a time. 1919 */ 1920void 1921pmap_zero_page(phys) 1922 vm_offset_t phys; 1923{ 1924 if (*(int *) CMAP2) 1925 panic("pmap_zero_page: CMAP busy"); 1926 1927 *(int *) CMAP2 = PG_V | PG_KW | (phys & PG_FRAME); 1928 bzero(CADDR2, PAGE_SIZE); 1929 1930 *(int *) CMAP2 = 0; 1931 pmap_update_1pg((vm_offset_t) CADDR2); 1932} 1933 1934/* 1935 * pmap_copy_page copies the specified (machine independent) 1936 * page by mapping the page into virtual memory and using 1937 * bcopy to copy the page, one machine dependent page at a 1938 * time. 1939 */ 1940void 1941pmap_copy_page(src, dst) 1942 vm_offset_t src; 1943 vm_offset_t dst; 1944{ 1945 if (*(int *) CMAP1 || *(int *) CMAP2) 1946 panic("pmap_copy_page: CMAP busy"); 1947 1948 *(int *) CMAP1 = PG_V | PG_KW | (src & PG_FRAME); 1949 *(int *) CMAP2 = PG_V | PG_KW | (dst & PG_FRAME); 1950 1951#if __GNUC__ > 1 1952 memcpy(CADDR2, CADDR1, PAGE_SIZE); 1953#else 1954 bcopy(CADDR1, CADDR2, PAGE_SIZE); 1955#endif 1956 *(int *) CMAP1 = 0; 1957 *(int *) CMAP2 = 0; 1958 pmap_update_2pg( (vm_offset_t) CADDR1, (vm_offset_t) CADDR2); 1959} 1960 1961 1962/* 1963 * Routine: pmap_pageable 1964 * Function: 1965 * Make the specified pages (by pmap, offset) 1966 * pageable (or not) as requested. 1967 * 1968 * A page which is not pageable may not take 1969 * a fault; therefore, its page table entry 1970 * must remain valid for the duration. 1971 * 1972 * This routine is merely advisory; pmap_enter 1973 * will specify that these pages are to be wired 1974 * down (or not) as appropriate. 1975 */ 1976void 1977pmap_pageable(pmap, sva, eva, pageable) 1978 pmap_t pmap; 1979 vm_offset_t sva, eva; 1980 boolean_t pageable; 1981{ 1982} 1983 1984/* 1985 * this routine returns true if a physical page resides 1986 * in the given pmap. 1987 */ 1988boolean_t 1989pmap_page_exists(pmap, pa) 1990 pmap_t pmap; 1991 vm_offset_t pa; 1992{ 1993 register pv_entry_t pv; 1994 int s; 1995 1996 if (!pmap_is_managed(pa)) 1997 return FALSE; 1998 1999 pv = pa_to_pvh(pa); 2000 s = splhigh(); 2001 2002 /* 2003 * Not found, check current mappings returning immediately if found. 2004 */ 2005 if (pv->pv_pmap != NULL) { 2006 for (; pv; pv = pv->pv_next) { 2007 if (pv->pv_pmap == pmap) { 2008 splx(s); 2009 return TRUE; 2010 } 2011 } 2012 } 2013 splx(s); 2014 return (FALSE); 2015} 2016 2017/* 2018 * pmap_testbit tests bits in pte's 2019 * note that the testbit/changebit routines are inline, 2020 * and a lot of things compile-time evaluate. 2021 */ 2022static __inline boolean_t 2023pmap_testbit(pa, bit) 2024 register vm_offset_t pa; 2025 int bit; 2026{ 2027 register pv_entry_t pv; 2028 pt_entry_t *pte; 2029 int s; 2030 2031 if (!pmap_is_managed(pa)) 2032 return FALSE; 2033 2034 pv = pa_to_pvh(pa); 2035 s = splhigh(); 2036 2037 /* 2038 * Not found, check current mappings returning immediately if found. 2039 */ 2040 if (pv->pv_pmap != NULL) { 2041 for (; pv; pv = pv->pv_next) { 2042 /* 2043 * if the bit being tested is the modified bit, then 2044 * mark UPAGES as always modified, and ptes as never 2045 * modified. 2046 */ 2047 if (bit & (PG_U|PG_M)) { 2048 if ((pv->pv_va >= clean_sva) && (pv->pv_va < clean_eva)) { 2049 continue; 2050 } 2051 } 2052 if (!pv->pv_pmap) { 2053#if defined(PMAP_DIAGNOSTIC) 2054 printf("Null pmap (tb) at va: 0x%lx\n", pv->pv_va); 2055#endif 2056 continue; 2057 } 2058 pte = pmap_pte(pv->pv_pmap, pv->pv_va); 2059 if ((int) *pte & bit) { 2060 splx(s); 2061 return TRUE; 2062 } 2063 } 2064 } 2065 splx(s); 2066 return (FALSE); 2067} 2068 2069/* 2070 * this routine is used to modify bits in ptes 2071 */ 2072static __inline void 2073pmap_changebit(pa, bit, setem) 2074 vm_offset_t pa; 2075 int bit; 2076 boolean_t setem; 2077{ 2078 register pv_entry_t pv; 2079 register pt_entry_t *pte, npte; 2080 vm_offset_t va; 2081 int changed; 2082 int s; 2083 2084 if (!pmap_is_managed(pa)) 2085 return; 2086 2087 pv = pa_to_pvh(pa); 2088 s = splhigh(); 2089 2090 /* 2091 * Loop over all current mappings setting/clearing as appropos If 2092 * setting RO do we need to clear the VAC? 2093 */ 2094 if (pv->pv_pmap != NULL) { 2095 for (; pv; pv = pv->pv_next) { 2096 va = pv->pv_va; 2097 2098 /* 2099 * don't write protect pager mappings 2100 */ 2101 if (!setem && (bit == PG_RW)) { 2102 if (va >= clean_sva && va < clean_eva) 2103 continue; 2104 } 2105 if (!pv->pv_pmap) { 2106#if defined(PMAP_DIAGNOSTIC) 2107 printf("Null pmap (cb) at va: 0x%lx\n", va); 2108#endif 2109 continue; 2110 } 2111 2112 pte = pmap_pte(pv->pv_pmap, va); 2113 if (setem) { 2114 *(int *)pte |= bit; 2115 } else { 2116 if (bit == PG_RW) { 2117 vm_offset_t pbits = *(vm_offset_t *)pte; 2118 if (pbits & PG_M) { 2119 vm_page_t m; 2120 vm_offset_t pa = pbits & PG_FRAME; 2121 m = PHYS_TO_VM_PAGE(pa); 2122 m->dirty = VM_PAGE_BITS_ALL; 2123 } 2124 *(int *)pte &= ~(PG_M|PG_RW); 2125 } else { 2126 *(int *)pte &= ~bit; 2127 } 2128 } 2129 } 2130 } 2131 splx(s); 2132 pmap_update(); 2133} 2134 2135/* 2136 * pmap_page_protect: 2137 * 2138 * Lower the permission for all mappings to a given page. 2139 */ 2140void 2141pmap_page_protect(phys, prot) 2142 vm_offset_t phys; 2143 vm_prot_t prot; 2144{ 2145 if ((prot & VM_PROT_WRITE) == 0) { 2146 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) 2147 pmap_changebit(phys, PG_RW, FALSE); 2148 else 2149 pmap_remove_all(phys); 2150 } 2151} 2152 2153vm_offset_t 2154pmap_phys_address(ppn) 2155 int ppn; 2156{ 2157 return (i386_ptob(ppn)); 2158} 2159 2160/* 2161 * pmap_is_referenced: 2162 * 2163 * Return whether or not the specified physical page was referenced 2164 * by any physical maps. 2165 */ 2166boolean_t 2167pmap_is_referenced(vm_offset_t pa) 2168{ 2169 return pmap_testbit((pa), PG_U); 2170} 2171 2172/* 2173 * pmap_is_modified: 2174 * 2175 * Return whether or not the specified physical page was modified 2176 * in any physical maps. 2177 */ 2178boolean_t 2179pmap_is_modified(vm_offset_t pa) 2180{ 2181 return pmap_testbit((pa), PG_M); 2182} 2183 2184/* 2185 * Clear the modify bits on the specified physical page. 2186 */ 2187void 2188pmap_clear_modify(vm_offset_t pa) 2189{ 2190 pmap_changebit((pa), PG_M, FALSE); 2191} 2192 2193/* 2194 * pmap_clear_reference: 2195 * 2196 * Clear the reference bit on the specified physical page. 2197 */ 2198void 2199pmap_clear_reference(vm_offset_t pa) 2200{ 2201 pmap_changebit((pa), PG_U, FALSE); 2202} 2203 2204/* 2205 * Miscellaneous support routines follow 2206 */ 2207 2208static void 2209i386_protection_init() 2210{ 2211 register int *kp, prot; 2212 2213 kp = protection_codes; 2214 for (prot = 0; prot < 8; prot++) { 2215 switch (prot) { 2216 case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE: 2217 /* 2218 * Read access is also 0. There isn't any execute bit, 2219 * so just make it readable. 2220 */ 2221 case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE: 2222 case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE: 2223 case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE: 2224 *kp++ = 0; 2225 break; 2226 case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE: 2227 case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE: 2228 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE: 2229 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 2230 *kp++ = PG_RW; 2231 break; 2232 } 2233 } 2234} 2235 2236/* 2237 * Map a set of physical memory pages into the kernel virtual 2238 * address space. Return a pointer to where it is mapped. This 2239 * routine is intended to be used for mapping device memory, 2240 * NOT real memory. The non-cacheable bits are set on each 2241 * mapped page. 2242 */ 2243void * 2244pmap_mapdev(pa, size) 2245 vm_offset_t pa; 2246 vm_size_t size; 2247{ 2248 vm_offset_t va, tmpva; 2249 pt_entry_t *pte; 2250 2251 size = roundup(size, PAGE_SIZE); 2252 2253 va = kmem_alloc_pageable(kernel_map, size); 2254 if (!va) 2255 panic("pmap_mapdev: Couldn't alloc kernel virtual memory"); 2256 2257 pa = pa & PG_FRAME; 2258 for (tmpva = va; size > 0;) { 2259 pte = vtopte(tmpva); 2260 *pte = (pt_entry_t) ((int) (pa | PG_RW | PG_V | PG_N)); 2261 size -= PAGE_SIZE; 2262 tmpva += PAGE_SIZE; 2263 pa += PAGE_SIZE; 2264 } 2265 pmap_update(); 2266 2267 return ((void *) va); 2268} 2269 2270#if defined(PMAP_DEBUG) 2271pmap_pid_dump(int pid) { 2272 pmap_t pmap; 2273 struct proc *p; 2274 int npte = 0; 2275 int index; 2276 for (p = allproc.lh_first; p != NULL; p = p->p_list.le_next) { 2277 if (p->p_pid != pid) 2278 continue; 2279 2280 if (p->p_vmspace) { 2281 int i,j; 2282 index = 0; 2283 pmap = &p->p_vmspace->vm_pmap; 2284 for(i=0;i<1024;i++) { 2285 pd_entry_t *pde; 2286 pt_entry_t *pte; 2287 unsigned base = i << PD_SHIFT; 2288 2289 pde = &pmap->pm_pdir[i]; 2290 if (pde && pmap_pde_v(pde)) { 2291 for(j=0;j<1024;j++) { 2292 unsigned va = base + (j << PG_SHIFT); 2293 if (va >= (vm_offset_t) VM_MIN_KERNEL_ADDRESS) { 2294 if (index) { 2295 index = 0; 2296 printf("\n"); 2297 } 2298 return npte; 2299 } 2300 pte = pmap_pte( pmap, va); 2301 if (pte && pmap_pte_v(pte)) { 2302 vm_offset_t pa; 2303 vm_page_t m; 2304 pa = *(int *)pte; 2305 m = PHYS_TO_VM_PAGE((pa & PG_FRAME)); 2306 printf("va: 0x%x, pt: 0x%x, h: %d, w: %d, f: 0x%x", 2307 va, pa, m->hold_count, m->wire_count, m->flags); 2308 npte++; 2309 index++; 2310 if (index >= 2) { 2311 index = 0; 2312 printf("\n"); 2313 } else { 2314 printf(" "); 2315 } 2316 } 2317 } 2318 } 2319 } 2320 } 2321 } 2322 return npte; 2323} 2324#endif 2325 2326#if defined(DEBUG) 2327 2328static void pads __P((pmap_t pm)); 2329static void pmap_pvdump __P((vm_offset_t pa)); 2330 2331/* print address space of pmap*/ 2332static void 2333pads(pm) 2334 pmap_t pm; 2335{ 2336 unsigned va, i, j; 2337 pt_entry_t *ptep; 2338 2339 if (pm == kernel_pmap) 2340 return; 2341 for (i = 0; i < 1024; i++) 2342 if (pm->pm_pdir[i]) 2343 for (j = 0; j < 1024; j++) { 2344 va = (i << PD_SHIFT) + (j << PG_SHIFT); 2345 if (pm == kernel_pmap && va < KERNBASE) 2346 continue; 2347 if (pm != kernel_pmap && va > UPT_MAX_ADDRESS) 2348 continue; 2349 ptep = pmap_pte(pm, va); 2350 if (pmap_pte_v(ptep)) 2351 printf("%x:%x ", va, *(int *) ptep); 2352 }; 2353 2354} 2355 2356static void 2357pmap_pvdump(pa) 2358 vm_offset_t pa; 2359{ 2360 register pv_entry_t pv; 2361 2362 printf("pa %x", pa); 2363 for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next) { 2364#ifdef used_to_be 2365 printf(" -> pmap %x, va %x, flags %x", 2366 pv->pv_pmap, pv->pv_va, pv->pv_flags); 2367#endif 2368 printf(" -> pmap %x, va %x", 2369 pv->pv_pmap, pv->pv_va); 2370 pads(pv->pv_pmap); 2371 } 2372 printf(" "); 2373} 2374#endif 2375