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