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