|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * File: pmap.c ! 28: * Author: Avadis Tevanian, Jr., Michael Wayne Young ! 29: * (These guys wrote the Vax version) ! 30: * ! 31: * Physical Map management code for Intel i386, i486, and i860. ! 32: * ! 33: * Manages physical address maps. ! 34: * ! 35: * In addition to hardware address maps, this ! 36: * module is called upon to provide software-use-only ! 37: * maps which may or may not be stored in the same ! 38: * form as hardware maps. These pseudo-maps are ! 39: * used to store intermediate results from copy ! 40: * operations to and from address spaces. ! 41: * ! 42: * Since the information managed by this module is ! 43: * also stored by the logical address mapping module, ! 44: * this module may throw away valid virtual-to-physical ! 45: * mappings at almost any time. However, invalidations ! 46: * of virtual-to-physical mappings must be done as ! 47: * requested. ! 48: * ! 49: * In order to cope with hardware architectures which ! 50: * make virtual-to-physical map invalidates expensive, ! 51: * this module may delay invalidate or reduced protection ! 52: * operations until such time as they are actually ! 53: * necessary. This module is given full information as ! 54: * to which processors are currently using which maps, ! 55: * and to when physical maps must be made correct. ! 56: */ ! 57: ! 58: #include <cpus.h> ! 59: ! 60: #include <mach/machine/vm_types.h> ! 61: ! 62: #include <mach/boolean.h> ! 63: #include <kern/thread.h> ! 64: #include <kern/zalloc.h> ! 65: ! 66: #include <kern/lock.h> ! 67: ! 68: #include <vm/pmap.h> ! 69: #include <vm/vm_map.h> ! 70: #include <vm/vm_kern.h> ! 71: #include "vm_param.h" ! 72: #include <mach/vm_prot.h> ! 73: #include <vm/vm_object.h> ! 74: #include <vm/vm_page.h> ! 75: #include <vm/vm_user.h> ! 76: ! 77: #include <mach/machine/vm_param.h> ! 78: #include <machine/thread.h> ! 79: #include "cpu_number.h" ! 80: #if i860 ! 81: #include <i860ipsc/nodehw.h> ! 82: #endif ! 83: ! 84: #ifdef ORC ! 85: #define OLIVETTICACHE 1 ! 86: #endif ORC ! 87: ! 88: #ifndef OLIVETTICACHE ! 89: #define WRITE_PTE(pte_p, pte_entry) *(pte_p) = (pte_entry); ! 90: #define WRITE_PTE_FAST(pte_p, pte_entry) *(pte_p) = (pte_entry); ! 91: #else OLIVETTICACHE ! 92: #error might not work anymore ! 93: ! 94: /* This gross kludgery is needed for Olivetti XP7 & XP9 boxes to get ! 95: * around an apparent hardware bug. Other than at startup it doesn't ! 96: * affect run-time performacne very much, so we leave it in for all ! 97: * machines. ! 98: */ ! 99: extern unsigned *pstart(); ! 100: #define CACHE_LINE 8 ! 101: #define CACHE_SIZE 512 ! 102: #define CACHE_PAGE 0x1000; ! 103: ! 104: #define WRITE_PTE(pte_p, pte_entry) { write_pte(pte_p, pte_entry); } ! 105: ! 106: write_pte(pte_p, pte_entry) ! 107: pt_entry_t *pte_p, pte_entry; ! 108: { ! 109: unsigned long count; ! 110: volatile unsigned long hold, *addr1, *addr2; ! 111: ! 112: if ( pte_entry != *pte_p ) ! 113: *pte_p = pte_entry; ! 114: else { ! 115: /* This isn't necessarily the optimal algorithm */ ! 116: addr1 = (unsigned long *)pstart; ! 117: for (count = 0; count < CACHE_SIZE; count++) { ! 118: addr2 = addr1 + CACHE_PAGE; ! 119: hold = *addr1; /* clear cache bank - A - */ ! 120: hold = *addr2; /* clear cache bank - B - */ ! 121: addr1 += CACHE_LINE; ! 122: } ! 123: } ! 124: } ! 125: ! 126: #define WRITE_PTE_FAST(pte_p, pte_entry)*pte_p = pte_entry; ! 127: ! 128: #endif OLIVETTICACHE ! 129: ! 130: /* ! 131: * Private data structures. ! 132: */ ! 133: ! 134: /* ! 135: * For each vm_page_t, there is a list of all currently ! 136: * valid virtual mappings of that page. An entry is ! 137: * a pv_entry_t; the list is the pv_table. ! 138: */ ! 139: ! 140: typedef struct pv_entry { ! 141: struct pv_entry *next; /* next pv_entry */ ! 142: pmap_t pmap; /* pmap where mapping lies */ ! 143: vm_offset_t va; /* virtual address for mapping */ ! 144: } *pv_entry_t; ! 145: ! 146: #define PV_ENTRY_NULL ((pv_entry_t) 0) ! 147: ! 148: pv_entry_t pv_head_table; /* array of entries, one per page */ ! 149: ! 150: /* ! 151: * pv_list entries are kept on a list that can only be accessed ! 152: * with the pmap system locked (at SPLVM, not in the cpus_active set). ! 153: * The list is refilled from the pv_list_zone if it becomes empty. ! 154: */ ! 155: pv_entry_t pv_free_list; /* free list at SPLVM */ ! 156: decl_simple_lock_data(, pv_free_list_lock) ! 157: ! 158: #define PV_ALLOC(pv_e) { \ ! 159: simple_lock(&pv_free_list_lock); \ ! 160: if ((pv_e = pv_free_list) != 0) { \ ! 161: pv_free_list = pv_e->next; \ ! 162: } \ ! 163: simple_unlock(&pv_free_list_lock); \ ! 164: } ! 165: ! 166: #define PV_FREE(pv_e) { \ ! 167: simple_lock(&pv_free_list_lock); \ ! 168: pv_e->next = pv_free_list; \ ! 169: pv_free_list = pv_e; \ ! 170: simple_unlock(&pv_free_list_lock); \ ! 171: } ! 172: ! 173: zone_t pv_list_zone; /* zone of pv_entry structures */ ! 174: ! 175: /* ! 176: * Each entry in the pv_head_table is locked by a bit in the ! 177: * pv_lock_table. The lock bits are accessed by the physical ! 178: * address of the page they lock. ! 179: */ ! 180: ! 181: char *pv_lock_table; /* pointer to array of bits */ ! 182: #define pv_lock_table_size(n) (((n)+BYTE_SIZE-1)/BYTE_SIZE) ! 183: ! 184: /* Has pmap_init completed? */ ! 185: boolean_t pmap_initialized = FALSE; ! 186: ! 187: /* ! 188: * More-specific code provides these; ! 189: * they indicate the total extent of physical memory ! 190: * that we know about and might ever have to manage. ! 191: */ ! 192: extern vm_offset_t phys_first_addr, phys_last_addr; ! 193: ! 194: /* ! 195: * Range of kernel virtual addresses available for kernel memory mapping. ! 196: * Does not include the virtual addresses used to map physical memory 1-1. ! 197: * Initialized by pmap_bootstrap. ! 198: */ ! 199: vm_offset_t kernel_virtual_start; ! 200: vm_offset_t kernel_virtual_end; ! 201: ! 202: /* XXX stupid fixed limit - get rid */ ! 203: vm_size_t morevm = 40 * 1024 * 1024; /* VM space for kernel map */ ! 204: ! 205: /* ! 206: * Index into pv_head table, its lock bits, and the modify/reference ! 207: * bits starting at phys_first_addr. ! 208: */ ! 209: #define pa_index(pa) (atop(pa - phys_first_addr)) ! 210: ! 211: #define pai_to_pvh(pai) (&pv_head_table[pai]) ! 212: #define lock_pvh_pai(pai) (bit_lock(pai, pv_lock_table)) ! 213: #define unlock_pvh_pai(pai) (bit_unlock(pai, pv_lock_table)) ! 214: ! 215: /* ! 216: * Array of physical page attribites for managed pages. ! 217: * One byte per physical page. ! 218: */ ! 219: char *pmap_phys_attributes; ! 220: ! 221: /* ! 222: * Physical page attributes. Copy bits from PTE definition. ! 223: */ ! 224: #define PHYS_MODIFIED INTEL_PTE_MOD /* page modified */ ! 225: #define PHYS_REFERENCED INTEL_PTE_REF /* page referenced */ ! 226: ! 227: /* ! 228: * Amount of virtual memory mapped by one ! 229: * page-directory entry. ! 230: */ ! 231: #define PDE_MAPPED_SIZE (pdenum2lin(1)) ! 232: ! 233: /* ! 234: * We allocate page table pages directly from the VM system ! 235: * through this object. It maps physical memory. ! 236: */ ! 237: vm_object_t pmap_object = VM_OBJECT_NULL; ! 238: ! 239: /* ! 240: * Locking and TLB invalidation ! 241: */ ! 242: ! 243: /* ! 244: * Locking Protocols: ! 245: * ! 246: * There are two structures in the pmap module that need locking: ! 247: * the pmaps themselves, and the per-page pv_lists (which are locked ! 248: * by locking the pv_lock_table entry that corresponds to the pv_head ! 249: * for the list in question.) Most routines want to lock a pmap and ! 250: * then do operations in it that require pv_list locking -- however ! 251: * pmap_remove_all and pmap_copy_on_write operate on a physical page ! 252: * basis and want to do the locking in the reverse order, i.e. lock ! 253: * a pv_list and then go through all the pmaps referenced by that list. ! 254: * To protect against deadlock between these two cases, the pmap_lock ! 255: * is used. There are three different locking protocols as a result: ! 256: * ! 257: * 1. pmap operations only (pmap_extract, pmap_access, ...) Lock only ! 258: * the pmap. ! 259: * ! 260: * 2. pmap-based operations (pmap_enter, pmap_remove, ...) Get a read ! 261: * lock on the pmap_lock (shared read), then lock the pmap ! 262: * and finally the pv_lists as needed [i.e. pmap lock before ! 263: * pv_list lock.] ! 264: * ! 265: * 3. pv_list-based operations (pmap_remove_all, pmap_copy_on_write, ...) ! 266: * Get a write lock on the pmap_lock (exclusive write); this ! 267: * also guaranteees exclusive access to the pv_lists. Lock the ! 268: * pmaps as needed. ! 269: * ! 270: * At no time may any routine hold more than one pmap lock or more than ! 271: * one pv_list lock. Because interrupt level routines can allocate ! 272: * mbufs and cause pmap_enter's, the pmap_lock and the lock on the ! 273: * kernel_pmap can only be held at splvm. ! 274: */ ! 275: ! 276: #if NCPUS > 1 ! 277: /* ! 278: * We raise the interrupt level to splvm, to block interprocessor ! 279: * interrupts during pmap operations. We must take the CPU out of ! 280: * the cpus_active set while interrupts are blocked. ! 281: */ ! 282: #define SPLVM(spl) { \ ! 283: spl = splvm(); \ ! 284: i_bit_clear(cpu_number(), &cpus_active); \ ! 285: } ! 286: ! 287: #define SPLX(spl) { \ ! 288: i_bit_set(cpu_number(), &cpus_active); \ ! 289: splx(spl); \ ! 290: } ! 291: ! 292: /* ! 293: * Lock on pmap system ! 294: */ ! 295: lock_data_t pmap_system_lock; ! 296: ! 297: #define PMAP_READ_LOCK(pmap, spl) { \ ! 298: SPLVM(spl); \ ! 299: lock_read(&pmap_system_lock); \ ! 300: simple_lock(&(pmap)->lock); \ ! 301: } ! 302: ! 303: #define PMAP_WRITE_LOCK(spl) { \ ! 304: SPLVM(spl); \ ! 305: lock_write(&pmap_system_lock); \ ! 306: } ! 307: ! 308: #define PMAP_READ_UNLOCK(pmap, spl) { \ ! 309: simple_unlock(&(pmap)->lock); \ ! 310: lock_read_done(&pmap_system_lock); \ ! 311: SPLX(spl); \ ! 312: } ! 313: ! 314: #define PMAP_WRITE_UNLOCK(spl) { \ ! 315: lock_write_done(&pmap_system_lock); \ ! 316: SPLX(spl); \ ! 317: } ! 318: ! 319: #define PMAP_WRITE_TO_READ_LOCK(pmap) { \ ! 320: simple_lock(&(pmap)->lock); \ ! 321: lock_write_to_read(&pmap_system_lock); \ ! 322: } ! 323: ! 324: #define LOCK_PVH(index) (lock_pvh_pai(index)) ! 325: ! 326: #define UNLOCK_PVH(index) (unlock_pvh_pai(index)) ! 327: ! 328: #define PMAP_UPDATE_TLBS(pmap, s, e) \ ! 329: { \ ! 330: cpu_set cpu_mask = 1 << cpu_number(); \ ! 331: cpu_set users; \ ! 332: \ ! 333: /* Since the pmap is locked, other updates are locked */ \ ! 334: /* out, and any pmap_activate has finished. */ \ ! 335: \ ! 336: /* find other cpus using the pmap */ \ ! 337: users = (pmap)->cpus_using & ~cpu_mask; \ ! 338: if (users) { \ ! 339: /* signal them, and wait for them to finish */ \ ! 340: /* using the pmap */ \ ! 341: signal_cpus(users, (pmap), (s), (e)); \ ! 342: while ((pmap)->cpus_using & cpus_active & ~cpu_mask) \ ! 343: continue; \ ! 344: } \ ! 345: \ ! 346: /* invalidate our own TLB if pmap is in use */ \ ! 347: if ((pmap)->cpus_using & cpu_mask) { \ ! 348: INVALIDATE_TLB((s), (e)); \ ! 349: } \ ! 350: } ! 351: ! 352: #else NCPUS > 1 ! 353: ! 354: #define SPLVM(spl) ! 355: #define SPLX(spl) ! 356: ! 357: #define PMAP_READ_LOCK(pmap, spl) SPLVM(spl) ! 358: #define PMAP_WRITE_LOCK(spl) SPLVM(spl) ! 359: #define PMAP_READ_UNLOCK(pmap, spl) SPLX(spl) ! 360: #define PMAP_WRITE_UNLOCK(spl) SPLX(spl) ! 361: #define PMAP_WRITE_TO_READ_LOCK(pmap) ! 362: ! 363: #define LOCK_PVH(index) ! 364: #define UNLOCK_PVH(index) ! 365: ! 366: #define PMAP_UPDATE_TLBS(pmap, s, e) { \ ! 367: /* invalidate our own TLB if pmap is in use */ \ ! 368: if ((pmap)->cpus_using) { \ ! 369: INVALIDATE_TLB((s), (e)); \ ! 370: } \ ! 371: } ! 372: ! 373: #endif NCPUS > 1 ! 374: ! 375: #define MAX_TBIS_SIZE 32 /* > this -> TBIA */ /* XXX */ ! 376: ! 377: #if i860 ! 378: /* Do a data cache flush until we find the caching bug XXX prp */ ! 379: #define INVALIDATE_TLB(s, e) { \ ! 380: flush(); \ ! 381: flush_tlb(); \ ! 382: } ! 383: #else i860 ! 384: #define INVALIDATE_TLB(s, e) { \ ! 385: flush_tlb(); \ ! 386: } ! 387: #endif i860 ! 388: ! 389: ! 390: #if NCPUS > 1 ! 391: /* ! 392: * Structures to keep track of pending TLB invalidations ! 393: */ ! 394: ! 395: #define UPDATE_LIST_SIZE 4 ! 396: ! 397: struct pmap_update_item { ! 398: pmap_t pmap; /* pmap to invalidate */ ! 399: vm_offset_t start; /* start address to invalidate */ ! 400: vm_offset_t end; /* end address to invalidate */ ! 401: } ; ! 402: ! 403: typedef struct pmap_update_item *pmap_update_item_t; ! 404: ! 405: /* ! 406: * List of pmap updates. If the list overflows, ! 407: * the last entry is changed to invalidate all. ! 408: */ ! 409: struct pmap_update_list { ! 410: decl_simple_lock_data(, lock) ! 411: int count; ! 412: struct pmap_update_item item[UPDATE_LIST_SIZE]; ! 413: } ; ! 414: typedef struct pmap_update_list *pmap_update_list_t; ! 415: ! 416: struct pmap_update_list cpu_update_list[NCPUS]; ! 417: ! 418: #endif NCPUS > 1 ! 419: ! 420: /* ! 421: * Other useful macros. ! 422: */ ! 423: #define current_pmap() (vm_map_pmap(current_thread()->task->map)) ! 424: #define pmap_in_use(pmap, cpu) (((pmap)->cpus_using & (1 << (cpu))) != 0) ! 425: ! 426: struct pmap kernel_pmap_store; ! 427: pmap_t kernel_pmap; ! 428: ! 429: struct zone *pmap_zone; /* zone of pmap structures */ ! 430: ! 431: int pmap_debug = 0; /* flag for debugging prints */ ! 432: ! 433: #if 0 ! 434: int ptes_per_vm_page; /* number of hardware ptes needed ! 435: to map one VM page. */ ! 436: #else ! 437: #define ptes_per_vm_page 1 ! 438: #endif ! 439: ! 440: unsigned int inuse_ptepages_count = 0; /* debugging */ ! 441: ! 442: extern char end; ! 443: ! 444: /* ! 445: * Pointer to the basic page directory for the kernel. ! 446: * Initialized by pmap_bootstrap(). ! 447: */ ! 448: pt_entry_t *kernel_page_dir; ! 449: ! 450: void pmap_remove_range(); /* forward */ ! 451: #if NCPUS > 1 ! 452: void signal_cpus(); /* forward */ ! 453: #endif NCPUS > 1 ! 454: ! 455: #if i860 ! 456: /* ! 457: * Paging flag ! 458: */ ! 459: int paging_enabled = 0; ! 460: #endif ! 461: ! 462: static inline pt_entry_t * ! 463: pmap_pde(pmap_t pmap, vm_offset_t addr) ! 464: { ! 465: if (pmap == kernel_pmap) ! 466: addr = kvtolin(addr); ! 467: return &pmap->dirbase[lin2pdenum(addr)]; ! 468: } ! 469: ! 470: /* ! 471: * Given an offset and a map, compute the address of the ! 472: * pte. If the address is invalid with respect to the map ! 473: * then PT_ENTRY_NULL is returned (and the map may need to grow). ! 474: * ! 475: * This is only used internally. ! 476: */ ! 477: pt_entry_t * ! 478: pmap_pte(pmap_t pmap, vm_offset_t addr) ! 479: { ! 480: pt_entry_t *ptp; ! 481: pt_entry_t pte; ! 482: ! 483: if (pmap->dirbase == 0) ! 484: return(PT_ENTRY_NULL); ! 485: pte = *pmap_pde(pmap, addr); ! 486: if ((pte & INTEL_PTE_VALID) == 0) ! 487: return(PT_ENTRY_NULL); ! 488: ptp = (pt_entry_t *)ptetokv(pte); ! 489: return(&ptp[ptenum(addr)]); ! 490: } ! 491: ! 492: #define DEBUG_PTE_PAGE 0 ! 493: ! 494: #if DEBUG_PTE_PAGE ! 495: void ptep_check(ptep) ! 496: ptep_t ptep; ! 497: { ! 498: register pt_entry_t *pte, *epte; ! 499: int ctu, ctw; ! 500: ! 501: /* check the use and wired counts */ ! 502: if (ptep == PTE_PAGE_NULL) ! 503: return; ! 504: pte = pmap_pte(ptep->pmap, ptep->va); ! 505: epte = pte + INTEL_PGBYTES/sizeof(pt_entry_t); ! 506: ctu = 0; ! 507: ctw = 0; ! 508: while (pte < epte) { ! 509: if (pte->pfn != 0) { ! 510: ctu++; ! 511: if (pte->wired) ! 512: ctw++; ! 513: } ! 514: pte += ptes_per_vm_page; ! 515: } ! 516: ! 517: if (ctu != ptep->use_count || ctw != ptep->wired_count) { ! 518: printf("use %d wired %d - actual use %d wired %d\n", ! 519: ptep->use_count, ptep->wired_count, ctu, ctw); ! 520: panic("pte count"); ! 521: } ! 522: } ! 523: #endif DEBUG_PTE_PAGE ! 524: ! 525: /* ! 526: * Map memory at initialization. The physical addresses being ! 527: * mapped are not managed and are never unmapped. ! 528: * ! 529: * For now, VM is already on, we only need to map the ! 530: * specified memory. ! 531: */ ! 532: vm_offset_t pmap_map(virt, start, end, prot) ! 533: register vm_offset_t virt; ! 534: register vm_offset_t start; ! 535: register vm_offset_t end; ! 536: register int prot; ! 537: { ! 538: register int ps; ! 539: ! 540: ps = PAGE_SIZE; ! 541: while (start < end) { ! 542: pmap_enter(kernel_pmap, virt, start, prot, FALSE); ! 543: virt += ps; ! 544: start += ps; ! 545: } ! 546: return(virt); ! 547: } ! 548: ! 549: /* ! 550: * Back-door routine for mapping kernel VM at initialization. ! 551: * Useful for mapping memory outside the range ! 552: * [phys_first_addr, phys_last_addr) (i.e., devices). ! 553: * Otherwise like pmap_map. ! 554: #if i860 ! 555: * Sets no-cache bit. ! 556: #endif ! 557: */ ! 558: vm_offset_t pmap_map_bd(virt, start, end, prot) ! 559: register vm_offset_t virt; ! 560: register vm_offset_t start; ! 561: register vm_offset_t end; ! 562: vm_prot_t prot; ! 563: { ! 564: register pt_entry_t template; ! 565: register pt_entry_t *pte; ! 566: ! 567: template = pa_to_pte(start) ! 568: #if i860 ! 569: | INTEL_PTE_NCACHE ! 570: #endif ! 571: | INTEL_PTE_VALID; ! 572: if (prot & VM_PROT_WRITE) ! 573: template |= INTEL_PTE_WRITE; ! 574: ! 575: while (start < end) { ! 576: pte = pmap_pte(kernel_pmap, virt); ! 577: if (pte == PT_ENTRY_NULL) ! 578: panic("pmap_map_bd: Invalid kernel address\n"); ! 579: WRITE_PTE_FAST(pte, template) ! 580: pte_increment_pa(template); ! 581: virt += PAGE_SIZE; ! 582: start += PAGE_SIZE; ! 583: } ! 584: return(virt); ! 585: } ! 586: ! 587: /* ! 588: * Bootstrap the system enough to run with virtual memory. ! 589: * Allocate the kernel page directory and page tables, ! 590: * and direct-map all physical memory. ! 591: * Called with mapping off. ! 592: */ ! 593: void pmap_bootstrap() ! 594: { ! 595: /* ! 596: * Mapping is turned off; we must reference only physical addresses. ! 597: * The load image of the system is to be mapped 1-1 physical = virtual. ! 598: */ ! 599: ! 600: /* ! 601: * Set ptes_per_vm_page for general use. ! 602: */ ! 603: #if 0 ! 604: ptes_per_vm_page = PAGE_SIZE / INTEL_PGBYTES; ! 605: #endif ! 606: ! 607: /* ! 608: * The kernel's pmap is statically allocated so we don't ! 609: * have to use pmap_create, which is unlikely to work ! 610: * correctly at this part of the boot sequence. ! 611: */ ! 612: ! 613: kernel_pmap = &kernel_pmap_store; ! 614: ! 615: #if NCPUS > 1 ! 616: lock_init(&pmap_system_lock, FALSE); /* NOT a sleep lock */ ! 617: #endif NCPUS > 1 ! 618: ! 619: simple_lock_init(&kernel_pmap->lock); ! 620: ! 621: kernel_pmap->ref_count = 1; ! 622: ! 623: /* ! 624: * Determine the kernel virtual address range. ! 625: * It starts at the end of the physical memory ! 626: * mapped into the kernel address space, ! 627: * and extends to a stupid arbitrary limit beyond that. ! 628: */ ! 629: kernel_virtual_start = phys_last_addr; ! 630: kernel_virtual_end = phys_last_addr + morevm; ! 631: ! 632: /* ! 633: * Allocate and clear a kernel page directory. ! 634: */ ! 635: kernel_pmap->dirbase = kernel_page_dir = (pt_entry_t*)pmap_grab_page(); ! 636: { ! 637: int i; ! 638: for (i = 0; i < NPDES; i++) ! 639: kernel_pmap->dirbase[i] = 0; ! 640: } ! 641: ! 642: /* ! 643: * Allocate and set up the kernel page tables. ! 644: */ ! 645: { ! 646: vm_offset_t va; ! 647: ! 648: /* ! 649: * Map virtual memory for all known physical memory, 1-1, ! 650: * from phys_first_addr to phys_last_addr. ! 651: * Make any mappings completely in the kernel's text segment read-only. ! 652: * ! 653: * Also allocate some additional all-null page tables afterwards ! 654: * for kernel virtual memory allocation, ! 655: * because this PMAP module is too stupid ! 656: * to allocate new kernel page tables later. ! 657: * XX fix this ! 658: */ ! 659: for (va = phys_first_addr; va < phys_last_addr + morevm; ) ! 660: { ! 661: pt_entry_t *pde = kernel_page_dir + lin2pdenum(kvtolin(va)); ! 662: pt_entry_t *ptable = (pt_entry_t*)pmap_grab_page(); ! 663: pt_entry_t *pte; ! 664: vm_offset_t pteva; ! 665: ! 666: /* Initialize the page directory entry. */ ! 667: *pde = pa_to_pte((vm_offset_t)ptable) ! 668: | INTEL_PTE_VALID | INTEL_PTE_WRITE; ! 669: ! 670: /* Initialize the page table. */ ! 671: for (pte = ptable; (va < phys_last_addr) && (pte < ptable+NPTES); pte++) ! 672: { ! 673: if ((pte - ptable) < ptenum(va)) ! 674: { ! 675: WRITE_PTE_FAST(pte, 0); ! 676: } ! 677: else ! 678: { ! 679: extern char start[], etext[]; ! 680: ! 681: if ((va >= (vm_offset_t)start) ! 682: && (va + INTEL_PGBYTES <= (vm_offset_t)etext)) ! 683: { ! 684: WRITE_PTE_FAST(pte, pa_to_pte(va) ! 685: | INTEL_PTE_VALID); ! 686: } ! 687: else ! 688: { ! 689: WRITE_PTE_FAST(pte, pa_to_pte(va) ! 690: | INTEL_PTE_VALID | INTEL_PTE_WRITE); ! 691: } ! 692: va += INTEL_PGBYTES; ! 693: } ! 694: } ! 695: for (; pte < ptable+NPTES; pte++) ! 696: { ! 697: WRITE_PTE_FAST(pte, 0); ! 698: va += INTEL_PGBYTES; ! 699: } ! 700: } ! 701: } ! 702: ! 703: #if i860 ! 704: #error probably doesnt work anymore ! 705: XXX move to architecture-specific code just after the pmap_bootstrap call. ! 706: ! 707: /* kvtophys should now work in phys range */ ! 708: ! 709: /* ! 710: * Mark page table pages non-cacheable ! 711: */ ! 712: ! 713: pt_pte = (pt_entry_t *)pte_to_pa(*(kpde + pdenum(sva))) + ptenum(sva); ! 714: ! 715: for (va = load_start; va < tva; va += INTEL_PGBYTES*NPTES) { ! 716: /* Mark page table non-cacheable */ ! 717: *pt_pte |= INTEL_PTE_NCACHE; ! 718: pt_pte++; ! 719: } ! 720: ! 721: /* ! 722: * Map I/O space ! 723: */ ! 724: ! 725: ppde = kpde; ! 726: ppde += pdenum(IO_BASE); ! 727: ! 728: if (pte_to_pa(*ppde) == 0) { ! 729: /* This pte has not been allocated */ ! 730: ppte = (pt_entry_t *)kvtophys(virtual_avail); ! 731: ptend = ppte + NPTES; ! 732: virtual_avail = phystokv((vm_offset_t)ptend); ! 733: *ppde = pa_to_pte((vm_offset_t)ppte) ! 734: | INTEL_PTE_VALID ! 735: | INTEL_PTE_WRITE; ! 736: pte = ptend; ! 737: ! 738: /* Mark page table non-cacheable */ ! 739: *pt_pte |= INTEL_PTE_NCACHE; ! 740: pt_pte++; ! 741: ! 742: bzero((char *)ppte, INTEL_PGBYTES); ! 743: } else { ! 744: ppte = (pt_entry_t *)(*ppde); /* first pte of page */ ! 745: } ! 746: *ppde |= INTEL_PTE_USER; ! 747: ! 748: ! 749: WRITE_PTE(ppte + ptenum(FIFO_ADDR), ! 750: pa_to_pte(FIFO_ADDR_PH) ! 751: | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_NCACHE); ! 752: ! 753: WRITE_PTE(ppte + ptenum(FIFO_ADDR + XEOD_OFF), ! 754: pa_to_pte(FIFO_ADDR_PH + XEOD_OFF_PH) ! 755: | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_NCACHE); ! 756: ! 757: /* XXX Allowed user access to control reg - cfj */ ! 758: WRITE_PTE(ppte + ptenum(CSR_ADDR), ! 759: pa_to_pte(CSR_ADDR_PH) ! 760: | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_NCACHE | INTEL_PTE_USER); ! 761: ! 762: /* XXX Allowed user access to perf reg - cfj */ ! 763: WRITE_PTE(ppte + ptenum(PERFCNT_ADDR), ! 764: pa_to_pte(PERFCNT_ADDR_PH) ! 765: | INTEL_PTE_VALID | INTEL_PTE_USER | INTEL_PTE_NCACHE | INTEL_PTE_USER); ! 766: ! 767: WRITE_PTE(ppte + ptenum(UART_ADDR), ! 768: pa_to_pte(UART_ADDR_PH) ! 769: | INTEL_PTE_VALID | INTEL_PTE_WRITE | INTEL_PTE_NCACHE); ! 770: ! 771: WRITE_PTE(ppte + ptenum(0xFFFFF000), ! 772: pa_to_pte(avail_end) ! 773: | INTEL_PTE_VALID | INTEL_PTE_WRITE); ! 774: avail_start = kvtophys(virtual_avail); ! 775: ! 776: /* ! 777: * Turn on mapping ! 778: */ ! 779: ! 780: flush_and_ctxsw(kernel_pmap->dirbase); ! 781: paging_enabled = 1; ! 782: ! 783: printf("Paging enabled.\n"); ! 784: #endif ! 785: ! 786: /* Architecture-specific code will turn on paging ! 787: soon after we return from here. */ ! 788: } ! 789: ! 790: void pmap_virtual_space(startp, endp) ! 791: vm_offset_t *startp; ! 792: vm_offset_t *endp; ! 793: { ! 794: *startp = kernel_virtual_start; ! 795: *endp = kernel_virtual_end; ! 796: } ! 797: ! 798: /* ! 799: * Initialize the pmap module. ! 800: * Called by vm_init, to initialize any structures that the pmap ! 801: * system needs to map virtual memory. ! 802: */ ! 803: void pmap_init() ! 804: { ! 805: register long npages; ! 806: vm_offset_t addr; ! 807: register vm_size_t s; ! 808: int i; ! 809: ! 810: /* ! 811: * Allocate memory for the pv_head_table and its lock bits, ! 812: * the modify bit array, and the pte_page table. ! 813: */ ! 814: ! 815: npages = atop(phys_last_addr - phys_first_addr); ! 816: s = (vm_size_t) (sizeof(struct pv_entry) * npages ! 817: + pv_lock_table_size(npages) ! 818: + npages); ! 819: ! 820: s = round_page(s); ! 821: if (kmem_alloc_wired(kernel_map, &addr, s) != KERN_SUCCESS) ! 822: panic("pmap_init"); ! 823: bzero((char *) addr, s); ! 824: ! 825: /* ! 826: * Allocate the structures first to preserve word-alignment. ! 827: */ ! 828: pv_head_table = (pv_entry_t) addr; ! 829: addr = (vm_offset_t) (pv_head_table + npages); ! 830: ! 831: pv_lock_table = (char *) addr; ! 832: addr = (vm_offset_t) (pv_lock_table + pv_lock_table_size(npages)); ! 833: ! 834: pmap_phys_attributes = (char *) addr; ! 835: ! 836: /* ! 837: * Create the zone of physical maps, ! 838: * and of the physical-to-virtual entries. ! 839: */ ! 840: s = (vm_size_t) sizeof(struct pmap); ! 841: pmap_zone = zinit(s, 400*s, 4096, 0, "pmap"); /* XXX */ ! 842: s = (vm_size_t) sizeof(struct pv_entry); ! 843: pv_list_zone = zinit(s, 10000*s, 4096, 0, "pv_list"); /* XXX */ ! 844: ! 845: #if NCPUS > 1 ! 846: /* ! 847: * Set up the pmap request lists ! 848: */ ! 849: for (i = 0; i < NCPUS; i++) { ! 850: pmap_update_list_t up = &cpu_update_list[i]; ! 851: ! 852: simple_lock_init(&up->lock); ! 853: up->count = 0; ! 854: } ! 855: #endif NCPUS > 1 ! 856: ! 857: /* ! 858: * Indicate that the PMAP module is now fully initialized. ! 859: */ ! 860: pmap_initialized = TRUE; ! 861: } ! 862: ! 863: #define valid_page(x) (pmap_initialized && pmap_valid_page(x)) ! 864: ! 865: boolean_t pmap_verify_free(phys) ! 866: vm_offset_t phys; ! 867: { ! 868: pv_entry_t pv_h; ! 869: int pai; ! 870: int spl; ! 871: boolean_t result; ! 872: ! 873: assert(phys != vm_page_fictitious_addr); ! 874: if (!pmap_initialized) ! 875: return(TRUE); ! 876: ! 877: if (!pmap_valid_page(phys)) ! 878: return(FALSE); ! 879: ! 880: PMAP_WRITE_LOCK(spl); ! 881: ! 882: pai = pa_index(phys); ! 883: pv_h = pai_to_pvh(pai); ! 884: ! 885: result = (pv_h->pmap == PMAP_NULL); ! 886: PMAP_WRITE_UNLOCK(spl); ! 887: ! 888: return(result); ! 889: } ! 890: ! 891: /* ! 892: * Routine: pmap_page_table_page_alloc ! 893: * ! 894: * Allocates a new physical page to be used as a page-table page. ! 895: * ! 896: * Must be called with the pmap system and the pmap unlocked, ! 897: * since these must be unlocked to use vm_page_grab. ! 898: */ ! 899: vm_offset_t ! 900: pmap_page_table_page_alloc() ! 901: { ! 902: register vm_page_t m; ! 903: register vm_offset_t pa; ! 904: ! 905: check_simple_locks(); ! 906: ! 907: /* ! 908: * We cannot allocate the pmap_object in pmap_init, ! 909: * because it is called before the zone package is up. ! 910: * Allocate it now if it is missing. ! 911: */ ! 912: if (pmap_object == VM_OBJECT_NULL) ! 913: pmap_object = vm_object_allocate(phys_last_addr - phys_first_addr); ! 914: ! 915: /* ! 916: * Allocate a VM page for the level 2 page table entries. ! 917: */ ! 918: while ((m = vm_page_grab()) == VM_PAGE_NULL) ! 919: VM_PAGE_WAIT((void (*)()) 0); ! 920: ! 921: /* ! 922: * Map the page to its physical address so that it ! 923: * can be found later. ! 924: */ ! 925: pa = m->phys_addr; ! 926: vm_object_lock(pmap_object); ! 927: vm_page_insert(m, pmap_object, pa); ! 928: vm_page_lock_queues(); ! 929: vm_page_wire(m); ! 930: inuse_ptepages_count++; ! 931: vm_page_unlock_queues(); ! 932: vm_object_unlock(pmap_object); ! 933: ! 934: /* ! 935: * Zero the page. ! 936: */ ! 937: bzero(phystokv(pa), PAGE_SIZE); ! 938: ! 939: #if i860 ! 940: /* ! 941: * Mark the page table page(s) non-cacheable. ! 942: */ ! 943: { ! 944: int i = ptes_per_vm_page; ! 945: pt_entry_t *pdp; ! 946: ! 947: pdp = pmap_pte(kernel_pmap, pa); ! 948: do { ! 949: *pdp |= INTEL_PTE_NCACHE; ! 950: pdp++; ! 951: } while (--i > 0); ! 952: } ! 953: #endif ! 954: return pa; ! 955: } ! 956: ! 957: /* ! 958: * Deallocate a page-table page. ! 959: * The page-table page must have all mappings removed, ! 960: * and be removed from its page directory. ! 961: */ ! 962: void ! 963: pmap_page_table_page_dealloc(pa) ! 964: vm_offset_t pa; ! 965: { ! 966: vm_page_t m; ! 967: ! 968: vm_object_lock(pmap_object); ! 969: m = vm_page_lookup(pmap_object, pa); ! 970: vm_page_lock_queues(); ! 971: vm_page_free(m); ! 972: inuse_ptepages_count--; ! 973: vm_page_unlock_queues(); ! 974: vm_object_unlock(pmap_object); ! 975: } ! 976: ! 977: /* ! 978: * Create and return a physical map. ! 979: * ! 980: * If the size specified for the map ! 981: * is zero, the map is an actual physical ! 982: * map, and may be referenced by the ! 983: * hardware. ! 984: * ! 985: * If the size specified is non-zero, ! 986: * the map will be used in software only, and ! 987: * is bounded by that size. ! 988: */ ! 989: pmap_t pmap_create(size) ! 990: vm_size_t size; ! 991: { ! 992: register pmap_t p; ! 993: register pmap_statistics_t stats; ! 994: ! 995: /* ! 996: * A software use-only map doesn't even need a map. ! 997: */ ! 998: ! 999: if (size != 0) { ! 1000: return(PMAP_NULL); ! 1001: } ! 1002: ! 1003: /* ! 1004: * Allocate a pmap struct from the pmap_zone. Then allocate ! 1005: * the page descriptor table from the pd_zone. ! 1006: */ ! 1007: ! 1008: p = (pmap_t) zalloc(pmap_zone); ! 1009: if (p == PMAP_NULL) ! 1010: panic("pmap_create"); ! 1011: ! 1012: if (kmem_alloc_wired(kernel_map, ! 1013: (vm_offset_t *)&p->dirbase, INTEL_PGBYTES) ! 1014: != KERN_SUCCESS) ! 1015: panic("pmap_create"); ! 1016: ! 1017: bcopy(kernel_page_dir, p->dirbase, INTEL_PGBYTES); ! 1018: p->ref_count = 1; ! 1019: ! 1020: simple_lock_init(&p->lock); ! 1021: p->cpus_using = 0; ! 1022: ! 1023: /* ! 1024: * Initialize statistics. ! 1025: */ ! 1026: ! 1027: stats = &p->stats; ! 1028: stats->resident_count = 0; ! 1029: stats->wired_count = 0; ! 1030: ! 1031: return(p); ! 1032: } ! 1033: ! 1034: /* ! 1035: * Retire the given physical map from service. ! 1036: * Should only be called if the map contains ! 1037: * no valid mappings. ! 1038: */ ! 1039: ! 1040: void pmap_destroy(p) ! 1041: register pmap_t p; ! 1042: { ! 1043: register pt_entry_t *pdep; ! 1044: register vm_offset_t pa; ! 1045: register int c, s; ! 1046: register vm_page_t m; ! 1047: ! 1048: if (p == PMAP_NULL) ! 1049: return; ! 1050: ! 1051: SPLVM(s); ! 1052: simple_lock(&p->lock); ! 1053: c = --p->ref_count; ! 1054: simple_unlock(&p->lock); ! 1055: SPLX(s); ! 1056: ! 1057: if (c != 0) { ! 1058: return; /* still in use */ ! 1059: } ! 1060: ! 1061: /* ! 1062: * Free the memory maps, then the ! 1063: * pmap structure. ! 1064: */ ! 1065: for (pdep = p->dirbase; ! 1066: pdep < &p->dirbase[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)]; ! 1067: pdep += ptes_per_vm_page) { ! 1068: if (*pdep & INTEL_PTE_VALID) { ! 1069: pa = pte_to_pa(*pdep); ! 1070: vm_object_lock(pmap_object); ! 1071: m = vm_page_lookup(pmap_object, pa); ! 1072: if (m == VM_PAGE_NULL) ! 1073: panic("pmap_destroy: pte page not in object"); ! 1074: vm_page_lock_queues(); ! 1075: vm_page_free(m); ! 1076: inuse_ptepages_count--; ! 1077: vm_page_unlock_queues(); ! 1078: vm_object_unlock(pmap_object); ! 1079: } ! 1080: } ! 1081: kmem_free(kernel_map, p->dirbase, INTEL_PGBYTES); ! 1082: zfree(pmap_zone, (vm_offset_t) p); ! 1083: } ! 1084: ! 1085: /* ! 1086: * Add a reference to the specified pmap. ! 1087: */ ! 1088: ! 1089: void pmap_reference(p) ! 1090: register pmap_t p; ! 1091: { ! 1092: int s; ! 1093: if (p != PMAP_NULL) { ! 1094: SPLVM(s); ! 1095: simple_lock(&p->lock); ! 1096: p->ref_count++; ! 1097: simple_unlock(&p->lock); ! 1098: SPLX(s); ! 1099: } ! 1100: } ! 1101: ! 1102: /* ! 1103: * Remove a range of hardware page-table entries. ! 1104: * The entries given are the first (inclusive) ! 1105: * and last (exclusive) entries for the VM pages. ! 1106: * The virtual address is the va for the first pte. ! 1107: * ! 1108: * The pmap must be locked. ! 1109: * If the pmap is not the kernel pmap, the range must lie ! 1110: * entirely within one pte-page. This is NOT checked. ! 1111: * Assumes that the pte-page exists. ! 1112: */ ! 1113: ! 1114: /* static */ ! 1115: void pmap_remove_range(pmap, va, spte, epte) ! 1116: pmap_t pmap; ! 1117: vm_offset_t va; ! 1118: pt_entry_t *spte; ! 1119: pt_entry_t *epte; ! 1120: { ! 1121: register pt_entry_t *cpte; ! 1122: int num_removed, num_unwired; ! 1123: int pai; ! 1124: vm_offset_t pa; ! 1125: ! 1126: #if DEBUG_PTE_PAGE ! 1127: if (pmap != kernel_pmap) ! 1128: ptep_check(get_pte_page(spte)); ! 1129: #endif DEBUG_PTE_PAGE ! 1130: num_removed = 0; ! 1131: num_unwired = 0; ! 1132: ! 1133: for (cpte = spte; cpte < epte; ! 1134: cpte += ptes_per_vm_page, va += PAGE_SIZE) { ! 1135: ! 1136: if (*cpte == 0) ! 1137: continue; ! 1138: pa = pte_to_pa(*cpte); ! 1139: ! 1140: num_removed++; ! 1141: if (*cpte & INTEL_PTE_WIRED) ! 1142: num_unwired++; ! 1143: ! 1144: if (!valid_page(pa)) { ! 1145: ! 1146: /* ! 1147: * Outside range of managed physical memory. ! 1148: * Just remove the mappings. ! 1149: */ ! 1150: register int i = ptes_per_vm_page; ! 1151: register pt_entry_t *lpte = cpte; ! 1152: do { ! 1153: *lpte = 0; ! 1154: lpte++; ! 1155: } while (--i > 0); ! 1156: continue; ! 1157: } ! 1158: ! 1159: pai = pa_index(pa); ! 1160: LOCK_PVH(pai); ! 1161: ! 1162: /* ! 1163: * Get the modify and reference bits. ! 1164: */ ! 1165: { ! 1166: register int i; ! 1167: register pt_entry_t *lpte; ! 1168: ! 1169: i = ptes_per_vm_page; ! 1170: lpte = cpte; ! 1171: do { ! 1172: pmap_phys_attributes[pai] |= ! 1173: *lpte & (PHYS_MODIFIED|PHYS_REFERENCED); ! 1174: *lpte = 0; ! 1175: lpte++; ! 1176: } while (--i > 0); ! 1177: } ! 1178: ! 1179: /* ! 1180: * Remove the mapping from the pvlist for ! 1181: * this physical page. ! 1182: */ ! 1183: { ! 1184: register pv_entry_t pv_h, prev, cur; ! 1185: ! 1186: pv_h = pai_to_pvh(pai); ! 1187: if (pv_h->pmap == PMAP_NULL) { ! 1188: panic("pmap_remove: null pv_list!"); ! 1189: } ! 1190: if (pv_h->va == va && pv_h->pmap == pmap) { ! 1191: /* ! 1192: * Header is the pv_entry. Copy the next one ! 1193: * to header and free the next one (we cannot ! 1194: * free the header) ! 1195: */ ! 1196: cur = pv_h->next; ! 1197: if (cur != PV_ENTRY_NULL) { ! 1198: *pv_h = *cur; ! 1199: PV_FREE(cur); ! 1200: } ! 1201: else { ! 1202: pv_h->pmap = PMAP_NULL; ! 1203: } ! 1204: } ! 1205: else { ! 1206: cur = pv_h; ! 1207: do { ! 1208: prev = cur; ! 1209: if ((cur = prev->next) == PV_ENTRY_NULL) { ! 1210: panic("pmap-remove: mapping not in pv_list!"); ! 1211: } ! 1212: } while (cur->va != va || cur->pmap != pmap); ! 1213: prev->next = cur->next; ! 1214: PV_FREE(cur); ! 1215: } ! 1216: UNLOCK_PVH(pai); ! 1217: } ! 1218: } ! 1219: ! 1220: /* ! 1221: * Update the counts ! 1222: */ ! 1223: pmap->stats.resident_count -= num_removed; ! 1224: pmap->stats.wired_count -= num_unwired; ! 1225: } ! 1226: ! 1227: /* ! 1228: * Remove the given range of addresses ! 1229: * from the specified map. ! 1230: * ! 1231: * It is assumed that the start and end are properly ! 1232: * rounded to the hardware page size. ! 1233: */ ! 1234: ! 1235: void pmap_remove(map, s, e) ! 1236: pmap_t map; ! 1237: vm_offset_t s, e; ! 1238: { ! 1239: int spl; ! 1240: register pt_entry_t *pde; ! 1241: register pt_entry_t *spte, *epte; ! 1242: vm_offset_t l; ! 1243: ! 1244: if (map == PMAP_NULL) ! 1245: return; ! 1246: ! 1247: PMAP_READ_LOCK(map, spl); ! 1248: ! 1249: /* ! 1250: * Invalidate the translation buffer first ! 1251: */ ! 1252: PMAP_UPDATE_TLBS(map, s, e); ! 1253: ! 1254: pde = pmap_pde(map, s); ! 1255: while (s < e) { ! 1256: l = (s + PDE_MAPPED_SIZE) & ~(PDE_MAPPED_SIZE-1); ! 1257: if (l > e) ! 1258: l = e; ! 1259: if (*pde & INTEL_PTE_VALID) { ! 1260: spte = (pt_entry_t *)ptetokv(*pde); ! 1261: spte = &spte[ptenum(s)]; ! 1262: epte = &spte[intel_btop(l-s)]; ! 1263: pmap_remove_range(map, s, spte, epte); ! 1264: } ! 1265: s = l; ! 1266: pde++; ! 1267: } ! 1268: ! 1269: PMAP_READ_UNLOCK(map, spl); ! 1270: } ! 1271: ! 1272: /* ! 1273: * Routine: pmap_page_protect ! 1274: * ! 1275: * Function: ! 1276: * Lower the permission for all mappings to a given ! 1277: * page. ! 1278: */ ! 1279: void pmap_page_protect(phys, prot) ! 1280: vm_offset_t phys; ! 1281: vm_prot_t prot; ! 1282: { ! 1283: pv_entry_t pv_h, prev; ! 1284: register pv_entry_t pv_e; ! 1285: register pt_entry_t *pte; ! 1286: int pai; ! 1287: register pmap_t pmap; ! 1288: int spl; ! 1289: boolean_t remove; ! 1290: ! 1291: assert(phys != vm_page_fictitious_addr); ! 1292: if (!valid_page(phys)) { ! 1293: /* ! 1294: * Not a managed page. ! 1295: */ ! 1296: return; ! 1297: } ! 1298: ! 1299: /* ! 1300: * Determine the new protection. ! 1301: */ ! 1302: switch (prot) { ! 1303: case VM_PROT_READ: ! 1304: case VM_PROT_READ|VM_PROT_EXECUTE: ! 1305: remove = FALSE; ! 1306: break; ! 1307: case VM_PROT_ALL: ! 1308: return; /* nothing to do */ ! 1309: default: ! 1310: remove = TRUE; ! 1311: break; ! 1312: } ! 1313: ! 1314: /* ! 1315: * Lock the pmap system first, since we will be changing ! 1316: * several pmaps. ! 1317: */ ! 1318: ! 1319: PMAP_WRITE_LOCK(spl); ! 1320: ! 1321: pai = pa_index(phys); ! 1322: pv_h = pai_to_pvh(pai); ! 1323: ! 1324: /* ! 1325: * Walk down PV list, changing or removing all mappings. ! 1326: * We do not have to lock the pv_list because we have ! 1327: * the entire pmap system locked. ! 1328: */ ! 1329: if (pv_h->pmap != PMAP_NULL) { ! 1330: ! 1331: prev = pv_e = pv_h; ! 1332: do { ! 1333: pmap = pv_e->pmap; ! 1334: /* ! 1335: * Lock the pmap to block pmap_extract and similar routines. ! 1336: */ ! 1337: simple_lock(&pmap->lock); ! 1338: ! 1339: { ! 1340: register vm_offset_t va; ! 1341: ! 1342: va = pv_e->va; ! 1343: pte = pmap_pte(pmap, va); ! 1344: ! 1345: /* ! 1346: * Consistency checks. ! 1347: */ ! 1348: /* assert(*pte & INTEL_PTE_VALID); XXX */ ! 1349: /* assert(pte_to_phys(*pte) == phys); */ ! 1350: ! 1351: /* ! 1352: * Invalidate TLBs for all CPUs using this mapping. ! 1353: */ ! 1354: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE); ! 1355: } ! 1356: ! 1357: /* ! 1358: * Remove the mapping if new protection is NONE ! 1359: * or if write-protecting a kernel mapping. ! 1360: */ ! 1361: if (remove || pmap == kernel_pmap) { ! 1362: /* ! 1363: * Remove the mapping, collecting any modify bits. ! 1364: */ ! 1365: if (*pte & INTEL_PTE_WIRED) ! 1366: panic("pmap_remove_all removing a wired page"); ! 1367: ! 1368: { ! 1369: register int i = ptes_per_vm_page; ! 1370: ! 1371: do { ! 1372: pmap_phys_attributes[pai] |= ! 1373: *pte & (PHYS_MODIFIED|PHYS_REFERENCED); ! 1374: *pte++ = 0; ! 1375: } while (--i > 0); ! 1376: } ! 1377: ! 1378: pmap->stats.resident_count--; ! 1379: ! 1380: /* ! 1381: * Remove the pv_entry. ! 1382: */ ! 1383: if (pv_e == pv_h) { ! 1384: /* ! 1385: * Fix up head later. ! 1386: */ ! 1387: pv_h->pmap = PMAP_NULL; ! 1388: } ! 1389: else { ! 1390: /* ! 1391: * Delete this entry. ! 1392: */ ! 1393: prev->next = pv_e->next; ! 1394: PV_FREE(pv_e); ! 1395: } ! 1396: } ! 1397: else { ! 1398: /* ! 1399: * Write-protect. ! 1400: */ ! 1401: register int i = ptes_per_vm_page; ! 1402: ! 1403: do { ! 1404: *pte &= ~INTEL_PTE_WRITE; ! 1405: pte++; ! 1406: } while (--i > 0); ! 1407: ! 1408: /* ! 1409: * Advance prev. ! 1410: */ ! 1411: prev = pv_e; ! 1412: } ! 1413: ! 1414: simple_unlock(&pmap->lock); ! 1415: ! 1416: } while ((pv_e = prev->next) != PV_ENTRY_NULL); ! 1417: ! 1418: /* ! 1419: * If pv_head mapping was removed, fix it up. ! 1420: */ ! 1421: if (pv_h->pmap == PMAP_NULL) { ! 1422: pv_e = pv_h->next; ! 1423: if (pv_e != PV_ENTRY_NULL) { ! 1424: *pv_h = *pv_e; ! 1425: PV_FREE(pv_e); ! 1426: } ! 1427: } ! 1428: } ! 1429: ! 1430: PMAP_WRITE_UNLOCK(spl); ! 1431: } ! 1432: ! 1433: /* ! 1434: * Set the physical protection on the ! 1435: * specified range of this map as requested. ! 1436: * Will not increase permissions. ! 1437: */ ! 1438: void pmap_protect(map, s, e, prot) ! 1439: pmap_t map; ! 1440: vm_offset_t s, e; ! 1441: vm_prot_t prot; ! 1442: { ! 1443: register pt_entry_t *pde; ! 1444: register pt_entry_t *spte, *epte; ! 1445: vm_offset_t l; ! 1446: int spl; ! 1447: ! 1448: if (map == PMAP_NULL) ! 1449: return; ! 1450: ! 1451: /* ! 1452: * Determine the new protection. ! 1453: */ ! 1454: switch (prot) { ! 1455: case VM_PROT_READ: ! 1456: case VM_PROT_READ|VM_PROT_EXECUTE: ! 1457: break; ! 1458: case VM_PROT_READ|VM_PROT_WRITE: ! 1459: case VM_PROT_ALL: ! 1460: return; /* nothing to do */ ! 1461: default: ! 1462: pmap_remove(map, s, e); ! 1463: return; ! 1464: } ! 1465: ! 1466: /* ! 1467: * If write-protecting in the kernel pmap, ! 1468: * remove the mappings; the i386 ignores ! 1469: * the write-permission bit in kernel mode. ! 1470: * ! 1471: * XXX should be #if'd for i386 ! 1472: */ ! 1473: if (map == kernel_pmap) { ! 1474: pmap_remove(map, s, e); ! 1475: return; ! 1476: } ! 1477: ! 1478: SPLVM(spl); ! 1479: simple_lock(&map->lock); ! 1480: ! 1481: /* ! 1482: * Invalidate the translation buffer first ! 1483: */ ! 1484: PMAP_UPDATE_TLBS(map, s, e); ! 1485: ! 1486: pde = pmap_pde(map, s); ! 1487: while (s < e) { ! 1488: l = (s + PDE_MAPPED_SIZE) & ~(PDE_MAPPED_SIZE-1); ! 1489: if (l > e) ! 1490: l = e; ! 1491: if (*pde & INTEL_PTE_VALID) { ! 1492: spte = (pt_entry_t *)ptetokv(*pde); ! 1493: spte = &spte[ptenum(s)]; ! 1494: epte = &spte[intel_btop(l-s)]; ! 1495: ! 1496: while (spte < epte) { ! 1497: if (*spte & INTEL_PTE_VALID) ! 1498: *spte &= ~INTEL_PTE_WRITE; ! 1499: spte++; ! 1500: } ! 1501: } ! 1502: s = l; ! 1503: pde++; ! 1504: } ! 1505: ! 1506: simple_unlock(&map->lock); ! 1507: SPLX(spl); ! 1508: } ! 1509: ! 1510: /* ! 1511: * Insert the given physical page (p) at ! 1512: * the specified virtual address (v) in the ! 1513: * target physical map with the protection requested. ! 1514: * ! 1515: * If specified, the page will be wired down, meaning ! 1516: * that the related pte can not be reclaimed. ! 1517: * ! 1518: * NB: This is the only routine which MAY NOT lazy-evaluate ! 1519: * or lose information. That is, this routine must actually ! 1520: * insert this page into the given map NOW. ! 1521: */ ! 1522: void pmap_enter(pmap, v, pa, prot, wired) ! 1523: register pmap_t pmap; ! 1524: vm_offset_t v; ! 1525: register vm_offset_t pa; ! 1526: vm_prot_t prot; ! 1527: boolean_t wired; ! 1528: { ! 1529: register pt_entry_t *pte; ! 1530: register pv_entry_t pv_h; ! 1531: register int i, pai; ! 1532: pv_entry_t pv_e; ! 1533: pt_entry_t template; ! 1534: int spl; ! 1535: vm_offset_t old_pa; ! 1536: ! 1537: assert(pa != vm_page_fictitious_addr); ! 1538: if (pmap_debug) printf("pmap(%x, %x)\n", v, pa); ! 1539: if (pmap == PMAP_NULL) ! 1540: return; ! 1541: ! 1542: if (pmap == kernel_pmap && (prot & VM_PROT_WRITE) == 0 ! 1543: && !wired /* hack for io_wire */ ) { ! 1544: /* ! 1545: * Because the 386 ignores write protection in kernel mode, ! 1546: * we cannot enter a read-only kernel mapping, and must ! 1547: * remove an existing mapping if changing it. ! 1548: * ! 1549: * XXX should be #if'd for i386 ! 1550: */ ! 1551: PMAP_READ_LOCK(pmap, spl); ! 1552: ! 1553: pte = pmap_pte(pmap, v); ! 1554: if (pte != PT_ENTRY_NULL && *pte != 0) { ! 1555: /* ! 1556: * Invalidate the translation buffer, ! 1557: * then remove the mapping. ! 1558: */ ! 1559: PMAP_UPDATE_TLBS(pmap, v, v + PAGE_SIZE); ! 1560: pmap_remove_range(pmap, v, pte, ! 1561: pte + ptes_per_vm_page); ! 1562: } ! 1563: PMAP_READ_UNLOCK(pmap, spl); ! 1564: return; ! 1565: } ! 1566: ! 1567: /* ! 1568: * Must allocate a new pvlist entry while we're unlocked; ! 1569: * zalloc may cause pageout (which will lock the pmap system). ! 1570: * If we determine we need a pvlist entry, we will unlock ! 1571: * and allocate one. Then we will retry, throughing away ! 1572: * the allocated entry later (if we no longer need it). ! 1573: */ ! 1574: pv_e = PV_ENTRY_NULL; ! 1575: Retry: ! 1576: PMAP_READ_LOCK(pmap, spl); ! 1577: ! 1578: /* ! 1579: * Expand pmap to include this pte. Assume that ! 1580: * pmap is always expanded to include enough hardware ! 1581: * pages to map one VM page. ! 1582: */ ! 1583: ! 1584: while ((pte = pmap_pte(pmap, v)) == PT_ENTRY_NULL) { ! 1585: /* ! 1586: * Need to allocate a new page-table page. ! 1587: */ ! 1588: vm_offset_t ptp; ! 1589: pt_entry_t *pdp; ! 1590: int i; ! 1591: ! 1592: if (pmap == kernel_pmap) { ! 1593: /* ! 1594: * Would have to enter the new page-table page in ! 1595: * EVERY pmap. ! 1596: */ ! 1597: panic("pmap_expand kernel pmap to %#x", v); ! 1598: } ! 1599: ! 1600: /* ! 1601: * Unlock the pmap and allocate a new page-table page. ! 1602: */ ! 1603: PMAP_READ_UNLOCK(pmap, spl); ! 1604: ! 1605: ptp = pmap_page_table_page_alloc(); ! 1606: ! 1607: /* ! 1608: * Re-lock the pmap and check that another thread has ! 1609: * not already allocated the page-table page. If it ! 1610: * has, discard the new page-table page (and try ! 1611: * again to make sure). ! 1612: */ ! 1613: PMAP_READ_LOCK(pmap, spl); ! 1614: ! 1615: if (pmap_pte(pmap, v) != PT_ENTRY_NULL) { ! 1616: /* ! 1617: * Oops... ! 1618: */ ! 1619: PMAP_READ_UNLOCK(pmap, spl); ! 1620: pmap_page_table_page_dealloc(ptp); ! 1621: PMAP_READ_LOCK(pmap, spl); ! 1622: continue; ! 1623: } ! 1624: ! 1625: /* ! 1626: * Enter the new page table page in the page directory. ! 1627: */ ! 1628: i = ptes_per_vm_page; ! 1629: /*XX pdp = &pmap->dirbase[pdenum(v) & ~(i-1)];*/ ! 1630: pdp = pmap_pde(pmap, v); ! 1631: do { ! 1632: *pdp = pa_to_pte(ptp) | INTEL_PTE_VALID ! 1633: | INTEL_PTE_USER ! 1634: | INTEL_PTE_WRITE; ! 1635: pdp++; ! 1636: ptp += INTEL_PGBYTES; ! 1637: } while (--i > 0); ! 1638: #if i860 ! 1639: /* ! 1640: * Flush the data cache. ! 1641: */ ! 1642: flush(); ! 1643: #endif /* i860 */ ! 1644: ! 1645: /* ! 1646: * Now, get the address of the page-table entry. ! 1647: */ ! 1648: continue; ! 1649: } ! 1650: ! 1651: /* ! 1652: * Special case if the physical page is already mapped ! 1653: * at this address. ! 1654: */ ! 1655: old_pa = pte_to_pa(*pte); ! 1656: if (*pte && old_pa == pa) { ! 1657: /* ! 1658: * May be changing its wired attribute or protection ! 1659: */ ! 1660: ! 1661: if (wired && !(*pte & INTEL_PTE_WIRED)) ! 1662: pmap->stats.wired_count++; ! 1663: else if (!wired && (*pte & INTEL_PTE_WIRED)) ! 1664: pmap->stats.wired_count--; ! 1665: ! 1666: template = pa_to_pte(pa) | INTEL_PTE_VALID; ! 1667: if (pmap != kernel_pmap) ! 1668: template |= INTEL_PTE_USER; ! 1669: if (prot & VM_PROT_WRITE) ! 1670: template |= INTEL_PTE_WRITE; ! 1671: if (wired) ! 1672: template |= INTEL_PTE_WIRED; ! 1673: PMAP_UPDATE_TLBS(pmap, v, v + PAGE_SIZE); ! 1674: i = ptes_per_vm_page; ! 1675: do { ! 1676: if (*pte & INTEL_PTE_MOD) ! 1677: template |= INTEL_PTE_MOD; ! 1678: WRITE_PTE(pte, template) ! 1679: pte++; ! 1680: pte_increment_pa(template); ! 1681: } while (--i > 0); ! 1682: } ! 1683: else { ! 1684: ! 1685: /* ! 1686: * Remove old mapping from the PV list if necessary. ! 1687: */ ! 1688: if (*pte) { ! 1689: /* ! 1690: * Invalidate the translation buffer, ! 1691: * then remove the mapping. ! 1692: */ ! 1693: PMAP_UPDATE_TLBS(pmap, v, v + PAGE_SIZE); ! 1694: ! 1695: /* ! 1696: * Don't free the pte page if removing last ! 1697: * mapping - we will immediately replace it. ! 1698: */ ! 1699: pmap_remove_range(pmap, v, pte, ! 1700: pte + ptes_per_vm_page); ! 1701: } ! 1702: ! 1703: if (valid_page(pa)) { ! 1704: ! 1705: /* ! 1706: * Enter the mapping in the PV list for this ! 1707: * physical page. ! 1708: */ ! 1709: ! 1710: pai = pa_index(pa); ! 1711: LOCK_PVH(pai); ! 1712: pv_h = pai_to_pvh(pai); ! 1713: ! 1714: if (pv_h->pmap == PMAP_NULL) { ! 1715: /* ! 1716: * No mappings yet ! 1717: */ ! 1718: pv_h->va = v; ! 1719: pv_h->pmap = pmap; ! 1720: pv_h->next = PV_ENTRY_NULL; ! 1721: } ! 1722: else { ! 1723: #if DEBUG ! 1724: { ! 1725: /* check that this mapping is not already there */ ! 1726: pv_entry_t e = pv_h; ! 1727: while (e != PV_ENTRY_NULL) { ! 1728: if (e->pmap == pmap && e->va == v) ! 1729: panic("pmap_enter: already in pv_list"); ! 1730: e = e->next; ! 1731: } ! 1732: } ! 1733: #endif DEBUG ! 1734: ! 1735: /* ! 1736: * Add new pv_entry after header. ! 1737: */ ! 1738: if (pv_e == PV_ENTRY_NULL) { ! 1739: PV_ALLOC(pv_e); ! 1740: if (pv_e == PV_ENTRY_NULL) { ! 1741: UNLOCK_PVH(pai); ! 1742: PMAP_READ_UNLOCK(pmap, spl); ! 1743: ! 1744: /* ! 1745: * Refill from zone. ! 1746: */ ! 1747: pv_e = (pv_entry_t) zalloc(pv_list_zone); ! 1748: goto Retry; ! 1749: } ! 1750: } ! 1751: pv_e->va = v; ! 1752: pv_e->pmap = pmap; ! 1753: pv_e->next = pv_h->next; ! 1754: pv_h->next = pv_e; ! 1755: /* ! 1756: * Remember that we used the pvlist entry. ! 1757: */ ! 1758: pv_e = PV_ENTRY_NULL; ! 1759: } ! 1760: UNLOCK_PVH(pai); ! 1761: } ! 1762: ! 1763: /* ! 1764: * And count the mapping. ! 1765: */ ! 1766: ! 1767: pmap->stats.resident_count++; ! 1768: if (wired) ! 1769: pmap->stats.wired_count++; ! 1770: ! 1771: /* ! 1772: * Build a template to speed up entering - ! 1773: * only the pfn changes. ! 1774: */ ! 1775: template = pa_to_pte(pa) | INTEL_PTE_VALID; ! 1776: if (pmap != kernel_pmap) ! 1777: template |= INTEL_PTE_USER; ! 1778: if (prot & VM_PROT_WRITE) ! 1779: template |= INTEL_PTE_WRITE; ! 1780: if (wired) ! 1781: template |= INTEL_PTE_WIRED; ! 1782: i = ptes_per_vm_page; ! 1783: do { ! 1784: WRITE_PTE(pte, template) ! 1785: pte++; ! 1786: pte_increment_pa(template); ! 1787: } while (--i > 0); ! 1788: } ! 1789: ! 1790: if (pv_e != PV_ENTRY_NULL) { ! 1791: PV_FREE(pv_e); ! 1792: } ! 1793: ! 1794: PMAP_READ_UNLOCK(pmap, spl); ! 1795: } ! 1796: ! 1797: /* ! 1798: * Routine: pmap_change_wiring ! 1799: * Function: Change the wiring attribute for a map/virtual-address ! 1800: * pair. ! 1801: * In/out conditions: ! 1802: * The mapping must already exist in the pmap. ! 1803: */ ! 1804: void pmap_change_wiring(map, v, wired) ! 1805: register pmap_t map; ! 1806: vm_offset_t v; ! 1807: boolean_t wired; ! 1808: { ! 1809: register pt_entry_t *pte; ! 1810: register int i; ! 1811: int spl; ! 1812: ! 1813: /* ! 1814: * We must grab the pmap system lock because we may ! 1815: * change a pte_page queue. ! 1816: */ ! 1817: PMAP_READ_LOCK(map, spl); ! 1818: ! 1819: if ((pte = pmap_pte(map, v)) == PT_ENTRY_NULL) ! 1820: panic("pmap_change_wiring: pte missing"); ! 1821: ! 1822: if (wired && !(*pte & INTEL_PTE_WIRED)) { ! 1823: /* ! 1824: * wiring down mapping ! 1825: */ ! 1826: map->stats.wired_count++; ! 1827: i = ptes_per_vm_page; ! 1828: do { ! 1829: *pte++ |= INTEL_PTE_WIRED; ! 1830: } while (--i > 0); ! 1831: } ! 1832: else if (!wired && (*pte & INTEL_PTE_WIRED)) { ! 1833: /* ! 1834: * unwiring mapping ! 1835: */ ! 1836: map->stats.wired_count--; ! 1837: i = ptes_per_vm_page; ! 1838: do { ! 1839: *pte &= ~INTEL_PTE_WIRED; ! 1840: } while (--i > 0); ! 1841: } ! 1842: ! 1843: PMAP_READ_UNLOCK(map, spl); ! 1844: } ! 1845: ! 1846: /* ! 1847: * Routine: pmap_extract ! 1848: * Function: ! 1849: * Extract the physical page address associated ! 1850: * with the given map/virtual_address pair. ! 1851: */ ! 1852: ! 1853: vm_offset_t pmap_extract(pmap, va) ! 1854: register pmap_t pmap; ! 1855: vm_offset_t va; ! 1856: { ! 1857: register pt_entry_t *pte; ! 1858: register vm_offset_t pa; ! 1859: int spl; ! 1860: ! 1861: SPLVM(spl); ! 1862: simple_lock(&pmap->lock); ! 1863: if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL) ! 1864: pa = (vm_offset_t) 0; ! 1865: else if (!(*pte & INTEL_PTE_VALID)) ! 1866: pa = (vm_offset_t) 0; ! 1867: else ! 1868: pa = pte_to_pa(*pte) + (va & INTEL_OFFMASK); ! 1869: simple_unlock(&pmap->lock); ! 1870: SPLX(spl); ! 1871: return(pa); ! 1872: } ! 1873: ! 1874: /* ! 1875: * Copy the range specified by src_addr/len ! 1876: * from the source map to the range dst_addr/len ! 1877: * in the destination map. ! 1878: * ! 1879: * This routine is only advisory and need not do anything. ! 1880: */ ! 1881: #if 0 ! 1882: void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr) ! 1883: pmap_t dst_pmap; ! 1884: pmap_t src_pmap; ! 1885: vm_offset_t dst_addr; ! 1886: vm_size_t len; ! 1887: vm_offset_t src_addr; ! 1888: { ! 1889: #ifdef lint ! 1890: dst_pmap++; src_pmap++; dst_addr++; len++; src_addr++; ! 1891: #endif lint ! 1892: } ! 1893: #endif 0 ! 1894: ! 1895: /* ! 1896: * Routine: pmap_collect ! 1897: * Function: ! 1898: * Garbage collects the physical map system for ! 1899: * pages which are no longer used. ! 1900: * Success need not be guaranteed -- that is, there ! 1901: * may well be pages which are not referenced, but ! 1902: * others may be collected. ! 1903: * Usage: ! 1904: * Called by the pageout daemon when pages are scarce. ! 1905: */ ! 1906: void pmap_collect(p) ! 1907: pmap_t p; ! 1908: { ! 1909: register pt_entry_t *pdp, *ptp; ! 1910: pt_entry_t *eptp; ! 1911: vm_offset_t pa; ! 1912: int spl, wired; ! 1913: ! 1914: if (p == PMAP_NULL) ! 1915: return; ! 1916: ! 1917: if (p == kernel_pmap) ! 1918: return; ! 1919: ! 1920: /* ! 1921: * Garbage collect map. ! 1922: */ ! 1923: PMAP_READ_LOCK(p, spl); ! 1924: PMAP_UPDATE_TLBS(p, VM_MIN_ADDRESS, VM_MAX_ADDRESS); ! 1925: ! 1926: for (pdp = p->dirbase; ! 1927: pdp < &p->dirbase[lin2pdenum(LINEAR_MIN_KERNEL_ADDRESS)]; ! 1928: pdp += ptes_per_vm_page) ! 1929: { ! 1930: if (*pdp & INTEL_PTE_VALID) { ! 1931: ! 1932: pa = pte_to_pa(*pdp); ! 1933: ptp = (pt_entry_t *)phystokv(pa); ! 1934: eptp = ptp + NPTES*ptes_per_vm_page; ! 1935: ! 1936: /* ! 1937: * If the pte page has any wired mappings, we cannot ! 1938: * free it. ! 1939: */ ! 1940: wired = 0; ! 1941: { ! 1942: register pt_entry_t *ptep; ! 1943: for (ptep = ptp; ptep < eptp; ptep++) { ! 1944: if (*ptep & INTEL_PTE_WIRED) { ! 1945: wired = 1; ! 1946: break; ! 1947: } ! 1948: } ! 1949: } ! 1950: if (!wired) { ! 1951: /* ! 1952: * Remove the virtual addresses mapped by this pte page. ! 1953: */ ! 1954: { /*XXX big hack*/ ! 1955: vm_offset_t va = pdenum2lin(pdp - p->dirbase); ! 1956: if (p == kernel_pmap) ! 1957: va = lintokv(va); ! 1958: pmap_remove_range(p, ! 1959: va, ! 1960: ptp, ! 1961: eptp); ! 1962: } ! 1963: ! 1964: /* ! 1965: * Invalidate the page directory pointer. ! 1966: */ ! 1967: { ! 1968: register int i = ptes_per_vm_page; ! 1969: register pt_entry_t *pdep = pdp; ! 1970: do { ! 1971: *pdep++ = 0; ! 1972: } while (--i > 0); ! 1973: } ! 1974: ! 1975: PMAP_READ_UNLOCK(p, spl); ! 1976: ! 1977: /* ! 1978: * And free the pte page itself. ! 1979: */ ! 1980: { ! 1981: register vm_page_t m; ! 1982: ! 1983: vm_object_lock(pmap_object); ! 1984: m = vm_page_lookup(pmap_object, pa); ! 1985: if (m == VM_PAGE_NULL) ! 1986: panic("pmap_collect: pte page not in object"); ! 1987: vm_page_lock_queues(); ! 1988: vm_page_free(m); ! 1989: inuse_ptepages_count--; ! 1990: vm_page_unlock_queues(); ! 1991: vm_object_unlock(pmap_object); ! 1992: } ! 1993: ! 1994: PMAP_READ_LOCK(p, spl); ! 1995: } ! 1996: } ! 1997: } ! 1998: PMAP_READ_UNLOCK(p, spl); ! 1999: return; ! 2000: ! 2001: } ! 2002: ! 2003: /* ! 2004: * Routine: pmap_activate ! 2005: * Function: ! 2006: * Binds the given physical map to the given ! 2007: * processor, and returns a hardware map description. ! 2008: */ ! 2009: #if 0 ! 2010: void pmap_activate(my_pmap, th, my_cpu) ! 2011: register pmap_t my_pmap; ! 2012: thread_t th; ! 2013: int my_cpu; ! 2014: { ! 2015: PMAP_ACTIVATE(my_pmap, th, my_cpu); ! 2016: } ! 2017: #endif 0 ! 2018: ! 2019: /* ! 2020: * Routine: pmap_deactivate ! 2021: * Function: ! 2022: * Indicates that the given physical map is no longer ! 2023: * in use on the specified processor. (This is a macro ! 2024: * in pmap.h) ! 2025: */ ! 2026: #if 0 ! 2027: void pmap_deactivate(pmap, th, which_cpu) ! 2028: pmap_t pmap; ! 2029: thread_t th; ! 2030: int which_cpu; ! 2031: { ! 2032: #ifdef lint ! 2033: pmap++; th++; which_cpu++; ! 2034: #endif lint ! 2035: PMAP_DEACTIVATE(pmap, th, which_cpu); ! 2036: } ! 2037: #endif 0 ! 2038: ! 2039: /* ! 2040: * Routine: pmap_kernel ! 2041: * Function: ! 2042: * Returns the physical map handle for the kernel. ! 2043: */ ! 2044: #if 0 ! 2045: pmap_t pmap_kernel() ! 2046: { ! 2047: return (kernel_pmap); ! 2048: } ! 2049: #endif 0 ! 2050: ! 2051: /* ! 2052: * pmap_zero_page zeros the specified (machine independent) page. ! 2053: * See machine/phys.c or machine/phys.s for implementation. ! 2054: */ ! 2055: #if 0 ! 2056: pmap_zero_page(phys) ! 2057: register vm_offset_t phys; ! 2058: { ! 2059: register int i; ! 2060: ! 2061: assert(phys != vm_page_fictitious_addr); ! 2062: i = PAGE_SIZE / INTEL_PGBYTES; ! 2063: phys = intel_pfn(phys); ! 2064: ! 2065: while (i--) ! 2066: zero_phys(phys++); ! 2067: } ! 2068: #endif 0 ! 2069: ! 2070: /* ! 2071: * pmap_copy_page copies the specified (machine independent) page. ! 2072: * See machine/phys.c or machine/phys.s for implementation. ! 2073: */ ! 2074: #if 0 ! 2075: pmap_copy_page(src, dst) ! 2076: vm_offset_t src, dst; ! 2077: { ! 2078: int i; ! 2079: ! 2080: assert(src != vm_page_fictitious_addr); ! 2081: assert(dst != vm_page_fictitious_addr); ! 2082: i = PAGE_SIZE / INTEL_PGBYTES; ! 2083: ! 2084: while (i--) { ! 2085: copy_phys(intel_pfn(src), intel_pfn(dst)); ! 2086: src += INTEL_PGBYTES; ! 2087: dst += INTEL_PGBYTES; ! 2088: } ! 2089: } ! 2090: #endif 0 ! 2091: ! 2092: /* ! 2093: * Routine: pmap_pageable ! 2094: * Function: ! 2095: * Make the specified pages (by pmap, offset) ! 2096: * pageable (or not) as requested. ! 2097: * ! 2098: * A page which is not pageable may not take ! 2099: * a fault; therefore, its page table entry ! 2100: * must remain valid for the duration. ! 2101: * ! 2102: * This routine is merely advisory; pmap_enter ! 2103: * will specify that these pages are to be wired ! 2104: * down (or not) as appropriate. ! 2105: */ ! 2106: pmap_pageable(pmap, start, end, pageable) ! 2107: pmap_t pmap; ! 2108: vm_offset_t start; ! 2109: vm_offset_t end; ! 2110: boolean_t pageable; ! 2111: { ! 2112: #ifdef lint ! 2113: pmap++; start++; end++; pageable++; ! 2114: #endif lint ! 2115: } ! 2116: ! 2117: /* ! 2118: * Clear specified attribute bits. ! 2119: */ ! 2120: void ! 2121: phys_attribute_clear(phys, bits) ! 2122: vm_offset_t phys; ! 2123: int bits; ! 2124: { ! 2125: pv_entry_t pv_h; ! 2126: register pv_entry_t pv_e; ! 2127: register pt_entry_t *pte; ! 2128: int pai; ! 2129: register pmap_t pmap; ! 2130: int spl; ! 2131: ! 2132: assert(phys != vm_page_fictitious_addr); ! 2133: if (!valid_page(phys)) { ! 2134: /* ! 2135: * Not a managed page. ! 2136: */ ! 2137: return; ! 2138: } ! 2139: ! 2140: /* ! 2141: * Lock the pmap system first, since we will be changing ! 2142: * several pmaps. ! 2143: */ ! 2144: ! 2145: PMAP_WRITE_LOCK(spl); ! 2146: ! 2147: pai = pa_index(phys); ! 2148: pv_h = pai_to_pvh(pai); ! 2149: ! 2150: /* ! 2151: * Walk down PV list, clearing all modify or reference bits. ! 2152: * We do not have to lock the pv_list because we have ! 2153: * the entire pmap system locked. ! 2154: */ ! 2155: if (pv_h->pmap != PMAP_NULL) { ! 2156: /* ! 2157: * There are some mappings. ! 2158: */ ! 2159: for (pv_e = pv_h; pv_e != PV_ENTRY_NULL; pv_e = pv_e->next) { ! 2160: ! 2161: pmap = pv_e->pmap; ! 2162: /* ! 2163: * Lock the pmap to block pmap_extract and similar routines. ! 2164: */ ! 2165: simple_lock(&pmap->lock); ! 2166: ! 2167: { ! 2168: register vm_offset_t va; ! 2169: ! 2170: va = pv_e->va; ! 2171: pte = pmap_pte(pmap, va); ! 2172: ! 2173: #if 0 ! 2174: /* ! 2175: * Consistency checks. ! 2176: */ ! 2177: assert(*pte & INTEL_PTE_VALID); ! 2178: /* assert(pte_to_phys(*pte) == phys); */ ! 2179: #endif ! 2180: ! 2181: /* ! 2182: * Invalidate TLBs for all CPUs using this mapping. ! 2183: */ ! 2184: PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE); ! 2185: } ! 2186: ! 2187: /* ! 2188: * Clear modify or reference bits. ! 2189: */ ! 2190: { ! 2191: register int i = ptes_per_vm_page; ! 2192: do { ! 2193: *pte &= ~bits; ! 2194: } while (--i > 0); ! 2195: } ! 2196: simple_unlock(&pmap->lock); ! 2197: } ! 2198: } ! 2199: ! 2200: pmap_phys_attributes[pai] &= ~bits; ! 2201: ! 2202: PMAP_WRITE_UNLOCK(spl); ! 2203: } ! 2204: ! 2205: /* ! 2206: * Check specified attribute bits. ! 2207: */ ! 2208: boolean_t ! 2209: phys_attribute_test(phys, bits) ! 2210: vm_offset_t phys; ! 2211: int bits; ! 2212: { ! 2213: pv_entry_t pv_h; ! 2214: register pv_entry_t pv_e; ! 2215: register pt_entry_t *pte; ! 2216: int pai; ! 2217: register pmap_t pmap; ! 2218: int spl; ! 2219: ! 2220: assert(phys != vm_page_fictitious_addr); ! 2221: if (!valid_page(phys)) { ! 2222: /* ! 2223: * Not a managed page. ! 2224: */ ! 2225: return (FALSE); ! 2226: } ! 2227: ! 2228: /* ! 2229: * Lock the pmap system first, since we will be checking ! 2230: * several pmaps. ! 2231: */ ! 2232: ! 2233: PMAP_WRITE_LOCK(spl); ! 2234: ! 2235: pai = pa_index(phys); ! 2236: pv_h = pai_to_pvh(pai); ! 2237: ! 2238: if (pmap_phys_attributes[pai] & bits) { ! 2239: PMAP_WRITE_UNLOCK(spl); ! 2240: return (TRUE); ! 2241: } ! 2242: ! 2243: /* ! 2244: * Walk down PV list, checking all mappings. ! 2245: * We do not have to lock the pv_list because we have ! 2246: * the entire pmap system locked. ! 2247: */ ! 2248: if (pv_h->pmap != PMAP_NULL) { ! 2249: /* ! 2250: * There are some mappings. ! 2251: */ ! 2252: for (pv_e = pv_h; pv_e != PV_ENTRY_NULL; pv_e = pv_e->next) { ! 2253: ! 2254: pmap = pv_e->pmap; ! 2255: /* ! 2256: * Lock the pmap to block pmap_extract and similar routines. ! 2257: */ ! 2258: simple_lock(&pmap->lock); ! 2259: ! 2260: { ! 2261: register vm_offset_t va; ! 2262: ! 2263: va = pv_e->va; ! 2264: pte = pmap_pte(pmap, va); ! 2265: ! 2266: #if 0 ! 2267: /* ! 2268: * Consistency checks. ! 2269: */ ! 2270: assert(*pte & INTEL_PTE_VALID); ! 2271: /* assert(pte_to_phys(*pte) == phys); */ ! 2272: #endif ! 2273: } ! 2274: ! 2275: /* ! 2276: * Check modify or reference bits. ! 2277: */ ! 2278: { ! 2279: register int i = ptes_per_vm_page; ! 2280: ! 2281: do { ! 2282: if (*pte & bits) { ! 2283: simple_unlock(&pmap->lock); ! 2284: PMAP_WRITE_UNLOCK(spl); ! 2285: return (TRUE); ! 2286: } ! 2287: } while (--i > 0); ! 2288: } ! 2289: simple_unlock(&pmap->lock); ! 2290: } ! 2291: } ! 2292: PMAP_WRITE_UNLOCK(spl); ! 2293: return (FALSE); ! 2294: } ! 2295: ! 2296: /* ! 2297: * Clear the modify bits on the specified physical page. ! 2298: */ ! 2299: ! 2300: void pmap_clear_modify(phys) ! 2301: register vm_offset_t phys; ! 2302: { ! 2303: phys_attribute_clear(phys, PHYS_MODIFIED); ! 2304: } ! 2305: ! 2306: /* ! 2307: * pmap_is_modified: ! 2308: * ! 2309: * Return whether or not the specified physical page is modified ! 2310: * by any physical maps. ! 2311: */ ! 2312: ! 2313: boolean_t pmap_is_modified(phys) ! 2314: register vm_offset_t phys; ! 2315: { ! 2316: return (phys_attribute_test(phys, PHYS_MODIFIED)); ! 2317: } ! 2318: ! 2319: /* ! 2320: * pmap_clear_reference: ! 2321: * ! 2322: * Clear the reference bit on the specified physical page. ! 2323: */ ! 2324: ! 2325: void pmap_clear_reference(phys) ! 2326: vm_offset_t phys; ! 2327: { ! 2328: phys_attribute_clear(phys, PHYS_REFERENCED); ! 2329: } ! 2330: ! 2331: /* ! 2332: * pmap_is_referenced: ! 2333: * ! 2334: * Return whether or not the specified physical page is referenced ! 2335: * by any physical maps. ! 2336: */ ! 2337: ! 2338: boolean_t pmap_is_referenced(phys) ! 2339: vm_offset_t phys; ! 2340: { ! 2341: return (phys_attribute_test(phys, PHYS_REFERENCED)); ! 2342: } ! 2343: ! 2344: #if NCPUS > 1 ! 2345: /* ! 2346: * TLB Coherence Code (TLB "shootdown" code) ! 2347: * ! 2348: * Threads that belong to the same task share the same address space and ! 2349: * hence share a pmap. However, they may run on distinct cpus and thus ! 2350: * have distinct TLBs that cache page table entries. In order to guarantee ! 2351: * the TLBs are consistent, whenever a pmap is changed, all threads that ! 2352: * are active in that pmap must have their TLB updated. To keep track of ! 2353: * this information, the set of cpus that are currently using a pmap is ! 2354: * maintained within each pmap structure (cpus_using). Pmap_activate() and ! 2355: * pmap_deactivate add and remove, respectively, a cpu from this set. ! 2356: * Since the TLBs are not addressable over the bus, each processor must ! 2357: * flush its own TLB; a processor that needs to invalidate another TLB ! 2358: * needs to interrupt the processor that owns that TLB to signal the ! 2359: * update. ! 2360: * ! 2361: * Whenever a pmap is updated, the lock on that pmap is locked, and all ! 2362: * cpus using the pmap are signaled to invalidate. All threads that need ! 2363: * to activate a pmap must wait for the lock to clear to await any updates ! 2364: * in progress before using the pmap. They must ACQUIRE the lock to add ! 2365: * their cpu to the cpus_using set. An implicit assumption made ! 2366: * throughout the TLB code is that all kernel code that runs at or higher ! 2367: * than splvm blocks out update interrupts, and that such code does not ! 2368: * touch pageable pages. ! 2369: * ! 2370: * A shootdown interrupt serves another function besides signaling a ! 2371: * processor to invalidate. The interrupt routine (pmap_update_interrupt) ! 2372: * waits for the both the pmap lock (and the kernel pmap lock) to clear, ! 2373: * preventing user code from making implicit pmap updates while the ! 2374: * sending processor is performing its update. (This could happen via a ! 2375: * user data write reference that turns on the modify bit in the page ! 2376: * table). It must wait for any kernel updates that may have started ! 2377: * concurrently with a user pmap update because the IPC code ! 2378: * changes mappings. ! 2379: * Spinning on the VALUES of the locks is sufficient (rather than ! 2380: * having to acquire the locks) because any updates that occur subsequent ! 2381: * to finding the lock unlocked will be signaled via another interrupt. ! 2382: * (This assumes the interrupt is cleared before the low level interrupt code ! 2383: * calls pmap_update_interrupt()). ! 2384: * ! 2385: * The signaling processor must wait for any implicit updates in progress ! 2386: * to terminate before continuing with its update. Thus it must wait for an ! 2387: * acknowledgement of the interrupt from each processor for which such ! 2388: * references could be made. For maintaining this information, a set ! 2389: * cpus_active is used. A cpu is in this set if and only if it can ! 2390: * use a pmap. When pmap_update_interrupt() is entered, a cpu is removed from ! 2391: * this set; when all such cpus are removed, it is safe to update. ! 2392: * ! 2393: * Before attempting to acquire the update lock on a pmap, a cpu (A) must ! 2394: * be at least at the priority of the interprocessor interrupt ! 2395: * (splip<=splvm). Otherwise, A could grab a lock and be interrupted by a ! 2396: * kernel update; it would spin forever in pmap_update_interrupt() trying ! 2397: * to acquire the user pmap lock it had already acquired. Furthermore A ! 2398: * must remove itself from cpus_active. Otherwise, another cpu holding ! 2399: * the lock (B) could be in the process of sending an update signal to A, ! 2400: * and thus be waiting for A to remove itself from cpus_active. If A is ! 2401: * spinning on the lock at priority this will never happen and a deadlock ! 2402: * will result. ! 2403: */ ! 2404: ! 2405: /* ! 2406: * Signal another CPU that it must flush its TLB ! 2407: */ ! 2408: void signal_cpus(use_list, pmap, start, end) ! 2409: cpu_set use_list; ! 2410: pmap_t pmap; ! 2411: vm_offset_t start, end; ! 2412: { ! 2413: register int which_cpu, j; ! 2414: register pmap_update_list_t update_list_p; ! 2415: ! 2416: while ((which_cpu = ffs(use_list)) != 0) { ! 2417: which_cpu -= 1; /* convert to 0 origin */ ! 2418: ! 2419: update_list_p = &cpu_update_list[which_cpu]; ! 2420: simple_lock(&update_list_p->lock); ! 2421: ! 2422: j = update_list_p->count; ! 2423: if (j >= UPDATE_LIST_SIZE) { ! 2424: /* ! 2425: * list overflowed. Change last item to ! 2426: * indicate overflow. ! 2427: */ ! 2428: update_list_p->item[UPDATE_LIST_SIZE-1].pmap = kernel_pmap; ! 2429: update_list_p->item[UPDATE_LIST_SIZE-1].start = VM_MIN_ADDRESS; ! 2430: update_list_p->item[UPDATE_LIST_SIZE-1].end = VM_MAX_KERNEL_ADDRESS; ! 2431: } ! 2432: else { ! 2433: update_list_p->item[j].pmap = pmap; ! 2434: update_list_p->item[j].start = start; ! 2435: update_list_p->item[j].end = end; ! 2436: update_list_p->count = j+1; ! 2437: } ! 2438: cpu_update_needed[which_cpu] = TRUE; ! 2439: simple_unlock(&update_list_p->lock); ! 2440: ! 2441: if ((cpus_idle & (1 << which_cpu)) == 0) ! 2442: interrupt_processor(which_cpu); ! 2443: use_list &= ~(1 << which_cpu); ! 2444: } ! 2445: } ! 2446: ! 2447: void process_pmap_updates(my_pmap) ! 2448: register pmap_t my_pmap; ! 2449: { ! 2450: register int my_cpu = cpu_number(); ! 2451: register pmap_update_list_t update_list_p; ! 2452: register int j; ! 2453: register pmap_t pmap; ! 2454: ! 2455: update_list_p = &cpu_update_list[my_cpu]; ! 2456: simple_lock(&update_list_p->lock); ! 2457: ! 2458: for (j = 0; j < update_list_p->count; j++) { ! 2459: pmap = update_list_p->item[j].pmap; ! 2460: if (pmap == my_pmap || ! 2461: pmap == kernel_pmap) { ! 2462: ! 2463: INVALIDATE_TLB(update_list_p->item[j].start, ! 2464: update_list_p->item[j].end); ! 2465: } ! 2466: } ! 2467: update_list_p->count = 0; ! 2468: cpu_update_needed[my_cpu] = FALSE; ! 2469: simple_unlock(&update_list_p->lock); ! 2470: } ! 2471: ! 2472: /* ! 2473: * Interrupt routine for TBIA requested from other processor. ! 2474: */ ! 2475: void pmap_update_interrupt() ! 2476: { ! 2477: register int my_cpu; ! 2478: register pmap_t my_pmap; ! 2479: int s; ! 2480: ! 2481: my_cpu = cpu_number(); ! 2482: ! 2483: /* ! 2484: * Exit now if we're idle. We'll pick up the update request ! 2485: * when we go active, and we must not put ourselves back in ! 2486: * the active set because we'll never process the interrupt ! 2487: * while we're idle (thus hanging the system). ! 2488: */ ! 2489: if (cpus_idle & (1 << my_cpu)) ! 2490: return; ! 2491: ! 2492: if (current_thread() == THREAD_NULL) ! 2493: my_pmap = kernel_pmap; ! 2494: else { ! 2495: my_pmap = current_pmap(); ! 2496: if (!pmap_in_use(my_pmap, my_cpu)) ! 2497: my_pmap = kernel_pmap; ! 2498: } ! 2499: ! 2500: /* ! 2501: * Raise spl to splvm (above splip) to block out pmap_extract ! 2502: * from IO code (which would put this cpu back in the active ! 2503: * set). ! 2504: */ ! 2505: s = splvm(); ! 2506: ! 2507: do { ! 2508: ! 2509: /* ! 2510: * Indicate that we're not using either user or kernel ! 2511: * pmap. ! 2512: */ ! 2513: i_bit_clear(my_cpu, &cpus_active); ! 2514: ! 2515: /* ! 2516: * Wait for any pmap updates in progress, on either user ! 2517: * or kernel pmap. ! 2518: */ ! 2519: while (*(volatile int *)&my_pmap->lock.lock_data || ! 2520: *(volatile int *)&kernel_pmap->lock.lock_data) ! 2521: continue; ! 2522: ! 2523: process_pmap_updates(my_pmap); ! 2524: ! 2525: i_bit_set(my_cpu, &cpus_active); ! 2526: ! 2527: } while (cpu_update_needed[my_cpu]); ! 2528: ! 2529: splx(s); ! 2530: } ! 2531: #else NCPUS > 1 ! 2532: /* ! 2533: * Dummy routine to satisfy external reference. ! 2534: */ ! 2535: void pmap_update_interrupt() ! 2536: { ! 2537: /* should never be called. */ ! 2538: } ! 2539: #endif NCPUS > 1 ! 2540: ! 2541: #if i860 /* akp */ ! 2542: void set_dirbase(dirbase) ! 2543: register vm_offset_t dirbase; ! 2544: { ! 2545: /*flush();*/ ! 2546: /*flush_tlb();*/ ! 2547: flush_and_ctxsw(dirbase); ! 2548: } ! 2549: #endif i860 ! 2550: ! 2551: #ifdef i386 ! 2552: /* Unmap page 0 to trap NULL references. */ ! 2553: void ! 2554: pmap_unmap_page_zero () ! 2555: { ! 2556: int *pte; ! 2557: ! 2558: pte = (int *) pmap_pte (kernel_pmap, 0); ! 2559: assert (pte); ! 2560: *pte = 0; ! 2561: asm volatile ("movl %%cr3,%%eax; movl %%eax,%%cr3" ::: "ax"); ! 2562: } ! 2563: #endif /* i386 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.