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