pmap.c revision 1887
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.27 1994/08/03 02:45:28 davidg 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 * Major modifications by John S. Dyson primarily to support 56 * pageable page tables, eliminating pmap_attributes, 57 * discontiguous memory pages, and using more efficient string 58 * instructions. Jan 13, 1994. Further modifications on Mar 2, 1994, 59 * general clean-up and efficiency mods. 60 */ 61 62/* 63 * Manages physical address maps. 64 * 65 * In addition to hardware address maps, this 66 * module is called upon to provide software-use-only 67 * maps which may or may not be stored in the same 68 * form as hardware maps. These pseudo-maps are 69 * used to store intermediate results from copy 70 * operations to and from address spaces. 71 * 72 * Since the information managed by this module is 73 * also stored by the logical address mapping module, 74 * this module may throw away valid virtual-to-physical 75 * mappings at almost any time. However, invalidations 76 * of virtual-to-physical mappings must be done as 77 * requested. 78 * 79 * In order to cope with hardware architectures which 80 * make virtual-to-physical map invalidates expensive, 81 * this module may delay invalidate or reduced protection 82 * operations until such time as they are actually 83 * necessary. This module is given full information as 84 * to which processors are currently using which maps, 85 * and to when physical maps must be made correct. 86 */ 87 88#include <sys/param.h> 89#include <sys/proc.h> 90#include <sys/malloc.h> 91#include <sys/user.h> 92 93#include <vm/vm.h> 94#include <vm/vm_kern.h> 95#include <vm/vm_page.h> 96 97#include <i386/include/cpufunc.h> 98#include <i386/include/cputypes.h> 99 100#include <i386/isa/isa.h> 101 102/* 103 * Allocate various and sundry SYSMAPs used in the days of old VM 104 * and not yet converted. XXX. 105 */ 106#define BSDVM_COMPAT 1 107 108/* 109 * Get PDEs and PTEs for user/kernel address space 110 */ 111#define pmap_pde(m, v) (&((m)->pm_pdir[((vm_offset_t)(v) >> PD_SHIFT)&1023])) 112#define pdir_pde(m, v) (m[((vm_offset_t)(v) >> PD_SHIFT)&1023]) 113 114#define pmap_pte_pa(pte) (*(int *)(pte) & PG_FRAME) 115 116#define pmap_pde_v(pte) ((*(int *)pte & PG_V) != 0) 117#define pmap_pte_w(pte) ((*(int *)pte & PG_W) != 0) 118#define pmap_pte_m(pte) ((*(int *)pte & PG_M) != 0) 119#define pmap_pte_u(pte) ((*(int *)pte & PG_U) != 0) 120#define pmap_pte_v(pte) ((*(int *)pte & PG_V) != 0) 121 122#define pmap_pte_set_w(pte, v) ((v)?(*(int *)pte |= PG_W):(*(int *)pte &= ~PG_W)) 123#define pmap_pte_set_prot(pte, v) ((*(int *)pte &= ~PG_PROT), (*(int *)pte |= (v))) 124 125/* 126 * Given a map and a machine independent protection code, 127 * convert to a vax protection code. 128 */ 129#define pte_prot(m, p) (protection_codes[p]) 130int protection_codes[8]; 131 132struct pmap kernel_pmap_store; 133pmap_t kernel_pmap; 134 135vm_offset_t phys_avail[6]; /* 2 entries + 1 null */ 136vm_offset_t avail_start; /* PA of first available physical page */ 137vm_offset_t avail_end; /* PA of last available physical page */ 138vm_size_t mem_size; /* memory size in bytes */ 139vm_offset_t virtual_avail; /* VA of first avail page (after kernel bss)*/ 140vm_offset_t virtual_end; /* VA of last avail page (end of kernel AS) */ 141int i386pagesperpage; /* PAGE_SIZE / I386_PAGE_SIZE */ 142boolean_t pmap_initialized = FALSE; /* Has pmap_init completed? */ 143vm_offset_t vm_first_phys, vm_last_phys; 144 145static inline boolean_t pmap_testbit(); 146static inline void pmap_changebit(); 147static inline int pmap_is_managed(); 148static inline void *vm_get_pmap(); 149static inline void vm_put_pmap(); 150inline void pmap_use_pt(); 151inline void pmap_unuse_pt(); 152inline pt_entry_t * pmap_pte(); 153static inline pv_entry_t get_pv_entry(); 154void pmap_alloc_pv_entry(); 155void pmap_clear_modify(); 156static void i386_protection_init(); 157 158void pmap_kenter __P((vm_offset_t, vm_offset_t)); 159void pmap_kremove __P((vm_offset_t)); 160void pmap_qenter __P((vm_offset_t, vm_page_t *, int)); 161void pmap_qremove __P((vm_offset_t, int)); 162 163extern vm_offset_t clean_sva, clean_eva; 164extern int cpu_class; 165 166#if BSDVM_COMPAT 167#include "msgbuf.h" 168 169/* 170 * All those kernel PT submaps that BSD is so fond of 171 */ 172pt_entry_t *CMAP1, *CMAP2, *ptmmap; 173caddr_t CADDR1, CADDR2, ptvmmap; 174pt_entry_t *msgbufmap; 175struct msgbuf *msgbufp; 176#endif 177 178void init_pv_entries(int) ; 179 180/* 181 * Routine: pmap_pte 182 * Function: 183 * Extract the page table entry associated 184 * with the given map/virtual_address pair. 185 * [ what about induced faults -wfj] 186 */ 187 188inline pt_entry_t * 189const pmap_pte(pmap, va) 190 register pmap_t pmap; 191 vm_offset_t va; 192{ 193 194 if (pmap && *pmap_pde(pmap, va)) { 195 vm_offset_t frame = (int) pmap->pm_pdir[PTDPTDI] & PG_FRAME; 196 /* are we current address space or kernel? */ 197 if ( (pmap == kernel_pmap) || (frame == ((int) PTDpde & PG_FRAME))) 198 return ((pt_entry_t *) vtopte(va)); 199 /* otherwise, we are alternate address space */ 200 else { 201 if ( frame != ((int) APTDpde & PG_FRAME) ) { 202 APTDpde = pmap->pm_pdir[PTDPTDI]; 203 tlbflush(); 204 } 205 return((pt_entry_t *) avtopte(va)); 206 } 207 } 208 return(0); 209} 210 211/* 212 * Routine: pmap_extract 213 * Function: 214 * Extract the physical page address associated 215 * with the given map/virtual_address pair. 216 */ 217 218vm_offset_t 219pmap_extract(pmap, va) 220 register pmap_t pmap; 221 vm_offset_t va; 222{ 223 pd_entry_t save; 224 vm_offset_t pa; 225 int s; 226 227 if (pmap && *pmap_pde(pmap, va)) { 228 vm_offset_t frame = (int) pmap->pm_pdir[PTDPTDI] & PG_FRAME; 229 /* are we current address space or kernel? */ 230 if ( (pmap == kernel_pmap) 231 || (frame == ((int) PTDpde & PG_FRAME)) ) { 232 pa = *(int *) vtopte(va); 233 /* otherwise, we are alternate address space */ 234 } else { 235 if ( frame != ((int) APTDpde & PG_FRAME)) { 236 APTDpde = pmap->pm_pdir[PTDPTDI]; 237 tlbflush(); 238 } 239 pa = *(int *) avtopte(va); 240 } 241 pa = (pa & PG_FRAME) | (va & ~PG_FRAME); 242 return pa; 243 } 244 return 0; 245 246} 247 248/* 249 * determine if a page is managed (memory vs. device) 250 */ 251static inline int 252pmap_is_managed(pa) 253 vm_offset_t pa; 254{ 255 int i; 256 257 if (!pmap_initialized) 258 return 0; 259 260 for (i = 0; phys_avail[i + 1]; i += 2) { 261 if (pa >= phys_avail[i] && pa < phys_avail[i + 1]) 262 return 1; 263 } 264 return 0; 265} 266 267/* 268 * find the vm_page_t of a pte (only) given va of pte and pmap 269 */ 270inline vm_page_t 271pmap_pte_vm_page(pmap, pt) 272 pmap_t pmap; 273 vm_offset_t pt; 274{ 275 pt = i386_trunc_page( pt); 276 pt = (pt - UPT_MIN_ADDRESS) / NBPG; 277 pt = ((vm_offset_t) pmap->pm_pdir[pt]) & PG_FRAME; 278 return PHYS_TO_VM_PAGE(pt); 279} 280 281/* 282 * Wire a page table page 283 */ 284inline void 285pmap_use_pt(pmap, va) 286 pmap_t pmap; 287 vm_offset_t va; 288{ 289 vm_offset_t pt; 290 291 if (va >= VM_MAX_ADDRESS || !pmap_initialized) 292 return; 293 294 pt = (vm_offset_t) vtopte(va); 295 vm_page_hold( pmap_pte_vm_page(pmap, pt)); 296} 297 298/* 299 * Unwire a page table page 300 */ 301inline void 302pmap_unuse_pt(pmap, va) 303 pmap_t pmap; 304 vm_offset_t va; 305{ 306 vm_offset_t pt; 307 308 if (va >= VM_MAX_ADDRESS || !pmap_initialized) 309 return; 310 311 pt = (vm_offset_t) vtopte(va); 312 vm_page_unhold( pmap_pte_vm_page(pmap, pt)); 313} 314 315/* [ macro again?, should I force kstack into user map here? -wfj ] */ 316void 317pmap_activate(pmap, pcbp) 318 register pmap_t pmap; 319 struct pcb *pcbp; 320{ 321 PMAP_ACTIVATE(pmap, pcbp); 322} 323 324/* 325 * Bootstrap the system enough to run with virtual memory. 326 * Map the kernel's code and data, and allocate the system page table. 327 * 328 * On the I386 this is called after mapping has already been enabled 329 * and just syncs the pmap module with what has already been done. 330 * [We can't call it easily with mapping off since the kernel is not 331 * mapped with PA == VA, hence we would have to relocate every address 332 * from the linked base (virtual) address "KERNBASE" to the actual 333 * (physical) address starting relative to 0] 334 */ 335 336#define DMAPAGES 8 337void 338pmap_bootstrap(firstaddr, loadaddr) 339 vm_offset_t firstaddr; 340 vm_offset_t loadaddr; 341{ 342#if BSDVM_COMPAT 343 vm_offset_t va; 344 pt_entry_t *pte; 345#endif 346 extern int IdlePTD; 347 348 avail_start = firstaddr + DMAPAGES*NBPG; 349 350 virtual_avail = (vm_offset_t) KERNBASE + avail_start; 351 virtual_end = VM_MAX_KERNEL_ADDRESS; 352 i386pagesperpage = PAGE_SIZE / NBPG; 353 354 /* 355 * Initialize protection array. 356 */ 357 i386_protection_init(); 358 359 /* 360 * The kernel's pmap is statically allocated so we don't 361 * have to use pmap_create, which is unlikely to work 362 * correctly at this part of the boot sequence. 363 */ 364 kernel_pmap = &kernel_pmap_store; 365 366 kernel_pmap->pm_pdir = (pd_entry_t *)(KERNBASE + IdlePTD); 367 368 simple_lock_init(&kernel_pmap->pm_lock); 369 kernel_pmap->pm_count = 1; 370 371#if BSDVM_COMPAT 372 /* 373 * Allocate all the submaps we need 374 */ 375#define SYSMAP(c, p, v, n) \ 376 v = (c)va; va += ((n)*NBPG); p = pte; pte += (n); 377 378 va = virtual_avail; 379 pte = pmap_pte(kernel_pmap, va); 380 381 SYSMAP(caddr_t ,CMAP1 ,CADDR1 ,1 ) 382 SYSMAP(caddr_t ,CMAP2 ,CADDR2 ,1 ) 383 SYSMAP(caddr_t ,ptmmap ,ptvmmap ,1 ) 384 SYSMAP(struct msgbuf * ,msgbufmap ,msgbufp ,1 ) 385 virtual_avail = va; 386#endif 387 /* 388 * reserve special hunk of memory for use by bus dma as a bounce 389 * buffer (contiguous virtual *and* physical memory). for now, 390 * assume vm does not use memory beneath hole, and we know that 391 * the bootstrap uses top 32k of base memory. -wfj 392 */ 393 { 394 extern vm_offset_t isaphysmem; 395 isaphysmem = va; 396 397 virtual_avail = pmap_map(va, firstaddr, 398 firstaddr + DMAPAGES*NBPG, VM_PROT_ALL); 399 } 400 401 *(int *)CMAP1 = *(int *)CMAP2 = *(int *)PTD = 0; 402 tlbflush(); 403 404} 405 406/* 407 * Initialize the pmap module. 408 * Called by vm_init, to initialize any structures that the pmap 409 * system needs to map virtual memory. 410 * pmap_init has been enhanced to support in a fairly consistant 411 * way, discontiguous physical memory. 412 */ 413void 414pmap_init(phys_start, phys_end) 415 vm_offset_t phys_start, phys_end; 416{ 417 vm_offset_t addr, addr2; 418 vm_size_t npg, s; 419 int rv; 420 int i; 421 extern int KPTphys; 422 extern int IdlePTD; 423 424 /* 425 * Now that kernel map has been allocated, we can mark as 426 * unavailable regions which we have mapped in locore. 427 */ 428 addr = atdevbase; 429 (void) vm_map_find(kernel_map, NULL, (vm_offset_t) 0, 430 &addr, (0x100000-0xa0000), FALSE); 431 432 addr = (vm_offset_t) KERNBASE + IdlePTD; 433 vm_object_reference(kernel_object); 434 (void) vm_map_find(kernel_map, kernel_object, addr, 435 &addr, (4 + NKPT) * NBPG, FALSE); 436 437 438 /* 439 * calculate the number of pv_entries needed 440 */ 441 vm_first_phys = phys_avail[0]; 442 for (i = 0; phys_avail[i + 1]; i += 2) ; 443 npg = (phys_avail[(i - 2) + 1] - vm_first_phys) / NBPG; 444 445 /* 446 * Allocate memory for random pmap data structures. Includes the 447 * pv_head_table. 448 */ 449 s = (vm_size_t) (sizeof(struct pv_entry) * npg); 450 s = i386_round_page(s); 451 addr = (vm_offset_t) kmem_alloc(kernel_map, s); 452 pv_table = (pv_entry_t) addr; 453 454 /* 455 * init the pv free list 456 */ 457 init_pv_entries(npg); 458 /* 459 * Now it is safe to enable pv_table recording. 460 */ 461 pmap_initialized = TRUE; 462} 463 464/* 465 * Used to map a range of physical addresses into kernel 466 * virtual address space. 467 * 468 * For now, VM is already on, we only need to map the 469 * specified memory. 470 */ 471vm_offset_t 472pmap_map(virt, start, end, prot) 473 vm_offset_t virt; 474 vm_offset_t start; 475 vm_offset_t end; 476 int prot; 477{ 478 while (start < end) { 479 pmap_enter(kernel_pmap, virt, start, prot, FALSE); 480 virt += PAGE_SIZE; 481 start += PAGE_SIZE; 482 } 483 return(virt); 484} 485 486/* 487 * Create and return a physical map. 488 * 489 * If the size specified for the map 490 * is zero, the map is an actual physical 491 * map, and may be referenced by the 492 * hardware. 493 * 494 * If the size specified is non-zero, 495 * the map will be used in software only, and 496 * is bounded by that size. 497 * 498 * [ just allocate a ptd and mark it uninitialize -- should we track 499 * with a table which process has which ptd? -wfj ] 500 */ 501 502pmap_t 503pmap_create(size) 504 vm_size_t size; 505{ 506 register pmap_t pmap; 507 508 /* 509 * Software use map does not need a pmap 510 */ 511 if (size) 512 return(NULL); 513 514 pmap = (pmap_t) malloc(sizeof *pmap, M_VMPMAP, M_WAITOK); 515 bzero(pmap, sizeof(*pmap)); 516 pmap_pinit(pmap); 517 return (pmap); 518} 519 520 521struct pmaplist { 522 struct pmaplist *next; 523}; 524 525static inline void * 526vm_get_pmap() 527{ 528 struct pmaplist *rtval; 529 530 rtval = (struct pmaplist *)kmem_alloc(kernel_map, ctob(1)); 531 bzero(rtval, ctob(1)); 532 return rtval; 533} 534 535static inline void 536vm_put_pmap(up) 537 struct pmaplist *up; 538{ 539 kmem_free(kernel_map, (vm_offset_t)up, ctob(1)); 540} 541 542/* 543 * Initialize a preallocated and zeroed pmap structure, 544 * such as one in a vmspace structure. 545 */ 546void 547pmap_pinit(pmap) 548 register struct pmap *pmap; 549{ 550 /* 551 * No need to allocate page table space yet but we do need a 552 * valid page directory table. 553 */ 554 pmap->pm_pdir = (pd_entry_t *) vm_get_pmap(); 555 556 /* wire in kernel global address entries */ 557 bcopy(PTD+KPTDI, pmap->pm_pdir+KPTDI, NKPT*PTESIZE); 558 559 /* install self-referential address mapping entry */ 560 *(int *)(pmap->pm_pdir+PTDPTDI) = 561 ((int)pmap_kextract((vm_offset_t)pmap->pm_pdir)) | PG_V | PG_KW; 562 563 pmap->pm_count = 1; 564 simple_lock_init(&pmap->pm_lock); 565} 566 567/* 568 * Retire the given physical map from service. 569 * Should only be called if the map contains 570 * no valid mappings. 571 */ 572void 573pmap_destroy(pmap) 574 register pmap_t pmap; 575{ 576 int count; 577 578 if (pmap == NULL) 579 return; 580 581 simple_lock(&pmap->pm_lock); 582 count = --pmap->pm_count; 583 simple_unlock(&pmap->pm_lock); 584 if (count == 0) { 585 pmap_release(pmap); 586 free((caddr_t)pmap, M_VMPMAP); 587 } 588} 589 590/* 591 * Release any resources held by the given physical map. 592 * Called when a pmap initialized by pmap_pinit is being released. 593 * Should only be called if the map contains no valid mappings. 594 */ 595void 596pmap_release(pmap) 597 register struct pmap *pmap; 598{ 599 vm_put_pmap((struct pmaplist *) pmap->pm_pdir); 600} 601 602/* 603 * Add a reference to the specified pmap. 604 */ 605void 606pmap_reference(pmap) 607 pmap_t pmap; 608{ 609 if (pmap != NULL) { 610 simple_lock(&pmap->pm_lock); 611 pmap->pm_count++; 612 simple_unlock(&pmap->pm_lock); 613 } 614} 615 616#define PV_FREELIST_MIN ((NBPG / sizeof (struct pv_entry)) / 2) 617 618/* 619 * Data for the pv entry allocation mechanism 620 */ 621int pv_freelistcnt; 622pv_entry_t pv_freelist; 623vm_offset_t pvva; 624int npvvapg; 625 626/* 627 * free the pv_entry back to the free list 628 */ 629inline static void 630free_pv_entry(pv) 631 pv_entry_t pv; 632{ 633 if (!pv) return; 634 ++pv_freelistcnt; 635 pv->pv_next = pv_freelist; 636 pv_freelist = pv; 637} 638 639/* 640 * get a new pv_entry, allocating a block from the system 641 * when needed. 642 * the memory allocation is performed bypassing the malloc code 643 * because of the possibility of allocations at interrupt time. 644 */ 645static inline pv_entry_t 646get_pv_entry() 647{ 648 pv_entry_t tmp; 649 650 /* 651 * get more pv_entry pages if needed 652 */ 653 while (pv_freelistcnt < PV_FREELIST_MIN || pv_freelist == 0) { 654 pmap_alloc_pv_entry(); 655 } 656 657 /* 658 * get a pv_entry off of the free list 659 */ 660 --pv_freelistcnt; 661 tmp = pv_freelist; 662 pv_freelist = tmp->pv_next; 663 tmp->pv_pmap = 0; 664 tmp->pv_va = 0; 665 tmp->pv_next = 0; 666 return tmp; 667} 668 669/* 670 * this *strange* allocation routine *statistically* eliminates the 671 * *possibility* of a malloc failure (*FATAL*) for a pv_entry_t data structure. 672 * also -- this code is MUCH MUCH faster than the malloc equiv... 673 */ 674void 675pmap_alloc_pv_entry() 676{ 677 /* 678 * do we have any pre-allocated map-pages left? 679 */ 680 if (npvvapg) { 681 vm_page_t m; 682 /* 683 * we do this to keep recursion away 684 */ 685 pv_freelistcnt += PV_FREELIST_MIN; 686 /* 687 * allocate a physical page out of the vm system 688 */ 689 if (m = vm_page_alloc(kernel_object, pvva-vm_map_min(kernel_map))) { 690 int newentries; 691 int i; 692 pv_entry_t entry; 693 newentries = (NBPG/sizeof (struct pv_entry)); 694 /* 695 * wire the page 696 */ 697 vm_page_wire(m); 698 m->flags &= ~PG_BUSY; 699 /* 700 * let the kernel see it 701 */ 702 pmap_kenter(pvva, VM_PAGE_TO_PHYS(m)); 703 704 entry = (pv_entry_t) pvva; 705 /* 706 * update the allocation pointers 707 */ 708 pvva += NBPG; 709 --npvvapg; 710 711 /* 712 * free the entries into the free list 713 */ 714 for (i = 0; i < newentries; i++) { 715 free_pv_entry(entry); 716 entry++; 717 } 718 } 719 pv_freelistcnt -= PV_FREELIST_MIN; 720 } 721 if (!pv_freelist) 722 panic("get_pv_entry: cannot get a pv_entry_t"); 723} 724 725 726 727/* 728 * init the pv_entry allocation system 729 */ 730#define PVSPERPAGE 64 731void 732init_pv_entries(npg) 733 int npg; 734{ 735 /* 736 * allocate enough kvm space for PVSPERPAGE entries per page (lots) 737 * kvm space is fairly cheap, be generous!!! (the system can panic 738 * if this is too small.) 739 */ 740 npvvapg = ((npg*PVSPERPAGE) * sizeof(struct pv_entry) + NBPG - 1)/NBPG; 741 pvva = kmem_alloc_pageable(kernel_map, npvvapg * NBPG); 742 /* 743 * get the first batch of entries 744 */ 745 free_pv_entry(get_pv_entry()); 746} 747 748static pt_entry_t * 749get_pt_entry(pmap) 750 pmap_t pmap; 751{ 752 pt_entry_t *ptp; 753 vm_offset_t frame = (int) pmap->pm_pdir[PTDPTDI] & PG_FRAME; 754 /* are we current address space or kernel? */ 755 if (pmap == kernel_pmap || frame == ((int) PTDpde & PG_FRAME)) { 756 ptp=PTmap; 757 /* otherwise, we are alternate address space */ 758 } else { 759 if ( frame != ((int) APTDpde & PG_FRAME)) { 760 APTDpde = pmap->pm_pdir[PTDPTDI]; 761 tlbflush(); 762 } 763 ptp=APTmap; 764 } 765 return ptp; 766} 767 768/* 769 * If it is the first entry on the list, it is actually 770 * in the header and we must copy the following entry up 771 * to the header. Otherwise we must search the list for 772 * the entry. In either case we free the now unused entry. 773 */ 774void 775pmap_remove_entry(pmap, pv, va) 776 struct pmap *pmap; 777 pv_entry_t pv; 778 vm_offset_t va; 779{ 780 pv_entry_t npv; 781 int wired; 782 int s; 783 s = splhigh(); 784 if (pmap == pv->pv_pmap && va == pv->pv_va) { 785 npv = pv->pv_next; 786 if (npv) { 787 *pv = *npv; 788 free_pv_entry(npv); 789 } else { 790 pv->pv_pmap = NULL; 791 } 792 } else { 793 for (npv = pv->pv_next; npv; npv = npv->pv_next) { 794 if (pmap == npv->pv_pmap && va == npv->pv_va) { 795 break; 796 } 797 pv = npv; 798 } 799 if (npv) { 800 pv->pv_next = npv->pv_next; 801 free_pv_entry(npv); 802 } 803 } 804 splx(s); 805} 806 807/* 808 * Remove the given range of addresses from the specified map. 809 * 810 * It is assumed that the start and end are properly 811 * rounded to the page size. 812 */ 813void 814pmap_remove(pmap, sva, eva) 815 struct pmap *pmap; 816 register vm_offset_t sva; 817 register vm_offset_t eva; 818{ 819 register pt_entry_t *ptp,*ptq; 820 vm_offset_t pa; 821 register pv_entry_t pv; 822 vm_offset_t va; 823 vm_page_t m; 824 pt_entry_t oldpte; 825 826 if (pmap == NULL) 827 return; 828 829 ptp = get_pt_entry(pmap); 830 831/* 832 * special handling of removing one page. a very 833 * common operation and easy to short circuit some 834 * code. 835 */ 836 if( (sva + NBPG) == eva) { 837 838 if( *pmap_pde( pmap, sva) == 0) 839 return; 840 841 ptq = ptp + i386_btop(sva); 842 843 if( !*ptq) 844 return; 845 /* 846 * Update statistics 847 */ 848 if (pmap_pte_w(ptq)) 849 pmap->pm_stats.wired_count--; 850 pmap->pm_stats.resident_count--; 851 852 pa = pmap_pte_pa(ptq); 853 oldpte = *ptq; 854 *ptq = 0; 855 856 if (pmap_is_managed(pa)) { 857 if ((int) oldpte & (PG_M | PG_U)) { 858 if ((sva < USRSTACK || sva > UPT_MAX_ADDRESS) || 859 (sva >= USRSTACK && sva < USRSTACK+(UPAGES*NBPG))) { 860 if (sva < clean_sva || sva >= clean_eva) { 861 m = PHYS_TO_VM_PAGE(pa); 862 if ((int) oldpte & PG_M) { 863 m->flags &= ~PG_CLEAN; 864 } 865 if ((int) oldpte & PG_U) { 866 m->flags |= PG_REFERENCED; 867 } 868 } 869 } 870 } 871 872 pv = pa_to_pvh(pa); 873 pmap_remove_entry(pmap, pv, sva); 874 pmap_unuse_pt(pmap, sva); 875 } 876 tlbflush(); 877 return; 878 } 879 880 sva = i386_btop(sva); 881 eva = i386_btop(eva); 882 883 while (sva < eva) { 884 /* 885 * Weed out invalid mappings. 886 * Note: we assume that the page directory table is 887 * always allocated, and in kernel virtual. 888 */ 889 890 if ( *pmap_pde(pmap, i386_ptob(sva)) == 0 ) { 891 /* We can race ahead here, straight to next pde.. */ 892 nextpde: 893 sva = ((sva + NPTEPG) & ~(NPTEPG - 1)); 894 continue; 895 } 896 897 ptq = ptp + sva; 898 899 /* 900 * search for page table entries, use string operations 901 * that are much faster than 902 * explicitly scanning when page tables are not fully 903 * populated. 904 */ 905 if ( *ptq == 0) { 906 vm_offset_t pdnxt = ((sva + NPTEPG) & ~(NPTEPG - 1)); 907 vm_offset_t nscan = pdnxt - sva; 908 int found = 0; 909 910 if ((nscan + sva) > eva) 911 nscan = eva - sva; 912 913 asm("xorl %%eax,%%eax;cld;repe;scasl;jz 1f;incl %%eax;1:;" 914 :"=D"(ptq),"=a"(found) 915 :"c"(nscan),"0"(ptq) 916 :"cx"); 917 918 if( !found) { 919 sva = pdnxt; 920 continue; 921 } 922 ptq -= 1; 923 924 sva = ptq - ptp; 925 } 926 927 /* 928 * Update statistics 929 */ 930 oldpte = *ptq; 931 if (((int)oldpte) & PG_W) 932 pmap->pm_stats.wired_count--; 933 pmap->pm_stats.resident_count--; 934 935 /* 936 * Invalidate the PTEs. 937 * XXX: should cluster them up and invalidate as many 938 * as possible at once. 939 */ 940 *ptq = 0; 941 942 va = i386_ptob(sva); 943 944 /* 945 * Remove from the PV table (raise IPL since we 946 * may be called at interrupt time). 947 */ 948 pa = ((int)oldpte) & PG_FRAME; 949 if (!pmap_is_managed(pa)) { 950 ++sva; 951 continue; 952 } 953 954 if ((((int) oldpte & PG_M) && (va < USRSTACK || va > UPT_MAX_ADDRESS)) 955 || (va >= USRSTACK && va < USRSTACK+(UPAGES*NBPG))) { 956 if (va < clean_sva || va >= clean_eva ) { 957 m = PHYS_TO_VM_PAGE(pa); 958 m->flags &= ~PG_CLEAN; 959 } 960 } 961 962 pv = pa_to_pvh(pa); 963 pmap_remove_entry(pmap, pv, va); 964 pmap_unuse_pt(pmap, va); 965 ++sva; 966 } 967 tlbflush(); 968} 969 970/* 971 * Routine: pmap_remove_all 972 * Function: 973 * Removes this physical page from 974 * all physical maps in which it resides. 975 * Reflects back modify bits to the pager. 976 * 977 * Notes: 978 * Original versions of this routine were very 979 * inefficient because they iteratively called 980 * pmap_remove (slow...) 981 */ 982void 983pmap_remove_all(pa) 984 vm_offset_t pa; 985{ 986 register pv_entry_t pv, npv; 987 register pt_entry_t *pte, *ptp; 988 vm_offset_t va; 989 struct pmap *pmap; 990 struct map *map; 991 vm_page_t m; 992 int s; 993 int anyvalid = 0; 994 995 /* 996 * Not one of ours 997 */ 998 if (!pmap_is_managed(pa)) 999 return; 1000 1001 pa = i386_trunc_page(pa); 1002 pv = pa_to_pvh(pa); 1003 m = PHYS_TO_VM_PAGE(pa); 1004 1005 s = splhigh(); 1006 while (pv->pv_pmap != NULL) { 1007 pmap = pv->pv_pmap; 1008 ptp = get_pt_entry(pmap); 1009 va = i386_btop(pv->pv_va); 1010 pte = ptp + va; 1011 if (pmap_pte_w(pte)) 1012 pmap->pm_stats.wired_count--; 1013 if ( *pte) { 1014 pmap->pm_stats.resident_count--; 1015 anyvalid++; 1016 1017 /* 1018 * update the vm_page_t clean bit 1019 */ 1020 if ( (m->flags & PG_CLEAN) && 1021 ((((int) *pte) & PG_M) && (pv->pv_va < USRSTACK || pv->pv_va > UPT_MAX_ADDRESS)) 1022 || (pv->pv_va >= USRSTACK && pv->pv_va < USRSTACK+(UPAGES*NBPG))) { 1023 if (pv->pv_va < clean_sva || pv->pv_va >= clean_eva) { 1024 m->flags &= ~PG_CLEAN; 1025 } 1026 } 1027 1028 *pte = 0; 1029 } 1030 pmap_unuse_pt(pmap, pv->pv_va); 1031 1032 npv = pv->pv_next; 1033 if (npv) { 1034 *pv = *npv; 1035 free_pv_entry(npv); 1036 } else { 1037 pv->pv_pmap = NULL; 1038 } 1039 } 1040 splx(s); 1041 if (anyvalid) 1042 tlbflush(); 1043} 1044 1045 1046/* 1047 * Set the physical protection on the 1048 * specified range of this map as requested. 1049 */ 1050void 1051pmap_protect(pmap, sva, eva, prot) 1052 register pmap_t pmap; 1053 vm_offset_t sva, eva; 1054 vm_prot_t prot; 1055{ 1056 register pt_entry_t *pte; 1057 register vm_offset_t va; 1058 int i386prot; 1059 register pt_entry_t *ptp; 1060 int evap = i386_btop(eva); 1061 int s; 1062 int anyvalid = 0;; 1063 1064 if (pmap == NULL) 1065 return; 1066 1067 if ((prot & VM_PROT_READ) == VM_PROT_NONE) { 1068 pmap_remove(pmap, sva, eva); 1069 return; 1070 } 1071 if (prot & VM_PROT_WRITE) 1072 return; 1073 1074 ptp = get_pt_entry(pmap); 1075 1076 va = sva; 1077 while (va < eva) { 1078 int found=0; 1079 int svap; 1080 vm_offset_t nscan; 1081 /* 1082 * Page table page is not allocated. 1083 * Skip it, we don't want to force allocation 1084 * of unnecessary PTE pages just to set the protection. 1085 */ 1086 if (! *pmap_pde(pmap, va)) { 1087 /* XXX: avoid address wrap around */ 1088nextpde: 1089 if (va >= i386_trunc_pdr((vm_offset_t)-1)) 1090 break; 1091 va = i386_round_pdr(va + PAGE_SIZE); 1092 continue; 1093 } 1094 1095 pte = ptp + i386_btop(va); 1096 1097 if( *pte == 0) { 1098 /* 1099 * scan for a non-empty pte 1100 */ 1101 svap = pte - ptp; 1102 nscan = ((svap + NPTEPG) & ~(NPTEPG - 1)) - svap; 1103 1104 if (nscan + svap > evap) 1105 nscan = evap - svap; 1106 1107 found = 0; 1108 if (nscan) 1109 asm("xorl %%eax,%%eax;cld;repe;scasl;jz 1f;incl %%eax;1:;" 1110 :"=D"(pte),"=a"(found) 1111 :"c"(nscan),"0"(pte):"cx"); 1112 1113 if( !found) 1114 goto nextpde; 1115 1116 pte -= 1; 1117 svap = pte - ptp; 1118 1119 va = i386_ptob(svap); 1120 } 1121 1122 anyvalid++; 1123 1124 i386prot = pte_prot(pmap, prot); 1125 if (va < UPT_MAX_ADDRESS) { 1126 i386prot |= PG_u; 1127 if( va >= UPT_MIN_ADDRESS) 1128 i386prot |= PG_RW; 1129 } 1130 pmap_pte_set_prot(pte, i386prot); 1131 va += PAGE_SIZE; 1132 } 1133 if (anyvalid) 1134 tlbflush(); 1135} 1136 1137/* 1138 * Insert the given physical page (p) at 1139 * the specified virtual address (v) in the 1140 * target physical map with the protection requested. 1141 * 1142 * If specified, the page will be wired down, meaning 1143 * that the related pte can not be reclaimed. 1144 * 1145 * NB: This is the only routine which MAY NOT lazy-evaluate 1146 * or lose information. That is, this routine must actually 1147 * insert this page into the given map NOW. 1148 */ 1149void 1150pmap_enter(pmap, va, pa, prot, wired) 1151 register pmap_t pmap; 1152 vm_offset_t va; 1153 register vm_offset_t pa; 1154 vm_prot_t prot; 1155 boolean_t wired; 1156{ 1157 register pt_entry_t *pte; 1158 register pt_entry_t npte; 1159 vm_offset_t opa; 1160 int cacheable=1; 1161 int ptevalid = 0; 1162 1163 if (pmap == NULL) 1164 return; 1165 1166 va = i386_trunc_page(va); 1167 pa = i386_trunc_page(pa); 1168 if (va > VM_MAX_KERNEL_ADDRESS)panic("pmap_enter: toobig"); 1169 1170 /* 1171 * Page Directory table entry not valid, we need a new PT page 1172 */ 1173 if ( *pmap_pde(pmap, va) == 0) { 1174 pg("ptdi %x, va %x", pmap->pm_pdir[PTDPTDI], va); 1175 } 1176 1177 pte = pmap_pte(pmap, va); 1178 opa = pmap_pte_pa(pte); 1179 1180 /* 1181 * Mapping has not changed, must be protection or wiring change. 1182 */ 1183 if (opa == pa) { 1184 /* 1185 * Wiring change, just update stats. 1186 * We don't worry about wiring PT pages as they remain 1187 * resident as long as there are valid mappings in them. 1188 * Hence, if a user page is wired, the PT page will be also. 1189 */ 1190 if (wired && !pmap_pte_w(pte) || !wired && pmap_pte_w(pte)) { 1191 if (wired) 1192 pmap->pm_stats.wired_count++; 1193 else 1194 pmap->pm_stats.wired_count--; 1195 } 1196 goto validate; 1197 } 1198 1199 /* 1200 * Mapping has changed, invalidate old range and fall through to 1201 * handle validating new mapping. 1202 */ 1203 if (opa) { 1204 pmap_remove(pmap, va, va + PAGE_SIZE); 1205 } 1206 1207 /* 1208 * Enter on the PV list if part of our managed memory 1209 * Note that we raise IPL while manipulating pv_table 1210 * since pmap_enter can be called at interrupt time. 1211 */ 1212 if (pmap_is_managed(pa)) { 1213 register pv_entry_t pv, npv; 1214 int s; 1215 1216 pv = pa_to_pvh(pa); 1217 s = splhigh(); 1218 /* 1219 * No entries yet, use header as the first entry 1220 */ 1221 if (pv->pv_pmap == NULL) { 1222 pv->pv_va = va; 1223 pv->pv_pmap = pmap; 1224 pv->pv_next = NULL; 1225 } 1226 /* 1227 * There is at least one other VA mapping this page. 1228 * Place this entry after the header. 1229 */ 1230 else { 1231 npv = get_pv_entry(); 1232 npv->pv_va = va; 1233 npv->pv_pmap = pmap; 1234 npv->pv_next = pv->pv_next; 1235 pv->pv_next = npv; 1236 } 1237 splx(s); 1238 cacheable = 1; 1239 } else { 1240 cacheable = 0; 1241 } 1242 1243 pmap_use_pt(pmap, va); 1244 1245 /* 1246 * Increment counters 1247 */ 1248 pmap->pm_stats.resident_count++; 1249 if (wired) 1250 pmap->pm_stats.wired_count++; 1251 1252validate: 1253 /* 1254 * Now validate mapping with desired protection/wiring. 1255 */ 1256 npte = (pt_entry_t) ( (int) (pa | pte_prot(pmap, prot) | PG_V)); 1257 /* 1258 * for correctness: 1259 */ 1260 if( !cacheable) 1261 (int) npte |= PG_N; 1262 1263 /* 1264 * When forking (copy-on-write, etc): 1265 * A process will turn off write permissions for any of its writable 1266 * pages. If the data (object) is only referred to by one process, the 1267 * processes map is modified directly as opposed to using the 1268 * object manipulation routine. When using pmap_protect, the 1269 * modified bits are not kept in the vm_page_t data structure. 1270 * Therefore, when using pmap_enter in vm_fault to bring back 1271 * writability of a page, there has been no memory of the 1272 * modified or referenced bits except at the pte level. 1273 * this clause supports the carryover of the modified and 1274 * used (referenced) bits. 1275 */ 1276 if (pa == opa) 1277 (int) npte |= (int) *pte & (PG_M|PG_U); 1278 1279 1280 if (wired) 1281 (int) npte |= PG_W; 1282 if (va < UPT_MIN_ADDRESS) 1283 (int) npte |= PG_u; 1284 else if (va < UPT_MAX_ADDRESS) 1285 (int) npte |= PG_u | PG_RW; 1286 1287 if(*pte != npte) { 1288 if (*pte) 1289 ptevalid++; 1290 *pte = npte; 1291 } 1292 if (ptevalid) 1293 tlbflush(); 1294} 1295 1296/* 1297 * Add a list of wired pages to the kva 1298 * this routine is only used for temporary 1299 * kernel mappings that do not need to have 1300 * page modification or references recorded. 1301 * Note that old mappings are simply written 1302 * over. The page *must* be wired. 1303 */ 1304void 1305pmap_qenter(va, m, count) 1306 vm_offset_t va; 1307 vm_page_t *m; 1308 int count; 1309{ 1310 int i; 1311 int anyvalid = 0; 1312 register pt_entry_t *pte; 1313 1314 for(i=0;i<count;i++) { 1315 pte = vtopte(va + i * NBPG); 1316 if (*pte) 1317 anyvalid++; 1318 *pte = (pt_entry_t) ( (int) (VM_PAGE_TO_PHYS(m[i]) | PG_RW | PG_V | PG_W)); 1319 } 1320 if (anyvalid) 1321 tlbflush(); 1322} 1323/* 1324 * this routine jerks page mappings from the 1325 * kernel -- it is meant only for temporary mappings. 1326 */ 1327void 1328pmap_qremove(va, count) 1329 vm_offset_t va; 1330 int count; 1331{ 1332 int i; 1333 register pt_entry_t *pte; 1334 for(i=0;i<count;i++) { 1335 pte = vtopte(va + i * NBPG); 1336 *pte = 0; 1337 } 1338 tlbflush(); 1339} 1340 1341/* 1342 * add a wired page to the kva 1343 * note that in order for the mapping to take effect -- you 1344 * should do a tlbflush after doing the pmap_kenter... 1345 */ 1346void 1347pmap_kenter(va, pa) 1348 vm_offset_t va; 1349 register vm_offset_t pa; 1350{ 1351 register pt_entry_t *pte; 1352 pte = vtopte(va); 1353 1354 *pte = (pt_entry_t) ( (int) (pa | PG_RW | PG_V | PG_W)); 1355} 1356 1357/* 1358 * remove a page from the kernel pagetables 1359 */ 1360void 1361pmap_kremove( va) 1362 vm_offset_t va; 1363{ 1364 register pt_entry_t *pte; 1365 pte = vtopte(va); 1366 1367 *pte = (pt_entry_t) 0; 1368 tlbflush(); 1369} 1370 1371/* 1372 * this code makes some *MAJOR* assumptions: 1373 * 1. Current pmap & pmap exists. 1374 * 2. Not wired. 1375 * 3. Read access. 1376 * 4. No page table pages. 1377 * 5. Tlbflush is deferred to calling procedure. 1378 * 6. Page IS managed. 1379 * but is *MUCH* faster than pmap_enter... 1380 */ 1381 1382static inline int 1383pmap_enter_quick(pmap, va, pa) 1384 register pmap_t pmap; 1385 vm_offset_t va; 1386 register vm_offset_t pa; 1387{ 1388 register pt_entry_t *pte; 1389 register pv_entry_t pv, npv; 1390 int s; 1391 int anyvalid = 0; 1392 1393 /* 1394 * Enter on the PV list if part of our managed memory 1395 * Note that we raise IPL while manipulating pv_table 1396 * since pmap_enter can be called at interrupt time. 1397 */ 1398 1399 pte = vtopte(va); 1400 if (pmap_pte_pa(pte)) { 1401 pmap_remove(pmap, va, va + PAGE_SIZE); 1402 } 1403 1404 pv = pa_to_pvh(pa); 1405 s = splhigh(); 1406 /* 1407 * No entries yet, use header as the first entry 1408 */ 1409 if (pv->pv_pmap == NULL) { 1410 pv->pv_va = va; 1411 pv->pv_pmap = pmap; 1412 pv->pv_next = NULL; 1413 } 1414 /* 1415 * There is at least one other VA mapping this page. 1416 * Place this entry after the header. 1417 */ 1418 else { 1419 npv = get_pv_entry(); 1420 npv->pv_va = va; 1421 npv->pv_pmap = pmap; 1422 npv->pv_next = pv->pv_next; 1423 pv->pv_next = npv; 1424 } 1425 splx(s); 1426 1427 pmap_use_pt(pmap, va); 1428 1429 /* 1430 * Increment counters 1431 */ 1432 pmap->pm_stats.resident_count++; 1433 1434validate: 1435 1436 if (*pte) 1437 anyvalid++; 1438 /* 1439 * Now validate mapping with desired protection/wiring. 1440 */ 1441 *pte = (pt_entry_t) ( (int) (pa | PG_V | PG_u)); 1442 1443 return (anyvalid); 1444} 1445 1446/* 1447 * pmap_object_init_pt preloads the ptes for a given object 1448 * into the specified pmap. This eliminates the blast of soft 1449 * faults on process startup and immediately after an mmap. 1450 */ 1451void 1452pmap_object_init_pt(pmap, addr, object, offset, size) 1453 pmap_t pmap; 1454 vm_offset_t addr; 1455 vm_object_t object; 1456 vm_offset_t offset; 1457 vm_offset_t size; 1458{ 1459 1460 vm_offset_t tmpoff; 1461 vm_page_t p; 1462 int s; 1463 vm_offset_t v, lastv=0; 1464 pt_entry_t pte; 1465 extern vm_map_t kernel_map; 1466 vm_offset_t objbytes; 1467 int anyvalid = 0; 1468 1469 if (!pmap) 1470 return; 1471 1472 /* 1473 * if we are processing a major portion of the object, then 1474 * scan the entire thing. 1475 */ 1476 if( size > object->size / 2) { 1477 objbytes = size; 1478 p = object->memq.tqh_first; 1479 while ((p != NULL) && (objbytes != 0)) { 1480 tmpoff = p->offset; 1481 if( tmpoff < offset) { 1482 p = p->listq.tqe_next; 1483 continue; 1484 } 1485 tmpoff -= offset; 1486 if( tmpoff >= size) { 1487 p = p->listq.tqe_next; 1488 continue; 1489 } 1490 1491 if ((p->flags & (PG_BUSY|PG_FICTITIOUS)) == 0 ) { 1492 vm_page_hold(p); 1493 v = i386_trunc_page(((vm_offset_t)vtopte( addr+tmpoff))); 1494 /* a fault might occur here */ 1495 *(volatile char *)v += 0; 1496 vm_page_unhold(p); 1497 anyvalid += pmap_enter_quick(pmap, addr+tmpoff, VM_PAGE_TO_PHYS(p)); 1498 } 1499 p = p->listq.tqe_next; 1500 objbytes -= NBPG; 1501 } 1502 } else { 1503 /* 1504 * else lookup the pages one-by-one. 1505 */ 1506 for(tmpoff = 0; tmpoff < size; tmpoff += NBPG) { 1507 if( p = vm_page_lookup(object, tmpoff + offset)) { 1508 if( (p->flags & (PG_BUSY|PG_FICTITIOUS)) == 0) { 1509 vm_page_hold(p); 1510 v = i386_trunc_page(((vm_offset_t)vtopte( addr+tmpoff))); 1511 /* a fault might occur here */ 1512 *(volatile char *)v += 0; 1513 vm_page_unhold(p); 1514 anyvalid += pmap_enter_quick(pmap, addr+tmpoff, VM_PAGE_TO_PHYS(p)); 1515 } 1516 } 1517 } 1518 } 1519 1520 if (anyvalid) 1521 tlbflush(); 1522} 1523 1524/* 1525 * Routine: pmap_change_wiring 1526 * Function: Change the wiring attribute for a map/virtual-address 1527 * pair. 1528 * In/out conditions: 1529 * The mapping must already exist in the pmap. 1530 */ 1531void 1532pmap_change_wiring(pmap, va, wired) 1533 register pmap_t pmap; 1534 vm_offset_t va; 1535 boolean_t wired; 1536{ 1537 register pt_entry_t *pte; 1538 1539 if (pmap == NULL) 1540 return; 1541 1542 pte = pmap_pte(pmap, va); 1543 if (wired && !pmap_pte_w(pte) || !wired && pmap_pte_w(pte)) { 1544 if (wired) 1545 pmap->pm_stats.wired_count++; 1546 else 1547 pmap->pm_stats.wired_count--; 1548 } 1549 /* 1550 * Wiring is not a hardware characteristic so there is no need 1551 * to invalidate TLB. 1552 */ 1553 pmap_pte_set_w(pte, wired); 1554 /* 1555 * When unwiring, set the modified bit in the pte -- could have 1556 * been changed by the kernel 1557 */ 1558 if (!wired) 1559 (int) *pte |= PG_M; 1560} 1561 1562 1563 1564/* 1565 * Copy the range specified by src_addr/len 1566 * from the source map to the range dst_addr/len 1567 * in the destination map. 1568 * 1569 * This routine is only advisory and need not do anything. 1570 */ 1571void 1572pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) 1573 pmap_t dst_pmap, src_pmap; 1574 vm_offset_t dst_addr; 1575 vm_size_t len; 1576 vm_offset_t src_addr; 1577{ 1578} 1579/* 1580 * Require that all active physical maps contain no 1581 * incorrect entries NOW. [This update includes 1582 * forcing updates of any address map caching.] 1583 * 1584 * Generally used to insure that a thread about 1585 * to run will see a semantically correct world. 1586 */ 1587void 1588pmap_update() 1589{ 1590 tlbflush(); 1591} 1592 1593/* 1594 * Routine: pmap_kernel 1595 * Function: 1596 * Returns the physical map handle for the kernel. 1597 */ 1598pmap_t 1599pmap_kernel() 1600{ 1601 return (kernel_pmap); 1602} 1603 1604/* 1605 * pmap_zero_page zeros the specified (machine independent) 1606 * page by mapping the page into virtual memory and using 1607 * bzero to clear its contents, one machine dependent page 1608 * at a time. 1609 */ 1610void 1611pmap_zero_page(phys) 1612 vm_offset_t phys; 1613{ 1614 if (*(int *)CMAP2) 1615 panic("pmap_zero_page: CMAP busy"); 1616 1617 *(int *)CMAP2 = PG_V | PG_KW | i386_trunc_page(phys); 1618 bzero(CADDR2,NBPG); 1619 1620 *(int *)CMAP2 = 0; 1621 tlbflush(); 1622} 1623 1624/* 1625 * pmap_copy_page copies the specified (machine independent) 1626 * page by mapping the page into virtual memory and using 1627 * bcopy to copy the page, one machine dependent page at a 1628 * time. 1629 */ 1630void 1631pmap_copy_page(src, dst) 1632 vm_offset_t src; 1633 vm_offset_t dst; 1634{ 1635 if (*(int *)CMAP1 || *(int *)CMAP2) 1636 panic("pmap_copy_page: CMAP busy"); 1637 1638 *(int *)CMAP1 = PG_V | PG_KW | i386_trunc_page(src); 1639 *(int *)CMAP2 = PG_V | PG_KW | i386_trunc_page(dst); 1640 1641#if __GNUC__ > 1 1642 memcpy(CADDR2, CADDR1, NBPG); 1643#else 1644 bcopy(CADDR1, CADDR2, NBPG); 1645#endif 1646 *(int *)CMAP1 = 0; 1647 *(int *)CMAP2 = 0; 1648 tlbflush(); 1649} 1650 1651 1652/* 1653 * Routine: pmap_pageable 1654 * Function: 1655 * Make the specified pages (by pmap, offset) 1656 * pageable (or not) as requested. 1657 * 1658 * A page which is not pageable may not take 1659 * a fault; therefore, its page table entry 1660 * must remain valid for the duration. 1661 * 1662 * This routine is merely advisory; pmap_enter 1663 * will specify that these pages are to be wired 1664 * down (or not) as appropriate. 1665 */ 1666void 1667pmap_pageable(pmap, sva, eva, pageable) 1668 pmap_t pmap; 1669 vm_offset_t sva, eva; 1670 boolean_t pageable; 1671{ 1672} 1673 1674/* 1675 * this routine returns true if a physical page resides 1676 * in the given pmap. 1677 */ 1678boolean_t 1679pmap_page_exists(pmap, pa) 1680 pmap_t pmap; 1681 vm_offset_t pa; 1682{ 1683 register pv_entry_t pv; 1684 int s; 1685 1686 if (!pmap_is_managed(pa)) 1687 return FALSE; 1688 1689 pv = pa_to_pvh(pa); 1690 s = splhigh(); 1691 1692 /* 1693 * Not found, check current mappings returning 1694 * immediately if found. 1695 */ 1696 if (pv->pv_pmap != NULL) { 1697 for (; pv; pv = pv->pv_next) { 1698 if (pv->pv_pmap == pmap) { 1699 splx(s); 1700 return TRUE; 1701 } 1702 } 1703 } 1704 splx(s); 1705 return(FALSE); 1706} 1707 1708/* 1709 * pmap_testbit tests bits in pte's 1710 * note that the testbit/changebit routines are inline, 1711 * and a lot of things compile-time evaluate. 1712 */ 1713static inline boolean_t 1714pmap_testbit(pa, bit) 1715 register vm_offset_t pa; 1716 int bit; 1717{ 1718 register pv_entry_t pv; 1719 pt_entry_t *pte; 1720 int s; 1721 1722 if (!pmap_is_managed(pa)) 1723 return FALSE; 1724 1725 pv = pa_to_pvh(pa); 1726 s = splhigh(); 1727 1728 /* 1729 * Not found, check current mappings returning 1730 * immediately if found. 1731 */ 1732 if (pv->pv_pmap != NULL) { 1733 for (; pv; pv = pv->pv_next) { 1734 /* 1735 * if the bit being tested is the modified bit, 1736 * then mark UPAGES as always modified, and 1737 * ptes as never modified. 1738 */ 1739 if (bit & PG_U ) { 1740 if ((pv->pv_va >= clean_sva) && (pv->pv_va < clean_eva)) { 1741 continue; 1742 } 1743 } 1744 if (bit & PG_M ) { 1745 if (pv->pv_va >= USRSTACK) { 1746 if (pv->pv_va >= clean_sva && pv->pv_va < clean_eva) { 1747 continue; 1748 } 1749 if (pv->pv_va < USRSTACK+(UPAGES*NBPG)) { 1750 splx(s); 1751 return TRUE; 1752 } 1753 else if (pv->pv_va < UPT_MAX_ADDRESS) { 1754 splx(s); 1755 return FALSE; 1756 } 1757 } 1758 } 1759 if( !pv->pv_pmap) { 1760 printf("Null pmap (tb) at va: 0x%lx\n", pv->pv_va); 1761 continue; 1762 } 1763 pte = pmap_pte(pv->pv_pmap, pv->pv_va); 1764 if ((int) *pte & bit) { 1765 splx(s); 1766 return TRUE; 1767 } 1768 } 1769 } 1770 splx(s); 1771 return(FALSE); 1772} 1773 1774/* 1775 * this routine is used to modify bits in ptes 1776 */ 1777static inline void 1778pmap_changebit(pa, bit, setem) 1779 vm_offset_t pa; 1780 int bit; 1781 boolean_t setem; 1782{ 1783 register pv_entry_t pv; 1784 register pt_entry_t *pte, npte; 1785 vm_offset_t va; 1786 int s; 1787 1788 if (!pmap_is_managed(pa)) 1789 return; 1790 1791 pv = pa_to_pvh(pa); 1792 s = splhigh(); 1793 1794 /* 1795 * Loop over all current mappings setting/clearing as appropos 1796 * If setting RO do we need to clear the VAC? 1797 */ 1798 if (pv->pv_pmap != NULL) { 1799 for (; pv; pv = pv->pv_next) { 1800 va = pv->pv_va; 1801 1802 /* 1803 * don't write protect pager mappings 1804 */ 1805 if (!setem && (bit == PG_RW)) { 1806 if (va >= clean_sva && va < clean_eva) 1807 continue; 1808 } 1809 1810 if( !pv->pv_pmap) { 1811 printf("Null pmap (cb) at va: 0x%lx\n", va); 1812 continue; 1813 } 1814 pte = pmap_pte(pv->pv_pmap, va); 1815 if (setem) 1816 (int) npte = (int) *pte | bit; 1817 else 1818 (int) npte = (int) *pte & ~bit; 1819 *pte = npte; 1820 } 1821 } 1822 splx(s); 1823 tlbflush(); 1824} 1825 1826/* 1827 * pmap_page_protect: 1828 * 1829 * Lower the permission for all mappings to a given page. 1830 */ 1831void 1832pmap_page_protect(phys, prot) 1833 vm_offset_t phys; 1834 vm_prot_t prot; 1835{ 1836 if ((prot & VM_PROT_WRITE) == 0) { 1837 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) 1838 pmap_changebit(phys, PG_RW, FALSE); 1839 else 1840 pmap_remove_all(phys); 1841 } 1842} 1843 1844/* 1845 * Clear the modify bits on the specified physical page. 1846 */ 1847void 1848pmap_clear_modify(pa) 1849 vm_offset_t pa; 1850{ 1851 pmap_changebit(pa, PG_M, FALSE); 1852} 1853 1854/* 1855 * pmap_clear_reference: 1856 * 1857 * Clear the reference bit on the specified physical page. 1858 */ 1859void 1860pmap_clear_reference(pa) 1861 vm_offset_t pa; 1862{ 1863 pmap_changebit(pa, PG_U, FALSE); 1864} 1865 1866/* 1867 * pmap_is_referenced: 1868 * 1869 * Return whether or not the specified physical page is referenced 1870 * by any physical maps. 1871 */ 1872 1873boolean_t 1874pmap_is_referenced(pa) 1875 vm_offset_t pa; 1876{ 1877 return(pmap_testbit(pa, PG_U)); 1878} 1879 1880/* 1881 * pmap_is_modified: 1882 * 1883 * Return whether or not the specified physical page is modified 1884 * by any physical maps. 1885 */ 1886 1887boolean_t 1888pmap_is_modified(pa) 1889 vm_offset_t pa; 1890{ 1891 return(pmap_testbit(pa, PG_M)); 1892} 1893 1894/* 1895 * Routine: pmap_copy_on_write 1896 * Function: 1897 * Remove write privileges from all 1898 * physical maps for this physical page. 1899 */ 1900void 1901pmap_copy_on_write(pa) 1902 vm_offset_t pa; 1903{ 1904 pmap_changebit(pa, PG_RW, FALSE); 1905} 1906 1907 1908vm_offset_t 1909pmap_phys_address(ppn) 1910 int ppn; 1911{ 1912 return(i386_ptob(ppn)); 1913} 1914 1915/* 1916 * Miscellaneous support routines follow 1917 */ 1918 1919void 1920i386_protection_init() 1921{ 1922 register int *kp, prot; 1923 1924 kp = protection_codes; 1925 for (prot = 0; prot < 8; prot++) { 1926 switch (prot) { 1927 case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE: 1928 /* 1929 * Read access is also 0. There isn't any execute 1930 * bit, so just make it readable. 1931 */ 1932 case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE: 1933 case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE: 1934 case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE: 1935 *kp++ = 0; 1936 break; 1937 case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE: 1938 case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE: 1939 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE: 1940 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: 1941 *kp++ = PG_RW; 1942 break; 1943 } 1944 } 1945} 1946 1947#ifdef DEBUG 1948/* print address space of pmap*/ 1949void 1950pads(pm) 1951 pmap_t pm; 1952{ 1953 unsigned va, i, j; 1954 pt_entry_t *ptep; 1955 1956 if (pm == kernel_pmap) return; 1957 for (i = 0; i < 1024; i++) 1958 if (pm->pm_pdir[i]) 1959 for (j = 0; j < 1024 ; j++) { 1960 va = (i<<PD_SHIFT)+(j<<PG_SHIFT); 1961 if (pm == kernel_pmap && va < KERNBASE) 1962 continue; 1963 if (pm != kernel_pmap && va > UPT_MAX_ADDRESS) 1964 continue; 1965 ptep = pmap_pte(pm, va); 1966 if (pmap_pte_v(ptep)) 1967 printf("%x:%x ", va, *(int *)ptep); 1968 } ; 1969 1970} 1971 1972void 1973pmap_pvdump(pa) 1974 vm_offset_t pa; 1975{ 1976 register pv_entry_t pv; 1977 1978 printf("pa %x", pa); 1979 for (pv = pa_to_pvh(pa); pv; pv = pv->pv_next) { 1980#ifdef used_to_be 1981 printf(" -> pmap %x, va %x, flags %x", 1982 pv->pv_pmap, pv->pv_va, pv->pv_flags); 1983#endif 1984 printf(" -> pmap %x, va %x", 1985 pv->pv_pmap, pv->pv_va); 1986 pads(pv->pv_pmap); 1987 } 1988 printf(" "); 1989} 1990#endif 1991 1992