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