Annotation of XNU/osfmk/i386/pmap.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /*
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  */
                     52: 
                     53: /*
                     54:  *     File:   pmap.c
                     55:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     56:  *     (These guys wrote the Vax version)
                     57:  *
                     58:  *     Physical Map management code for Intel i386, i486, and i860.
                     59:  *
                     60:  *     Manages physical address maps.
                     61:  *
                     62:  *     In addition to hardware address maps, this
                     63:  *     module is called upon to provide software-use-only
                     64:  *     maps which may or may not be stored in the same
                     65:  *     form as hardware maps.  These pseudo-maps are
                     66:  *     used to store intermediate results from copy
                     67:  *     operations to and from address spaces.
                     68:  *
                     69:  *     Since the information managed by this module is
                     70:  *     also stored by the logical address mapping module,
                     71:  *     this module may throw away valid virtual-to-physical
                     72:  *     mappings at almost any time.  However, invalidations
                     73:  *     of virtual-to-physical mappings must be done as
                     74:  *     requested.
                     75:  *
                     76:  *     In order to cope with hardware architectures which
                     77:  *     make virtual-to-physical map invalidates expensive,
                     78:  *     this module may delay invalidate or reduced protection
                     79:  *     operations until such time as they are actually
                     80:  *     necessary.  This module is given full information as
                     81:  *     to which processors are currently using which maps,
                     82:  *     and to when physical maps must be made correct.
                     83:  */
                     84: 
                     85: #include <cpus.h>
                     86: 
                     87: #include <string.h>
                     88: #include <norma_vm.h>
                     89: #include <mach_kdb.h>
                     90: #include <mach_ldebug.h>
                     91: 
                     92: #include <mach/machine/vm_types.h>
                     93: 
                     94: #include <mach/boolean.h>
                     95: #include <kern/thread.h>
                     96: #include <kern/zalloc.h>
                     97: 
                     98: #include <kern/lock.h>
                     99: #include <kern/spl.h>
                    100: 
                    101: #include <vm/pmap.h>
                    102: #include <vm/vm_map.h>
                    103: #include <vm/vm_kern.h>
                    104: #include <mach/vm_param.h>
                    105: #include <mach/vm_prot.h>
                    106: #include <vm/vm_object.h>
                    107: #include <vm/vm_page.h>
                    108: #include <vm/vm_user.h>
                    109: 
                    110: #include <mach/machine/vm_param.h>
                    111: #include <machine/thread.h>
                    112: 
                    113: #include <kern/misc_protos.h>                  /* prototyping */
                    114: #include <i386/misc_protos.h>
                    115: 
                    116: #include <i386/cpuid.h>
                    117: 
                    118: #if    MACH_KDB
                    119: #include <ddb/db_command.h>
                    120: #include <ddb/db_output.h>
                    121: #include <ddb/db_sym.h>
                    122: #include <ddb/db_print.h>
                    123: #endif /* MACH_KDB */
                    124: 
                    125: #include <kern/xpr.h>
                    126: 
                    127: #if NCPUS > 1
                    128: #include <i386/AT386/mp/mp_events.h>
                    129: #endif
                    130: 
                    131: /*
                    132:  * Forward declarations for internal functions.
                    133:  */
                    134: void   pmap_expand(
                    135:                        pmap_t          map,
                    136:                        vm_offset_t     v);
                    137: 
                    138: extern void    pmap_remove_range(
                    139:                        pmap_t          pmap,
                    140:                        vm_offset_t     va,
                    141:                        pt_entry_t      *spte,
                    142:                        pt_entry_t      *epte);
                    143: 
                    144: void   phys_attribute_clear(
                    145:                        vm_offset_t     phys,
                    146:                        int             bits);
                    147: 
                    148: boolean_t phys_attribute_test(
                    149:                        vm_offset_t     phys,
                    150:                        int             bits);
                    151: 
                    152: void pmap_set_modify(vm_offset_t       phys);
                    153: 
                    154: void phys_attribute_set(
                    155:                        vm_offset_t     phys,
                    156:                        int             bits);
                    157: 
                    158: 
                    159: #ifndef        set_dirbase
                    160: void   set_dirbase(vm_offset_t dirbase);
                    161: #endif /* set_dirbase */
                    162: 
                    163: #define        PA_TO_PTE(pa)   (pa_to_pte((pa) - VM_MIN_KERNEL_ADDRESS))
                    164: #define        iswired(pte)    ((pte) & INTEL_PTE_WIRED)
                    165: 
                    166: pmap_t real_pmap[NCPUS];
                    167: 
                    168: #define        WRITE_PTE(pte_p, pte_entry)             *(pte_p) = (pte_entry);
                    169: #define        WRITE_PTE_FAST(pte_p, pte_entry)        *(pte_p) = (pte_entry);
                    170: 
                    171: /*
                    172:  *     Private data structures.
                    173:  */
                    174: 
                    175: /*
                    176:  *     For each vm_page_t, there is a list of all currently
                    177:  *     valid virtual mappings of that page.  An entry is
                    178:  *     a pv_entry_t; the list is the pv_table.
                    179:  */
                    180: 
                    181: typedef struct pv_entry {
                    182:        struct pv_entry *next;          /* next pv_entry */
                    183:        pmap_t          pmap;           /* pmap where mapping lies */
                    184:        vm_offset_t     va;             /* virtual address for mapping */
                    185: } *pv_entry_t;
                    186: 
                    187: #define PV_ENTRY_NULL  ((pv_entry_t) 0)
                    188: 
                    189: pv_entry_t     pv_head_table;          /* array of entries, one per page */
                    190: 
                    191: /*
                    192:  *     pv_list entries are kept on a list that can only be accessed
                    193:  *     with the pmap system locked (at SPLVM, not in the cpus_active set).
                    194:  *     The list is refilled from the pv_list_zone if it becomes empty.
                    195:  */
                    196: pv_entry_t     pv_free_list;           /* free list at SPLVM */
                    197: decl_simple_lock_data(,pv_free_list_lock)
                    198: 
                    199: #define        PV_ALLOC(pv_e) { \
                    200:        simple_lock(&pv_free_list_lock); \
                    201:        if ((pv_e = pv_free_list) != 0) { \
                    202:            pv_free_list = pv_e->next; \
                    203:        } \
                    204:        simple_unlock(&pv_free_list_lock); \
                    205: }
                    206: 
                    207: #define        PV_FREE(pv_e) { \
                    208:        simple_lock(&pv_free_list_lock); \
                    209:        pv_e->next = pv_free_list; \
                    210:        pv_free_list = pv_e; \
                    211:        simple_unlock(&pv_free_list_lock); \
                    212: }
                    213: 
                    214: zone_t         pv_list_zone;           /* zone of pv_entry structures */
                    215: 
                    216: /*
                    217:  *     Each entry in the pv_head_table is locked by a bit in the
                    218:  *     pv_lock_table.  The lock bits are accessed by the physical
                    219:  *     address of the page they lock.
                    220:  */
                    221: 
                    222: char   *pv_lock_table;         /* pointer to array of bits */
                    223: #define pv_lock_table_size(n)  (((n)+BYTE_SIZE-1)/BYTE_SIZE)
                    224: 
                    225: /*
                    226:  *     First and last physical addresses that we maintain any information
                    227:  *     for.  Initialized to zero so that pmap operations done before
                    228:  *     pmap_init won't touch any non-existent structures.
                    229:  */
                    230: vm_offset_t    vm_first_phys = (vm_offset_t) 0;
                    231: vm_offset_t    vm_last_phys  = (vm_offset_t) 0;
                    232: boolean_t      pmap_initialized = FALSE;/* Has pmap_init completed? */
                    233: 
                    234: /*
                    235:  *     Index into pv_head table, its lock bits, and the modify/reference
                    236:  *     bits starting at vm_first_phys.
                    237:  */
                    238: 
                    239: #define pa_index(pa)   (atop(pa - vm_first_phys))
                    240: 
                    241: #define pai_to_pvh(pai)                (&pv_head_table[pai])
                    242: #define lock_pvh_pai(pai)      bit_lock(pai, (void *)pv_lock_table)
                    243: #define unlock_pvh_pai(pai)    bit_unlock(pai, (void *)pv_lock_table)
                    244: 
                    245: /*
                    246:  *     Array of physical page attribites for managed pages.
                    247:  *     One byte per physical page.
                    248:  */
                    249: char   *pmap_phys_attributes;
                    250: 
                    251: /*
                    252:  *     Physical page attributes.  Copy bits from PTE definition.
                    253:  */
                    254: #define        PHYS_MODIFIED   INTEL_PTE_MOD   /* page modified */
                    255: #define        PHYS_REFERENCED INTEL_PTE_REF   /* page referenced */
                    256: 
                    257: /*
                    258:  *     Amount of virtual memory mapped by one
                    259:  *     page-directory entry.
                    260:  */
                    261: #define        PDE_MAPPED_SIZE         (pdetova(1))
                    262: 
                    263: /*
                    264:  *     We allocate page table pages directly from the VM system
                    265:  *     through this object.  It maps physical memory.
                    266:  */
                    267: vm_object_t    pmap_object = VM_OBJECT_NULL;
                    268: 
                    269: /*
                    270:  *     Locking and TLB invalidation
                    271:  */
                    272: 
                    273: /*
                    274:  *     Locking Protocols:
                    275:  *
                    276:  *     There are two structures in the pmap module that need locking:
                    277:  *     the pmaps themselves, and the per-page pv_lists (which are locked
                    278:  *     by locking the pv_lock_table entry that corresponds to the pv_head
                    279:  *     for the list in question.)  Most routines want to lock a pmap and
                    280:  *     then do operations in it that require pv_list locking -- however
                    281:  *     pmap_remove_all and pmap_copy_on_write operate on a physical page
                    282:  *     basis and want to do the locking in the reverse order, i.e. lock
                    283:  *     a pv_list and then go through all the pmaps referenced by that list.
                    284:  *     To protect against deadlock between these two cases, the pmap_lock
                    285:  *     is used.  There are three different locking protocols as a result:
                    286:  *
                    287:  *  1.  pmap operations only (pmap_extract, pmap_access, ...)  Lock only
                    288:  *             the pmap.
                    289:  *
                    290:  *  2.  pmap-based operations (pmap_enter, pmap_remove, ...)  Get a read
                    291:  *             lock on the pmap_lock (shared read), then lock the pmap
                    292:  *             and finally the pv_lists as needed [i.e. pmap lock before
                    293:  *             pv_list lock.]
                    294:  *
                    295:  *  3.  pv_list-based operations (pmap_remove_all, pmap_copy_on_write, ...)
                    296:  *             Get a write lock on the pmap_lock (exclusive write); this
                    297:  *             also guaranteees exclusive access to the pv_lists.  Lock the
                    298:  *             pmaps as needed.
                    299:  *
                    300:  *     At no time may any routine hold more than one pmap lock or more than
                    301:  *     one pv_list lock.  Because interrupt level routines can allocate
                    302:  *     mbufs and cause pmap_enter's, the pmap_lock and the lock on the
                    303:  *     kernel_pmap can only be held at splhigh.
                    304:  */
                    305: 
                    306: #if    NCPUS > 1
                    307: /*
                    308:  *     We raise the interrupt level to splhigh, to block interprocessor
                    309:  *     interrupts during pmap operations.  We must take the CPU out of
                    310:  *     the cpus_active set while interrupts are blocked.
                    311:  */
                    312: #define SPLVM(spl)     { \
                    313:        spl = splhigh(); \
                    314:        mp_disable_preemption(); \
                    315:        i_bit_clear(cpu_number(), &cpus_active); \
                    316:        mp_enable_preemption(); \
                    317: }
                    318: 
                    319: #define SPLX(spl)      { \
                    320:        mp_disable_preemption(); \
                    321:        i_bit_set(cpu_number(), &cpus_active); \
                    322:        mp_enable_preemption(); \
                    323:        splx(spl); \
                    324: }
                    325: 
                    326: /*
                    327:  *     Lock on pmap system
                    328:  */
                    329: lock_t pmap_system_lock;
                    330: 
                    331: #define PMAP_READ_LOCK(pmap, spl) {    \
                    332:        SPLVM(spl);                     \
                    333:        lock_read(&pmap_system_lock);   \
                    334:        simple_lock(&(pmap)->lock);     \
                    335: }
                    336: 
                    337: #define PMAP_WRITE_LOCK(spl) {         \
                    338:        SPLVM(spl);                     \
                    339:        lock_write(&pmap_system_lock);  \
                    340: }
                    341: 
                    342: #define PMAP_READ_UNLOCK(pmap, spl) {          \
                    343:        simple_unlock(&(pmap)->lock);           \
                    344:        lock_read_done(&pmap_system_lock);      \
                    345:        SPLX(spl);                              \
                    346: }
                    347: 
                    348: #define PMAP_WRITE_UNLOCK(spl) {               \
                    349:        lock_write_done(&pmap_system_lock);     \
                    350:        SPLX(spl);                              \
                    351: }
                    352: 
                    353: #define PMAP_WRITE_TO_READ_LOCK(pmap) {                \
                    354:        simple_lock(&(pmap)->lock);             \
                    355:        lock_write_to_read(&pmap_system_lock);  \
                    356: }
                    357: 
                    358: #define LOCK_PVH(index)                lock_pvh_pai(index)
                    359: 
                    360: #define UNLOCK_PVH(index)      unlock_pvh_pai(index)
                    361: 
                    362: #define PMAP_FLUSH_TLBS()                                              \
                    363: {                                                                      \
                    364:        flush_tlb();                                                    \
                    365:        i386_signal_cpus(MP_TLB_FLUSH);                                 \
                    366: }
                    367: 
                    368: #define        PMAP_RELOAD_TLBS()      {               \
                    369:        i386_signal_cpus(MP_TLB_RELOAD);        \
                    370:        set_cr3(kernel_pmap->pdirbase);         \
                    371: }
                    372: 
                    373: #define PMAP_INVALIDATE_PAGE(map, addr) {      \
                    374:        if (map == kernel_pmap)                 \
                    375:                invlpg((vm_offset_t) addr);     \
                    376:        else                                    \
                    377:                flush_tlb();                    \
                    378:        i386_signal_cpus(MP_TLB_FLUSH);         \
                    379: }
                    380: 
                    381: #else  /* NCPUS > 1 */
                    382: 
                    383: #if    MACH_RT
                    384: #define SPLVM(spl)                     { (spl) = splhigh(); }
                    385: #define SPLX(spl)                      splx (spl)
                    386: #else  /* MACH_RT */
                    387: #define SPLVM(spl)
                    388: #define SPLX(spl)
                    389: #endif /* MACH_RT */
                    390: 
                    391: #define PMAP_READ_LOCK(pmap, spl)      SPLVM(spl)
                    392: #define PMAP_WRITE_LOCK(spl)           SPLVM(spl)
                    393: #define PMAP_READ_UNLOCK(pmap, spl)    SPLX(spl)
                    394: #define PMAP_WRITE_UNLOCK(spl)         SPLX(spl)
                    395: #define PMAP_WRITE_TO_READ_LOCK(pmap)
                    396: 
                    397: #if    MACH_RT
                    398: #define LOCK_PVH(index)                        disable_preemption()
                    399: #define UNLOCK_PVH(index)              enable_preemption()
                    400: #else  /* MACH_RT */
                    401: #define LOCK_PVH(index)
                    402: #define UNLOCK_PVH(index)
                    403: #endif /* MACH_RT */
                    404: 
                    405: #define        PMAP_FLUSH_TLBS()       flush_tlb()
                    406: #define        PMAP_RELOAD_TLBS()      set_cr3(kernel_pmap->pdirbase)
                    407: #define        PMAP_INVALIDATE_PAGE(map, addr) {       \
                    408:                if (map == kernel_pmap)         \
                    409:                        invlpg((vm_offset_t) addr);     \
                    410:                else                            \
                    411:                        flush_tlb();            \
                    412: }
                    413: 
                    414: #endif /* NCPUS > 1 */
                    415: 
                    416: #define MAX_TBIS_SIZE  32              /* > this -> TBIA */ /* XXX */
                    417: 
                    418: #if    NCPUS > 1
                    419: /*
                    420:  *     Structures to keep track of pending TLB invalidations
                    421:  */
                    422: cpu_set                        cpus_active;
                    423: cpu_set                        cpus_idle;
                    424: volatile boolean_t     cpu_update_needed[NCPUS];
                    425: 
                    426: 
                    427: #endif /* NCPUS > 1 */
                    428: 
                    429: /*
                    430:  *     Other useful macros.
                    431:  */
                    432: #define current_pmap()         (vm_map_pmap(current_act()->map))
                    433: #define pmap_in_use(pmap, cpu) (((pmap)->cpus_using & (1 << (cpu))) != 0)
                    434: 
                    435: struct pmap    kernel_pmap_store;
                    436: pmap_t         kernel_pmap;
                    437: 
                    438: struct zone    *pmap_zone;             /* zone of pmap structures */
                    439: 
                    440: int            pmap_debug = 0;         /* flag for debugging prints */
                    441: int            ptes_per_vm_page;       /* number of hardware ptes needed
                    442:                                           to map one VM page. */
                    443: unsigned int   inuse_ptepages_count = 0;       /* debugging */
                    444: 
                    445: /*
                    446:  *     Pmap cache.  Cache is threaded through ref_count field of pmap.
                    447:  *     Max will eventually be constant -- variable for experimentation.
                    448:  */
                    449: int            pmap_cache_max = 32;
                    450: int            pmap_alloc_chunk = 8;
                    451: pmap_t         pmap_cache_list;
                    452: int            pmap_cache_count;
                    453: decl_simple_lock_data(,pmap_cache_lock)
                    454: 
                    455: extern vm_offset_t     hole_start, hole_end;
                    456: 
                    457: extern char end;
                    458: 
                    459: /*
                    460:  * Page directory for kernel.
                    461:  */
                    462: pt_entry_t     *kpde = 0;      /* set by start.s - keep out of bss */
                    463: 
                    464: #if  DEBUG_ALIAS
                    465: #define PMAP_ALIAS_MAX 32
                    466: struct pmap_alias {
                    467:         vm_offset_t rpc;
                    468:         pmap_t pmap;
                    469:         vm_offset_t va;
                    470:         int cookie;
                    471: #define PMAP_ALIAS_COOKIE 0xdeadbeef
                    472: } pmap_aliasbuf[PMAP_ALIAS_MAX];
                    473: int pmap_alias_index = 0;
                    474: extern vm_offset_t get_rpc();
                    475: 
                    476: #endif  /* DEBUG_ALIAS */
                    477: 
                    478: /*
                    479:  *     Given an offset and a map, compute the address of the
                    480:  *     pte.  If the address is invalid with respect to the map
                    481:  *     then PT_ENTRY_NULL is returned (and the map may need to grow).
                    482:  *
                    483:  *     This is only used in machine-dependent code.
                    484:  */
                    485: 
                    486: pt_entry_t *
                    487: pmap_pte(
                    488:        register pmap_t         pmap,
                    489:        register vm_offset_t    addr)
                    490: {
                    491:        register pt_entry_t     *ptp;
                    492:        register pt_entry_t     pte;
                    493: 
                    494:        pte = pmap->dirbase[pdenum(pmap, addr)];
                    495:        if ((pte & INTEL_PTE_VALID) == 0)
                    496:                return(PT_ENTRY_NULL);
                    497:        ptp = (pt_entry_t *)ptetokv(pte);
                    498:        return(&ptp[ptenum(addr)]);
                    499: 
                    500: }
                    501: 
                    502: #define        pmap_pde(pmap, addr) (&(pmap)->dirbase[pdenum(pmap, addr)])
                    503: 
                    504: #define DEBUG_PTE_PAGE 0
                    505: 
                    506: #if    DEBUG_PTE_PAGE
                    507: void
                    508: ptep_check(
                    509:        ptep_t  ptep)
                    510: {
                    511:        register pt_entry_t     *pte, *epte;
                    512:        int                     ctu, ctw;
                    513: 
                    514:        /* check the use and wired counts */
                    515:        if (ptep == PTE_PAGE_NULL)
                    516:                return;
                    517:        pte = pmap_pte(ptep->pmap, ptep->va);
                    518:        epte = pte + INTEL_PGBYTES/sizeof(pt_entry_t);
                    519:        ctu = 0;
                    520:        ctw = 0;
                    521:        while (pte < epte) {
                    522:                if (pte->pfn != 0) {
                    523:                        ctu++;
                    524:                        if (pte->wired)
                    525:                                ctw++;
                    526:                }
                    527:                pte += ptes_per_vm_page;
                    528:        }
                    529: 
                    530:        if (ctu != ptep->use_count || ctw != ptep->wired_count) {
                    531:                printf("use %d wired %d - actual use %d wired %d\n",
                    532:                        ptep->use_count, ptep->wired_count, ctu, ctw);
                    533:                panic("pte count");
                    534:        }
                    535: }
                    536: #endif /* DEBUG_PTE_PAGE */
                    537: 
                    538: /*
                    539:  *     Map memory at initialization.  The physical addresses being
                    540:  *     mapped are not managed and are never unmapped.
                    541:  *
                    542:  *     For now, VM is already on, we only need to map the
                    543:  *     specified memory.
                    544:  */
                    545: vm_offset_t
                    546: pmap_map(
                    547:        register vm_offset_t    virt,
                    548:        register vm_offset_t    start,
                    549:        register vm_offset_t    end,
                    550:        register vm_prot_t      prot)
                    551: {
                    552:        register int            ps;
                    553: 
                    554:        ps = PAGE_SIZE;
                    555:        while (start < end) {
                    556:                pmap_enter(kernel_pmap, virt, start, prot, FALSE);
                    557:                virt += ps;
                    558:                start += ps;
                    559:        }
                    560:        return(virt);
                    561: }
                    562: 
                    563: /*
                    564:  *     Back-door routine for mapping kernel VM at initialization.  
                    565:  *     Useful for mapping memory outside the range
                    566:  *      Sets no-cache, A, D.
                    567:  *     [vm_first_phys, vm_last_phys) (i.e., devices).
                    568:  *     Otherwise like pmap_map.
                    569:  */
                    570: vm_offset_t
                    571: pmap_map_bd(
                    572:        register vm_offset_t    virt,
                    573:        register vm_offset_t    start,
                    574:        register vm_offset_t    end,
                    575:        vm_prot_t               prot)
                    576: {
                    577:        register pt_entry_t     template;
                    578:        register pt_entry_t     *pte;
                    579: 
                    580:        template = pa_to_pte(start)
                    581:                | INTEL_PTE_NCACHE
                    582:                | INTEL_PTE_REF
                    583:                | INTEL_PTE_MOD
                    584:                | INTEL_PTE_WIRED
                    585:                | INTEL_PTE_VALID;
                    586:        if (prot & VM_PROT_WRITE)
                    587:            template |= INTEL_PTE_WRITE;
                    588: 
                    589:        while (start < end) {
                    590:                pte = pmap_pte(kernel_pmap, virt);
                    591:                if (pte == PT_ENTRY_NULL)
                    592:                        panic("pmap_map_bd: Invalid kernel address\n");
                    593:                WRITE_PTE_FAST(pte, template)
                    594:                pte_increment_pa(template);
                    595:                virt += PAGE_SIZE;
                    596:                start += PAGE_SIZE;
                    597:        }
                    598: 
                    599:        PMAP_FLUSH_TLBS();
                    600: 
                    601:        return(virt);
                    602: }
                    603: 
                    604: extern int             cnvmem;
                    605: extern char            *first_avail;
                    606: extern vm_offset_t     virtual_avail, virtual_end;
                    607: extern vm_offset_t     avail_start, avail_end, avail_next;
                    608: 
                    609: /*
                    610:  *     Bootstrap the system enough to run with virtual memory.
                    611:  *     Map the kernel's code and data, and allocate the system page table.
                    612:  *     Called with mapping OFF.  Page_size must already be set.
                    613:  *
                    614:  *     Parameters:
                    615:  *     load_start:     PA where kernel was loaded
                    616:  *     avail_start     PA of first available physical page -
                    617:  *                        after kernel page tables
                    618:  *     avail_end       PA of last available physical page
                    619:  *     virtual_avail   VA of first available page -
                    620:  *                        after kernel page tables
                    621:  *     virtual_end     VA of last available page -
                    622:  *                        end of kernel address space
                    623:  *
                    624:  *     &start_text     start of kernel text
                    625:  *     &etext          end of kernel text
                    626:  */
                    627: 
                    628: void
                    629: pmap_bootstrap(
                    630:        vm_offset_t     load_start)
                    631: {
                    632:        vm_offset_t     va, tva, paddr;
                    633:        pt_entry_t      template;
                    634:        pt_entry_t      *pde, *pte, *ptend;
                    635:        vm_size_t       morevm;         /* VM space for kernel map */
                    636: 
                    637:        /*
                    638:         *      Set ptes_per_vm_page for general use.
                    639:         */
                    640:        ptes_per_vm_page = PAGE_SIZE / INTEL_PGBYTES;
                    641: 
                    642:        /*
                    643:         *      The kernel's pmap is statically allocated so we don't
                    644:         *      have to use pmap_create, which is unlikely to work
                    645:         *      correctly at this part of the boot sequence.
                    646:         */
                    647: 
                    648:        kernel_pmap = &kernel_pmap_store;
                    649: 
                    650: #if    NCPUS > 1
                    651:        lock_init(&pmap_system_lock,
                    652:                  FALSE,                /* NOT a sleep lock */
                    653:                  ETAP_VM_PMAP_SYS,
                    654:                  ETAP_VM_PMAP_SYS_I);
                    655: #endif /* NCPUS > 1 */
                    656: 
                    657:        simple_lock_init(&kernel_pmap->lock, ETAP_VM_PMAP_KERNEL);
                    658:        simple_lock_init(&pv_free_list_lock, ETAP_VM_PMAP_FREE);
                    659: 
                    660:        kernel_pmap->ref_count = 1;
                    661: 
                    662:        /*
                    663:         *      The kernel page directory has been allocated;
                    664:         *      its virtual address is in kpde.
                    665:         *
                    666:         *      Enough kernel page table pages have been allocated
                    667:         *      to map low system memory, kernel text, kernel data/bss,
                    668:         *      kdb's symbols, and the page directory and page tables.
                    669:         *
                    670:         *      No other physical memory has been allocated.
                    671:         */
                    672: 
                    673:        /*
                    674:         * Start mapping virtual memory to physical memory, 1-1,
                    675:         * at end of mapped memory.
                    676:         */
                    677: 
                    678:        virtual_avail = phystokv(avail_start);
                    679:        virtual_end = phystokv(avail_end);
                    680: 
                    681:        pde = kpde;
                    682:        pde += pdenum(kernel_pmap, virtual_avail);
                    683: 
                    684:        if (pte_to_pa(*pde) == 0) {
                    685:            /* This pte has not been allocated */
                    686:            pte = 0; ptend = 0;
                    687:        }
                    688:        else {
                    689:            pte = (pt_entry_t *)ptetokv(*pde);
                    690:                                                /* first pte of page */
                    691:            ptend = pte+NPTES;                  /* last pte of page */
                    692:            pte += ptenum(virtual_avail);       /* point to pte that
                    693:                                                   maps first avail VA */
                    694:            pde++;      /* point pde to first empty slot */
                    695:        }
                    696: 
                    697:        template = pa_to_pte(avail_start)
                    698:                | INTEL_PTE_VALID
                    699:                | INTEL_PTE_WRITE;
                    700: 
                    701:        for (va = virtual_avail; va < virtual_end; va += INTEL_PGBYTES) {
                    702:            if (pte >= ptend) {
                    703:                pte = (pt_entry_t *)phystokv(virtual_avail);
                    704:                ptend = pte + NPTES;
                    705:                virtual_avail = (vm_offset_t)ptend;
                    706:                *pde = PA_TO_PTE((vm_offset_t) pte)
                    707:                        | INTEL_PTE_VALID
                    708:                        | INTEL_PTE_WRITE;
                    709:                pde++;
                    710:            }
                    711:            WRITE_PTE_FAST(pte, template)
                    712:            pte++;
                    713:            pte_increment_pa(template);
                    714:        }
                    715: 
                    716:        avail_start = virtual_avail - VM_MIN_KERNEL_ADDRESS;
                    717:        avail_next = avail_start;
                    718: 
                    719:        /*
                    720:         *      Figure out maximum kernel address.
                    721:         *      Kernel virtual space is:
                    722:         *              - at least three times physical memory
                    723:         *              - at least VM_MIN_KERNEL_ADDRESS
                    724:         *              - limited by VM_MAX_KERNEL_ADDRESS
                    725:         */
                    726: 
                    727:        morevm = 3*avail_end;
                    728:        if (virtual_end + morevm > VM_MAX_KERNEL_ADDRESS)
                    729:                morevm = virtual_end - VM_MAX_KERNEL_ADDRESS;
                    730: 
                    731: /*
                    732:  *     startup requires additional virtual memory (for tables, buffers, 
                    733:  *     etc.).  The kd driver may also require some of that memory to
                    734:  *     access the graphics board.
                    735:  *
                    736:  */
                    737:        *(int *)&template = 0;
                    738: 
                    739:        /*
                    740:         * Leave room for kernel-loaded servers, which have been linked at
                    741:         * addresses from VM_MIN_KERNEL_LOADED_ADDRESS to
                    742:         * VM_MAX_KERNEL_LOADED_ADDRESS.
                    743:         */
                    744:        if (virtual_end + morevm < VM_MAX_KERNEL_LOADED_ADDRESS + 1)
                    745:                morevm = VM_MAX_KERNEL_LOADED_ADDRESS + 1 - virtual_end;
                    746: 
                    747: 
                    748:        virtual_end += morevm;
                    749:        for (tva = va; tva < virtual_end; tva += INTEL_PGBYTES) {
                    750:            if (pte >= ptend) {
                    751:                pmap_next_page(&paddr);
                    752:                pte = (pt_entry_t *)phystokv(paddr);
                    753:                ptend = pte + NPTES;
                    754:                *pde = PA_TO_PTE((vm_offset_t) pte)
                    755:                        | INTEL_PTE_VALID
                    756:                        | INTEL_PTE_WRITE;
                    757:                pde++;
                    758:            }
                    759:            WRITE_PTE_FAST(pte, template)
                    760:            pte++;
                    761:        }
                    762: 
                    763:        virtual_avail = va;
                    764: 
                    765:        /* Push the virtual avail address above hole_end */
                    766:        if (virtual_avail < hole_end)
                    767:                virtual_avail = hole_end;
                    768: 
                    769:        /*
                    770:         *      c.f. comment above
                    771:         *
                    772:         */
                    773:        virtual_end = va + morevm;
                    774:        while (pte < ptend)
                    775:            *pte++ = 0;
                    776: 
                    777:        /*
                    778:         *      invalidate user virtual addresses 
                    779:         */
                    780:        memset((char *)kpde,
                    781:               0,
                    782:               pdenum(kernel_pmap,VM_MIN_KERNEL_ADDRESS)*sizeof(pt_entry_t));
                    783:        kernel_pmap->dirbase = kpde;
                    784:        printf("Kernel virtual space from 0x%x to 0x%x.\n",
                    785:                        VM_MIN_KERNEL_ADDRESS, virtual_end);
                    786: 
                    787:        avail_start = avail_next;
                    788:        printf("Available physical space from 0x%x to 0x%x\n",
                    789:                        avail_start, avail_end);
                    790: 
                    791:        kernel_pmap->pdirbase = kvtophys((vm_offset_t)kernel_pmap->dirbase);
                    792: 
                    793: }
                    794: 
                    795: void
                    796: pmap_virtual_space(
                    797:        vm_offset_t *startp,
                    798:        vm_offset_t *endp)
                    799: {
                    800:        *startp = virtual_avail;
                    801:        *endp = virtual_end;
                    802: }
                    803: 
                    804: /*
                    805:  *     Initialize the pmap module.
                    806:  *     Called by vm_init, to initialize any structures that the pmap
                    807:  *     system needs to map virtual memory.
                    808:  */
                    809: void
                    810: pmap_init(void)
                    811: {
                    812:        register long           npages;
                    813:        vm_offset_t             addr;
                    814:        register vm_size_t      s;
                    815:        int                     i;
                    816: 
                    817:        /*
                    818:         *      Allocate memory for the pv_head_table and its lock bits,
                    819:         *      the modify bit array, and the pte_page table.
                    820:         */
                    821: 
                    822:        npages = atop(avail_end - avail_start);
                    823:        s = (vm_size_t) (sizeof(struct pv_entry) * npages
                    824:                                + pv_lock_table_size(npages)
                    825:                                + npages);
                    826: 
                    827:        s = round_page(s);
                    828:        if (kmem_alloc_wired(kernel_map, &addr, s) != KERN_SUCCESS)
                    829:                panic("pmap_init");
                    830: 
                    831:        memset((char *)addr, 0, s);
                    832: 
                    833:        /*
                    834:         *      Allocate the structures first to preserve word-alignment.
                    835:         */
                    836:        pv_head_table = (pv_entry_t) addr;
                    837:        addr = (vm_offset_t) (pv_head_table + npages);
                    838: 
                    839:        pv_lock_table = (char *) addr;
                    840:        addr = (vm_offset_t) (pv_lock_table + pv_lock_table_size(npages));
                    841: 
                    842:        pmap_phys_attributes = (char *) addr;
                    843: 
                    844:        /*
                    845:         *      Create the zone of physical maps,
                    846:         *      and of the physical-to-virtual entries.
                    847:         */
                    848:        s = (vm_size_t) sizeof(struct pmap);
                    849:        pmap_zone = zinit(s, 400*s, 4096, "pmap"); /* XXX */
                    850:        s = (vm_size_t) sizeof(struct pv_entry);
                    851:        pv_list_zone = zinit(s, 10000*s, 4096, "pv_list"); /* XXX */
                    852: 
                    853:        /*
                    854:         *      Only now, when all of the data structures are allocated,
                    855:         *      can we set vm_first_phys and vm_last_phys.  If we set them
                    856:         *      too soon, the kmem_alloc_wired above will try to use these
                    857:         *      data structures and blow up.
                    858:         */
                    859: 
                    860:        vm_first_phys = avail_start;
                    861:        vm_last_phys = avail_end;
                    862:        pmap_initialized = TRUE;
                    863: 
                    864:        /*
                    865:         *      Initializie pmap cache.
                    866:         */
                    867:        pmap_cache_list = PMAP_NULL;
                    868:        pmap_cache_count = 0;
                    869:        simple_lock_init(&pmap_cache_lock, ETAP_VM_PMAP_CACHE);
                    870: }
                    871: 
                    872: 
                    873: #define        pmap_valid_page(x)      ((avail_start <= x) && (x < avail_end))
                    874: 
                    875: 
                    876: #define valid_page(x) (pmap_initialized && pmap_valid_page(x))
                    877: 
                    878: boolean_t
                    879: pmap_verify_free(
                    880:        vm_offset_t     phys)
                    881: {
                    882:        pv_entry_t      pv_h;
                    883:        int             pai;
                    884:        spl_t           spl;
                    885:        boolean_t       result;
                    886: 
                    887:        assert(phys != vm_page_fictitious_addr);
                    888:        if (!pmap_initialized)
                    889:                return(TRUE);
                    890: 
                    891:        if (!pmap_valid_page(phys))
                    892:                return(FALSE);
                    893: 
                    894:        PMAP_WRITE_LOCK(spl);
                    895: 
                    896:        pai = pa_index(phys);
                    897:        pv_h = pai_to_pvh(pai);
                    898: 
                    899:        result = (pv_h->pmap == PMAP_NULL);
                    900:        PMAP_WRITE_UNLOCK(spl);
                    901: 
                    902:        return(result);
                    903: }
                    904: 
                    905: /*
                    906:  *     Create and return a physical map.
                    907:  *
                    908:  *     If the size specified for the map
                    909:  *     is zero, the map is an actual physical
                    910:  *     map, and may be referenced by the
                    911:  *     hardware.
                    912:  *
                    913:  *     If the size specified is non-zero,
                    914:  *     the map will be used in software only, and
                    915:  *     is bounded by that size.
                    916:  */
                    917: pmap_t
                    918: pmap_create(
                    919:        vm_size_t       size)
                    920: {
                    921:        register pmap_t                 p;
                    922:        register pmap_statistics_t      stats;
                    923: 
                    924:        /*
                    925:         *      A software use-only map doesn't even need a map.
                    926:         */
                    927: 
                    928:        if (size != 0) {
                    929:                return(PMAP_NULL);
                    930:        }
                    931: 
                    932:        /*
                    933:         *      Try to get cached pmap, if this fails,
                    934:         *      allocate a pmap struct from the pmap_zone.  Then allocate
                    935:         *      the page descriptor table from the pd_zone.
                    936:         */
                    937: 
                    938:        simple_lock(&pmap_cache_lock);
                    939:        while ((p = pmap_cache_list) == PMAP_NULL) {
                    940: 
                    941:                vm_offset_t             dirbases;
                    942:                register int            i;
                    943: 
                    944:                simple_unlock(&pmap_cache_lock);
                    945: 
                    946: #if    NCPUS > 1
                    947:        /*
                    948:         * XXX  NEEDS MP DOING ALLOC logic so that if multiple processors
                    949:         * XXX  get here, only one allocates a chunk of pmaps.
                    950:         * (for now we'll just let it go - safe but wasteful)
                    951:         */
                    952: #endif
                    953: 
                    954:                /*
                    955:                 *      Allocate a chunck of pmaps.  Single kmem_alloc_wired
                    956:                 *      operation reduces kernel map fragmentation.
                    957:                 */
                    958: 
                    959:                if (kmem_alloc_wired(kernel_map, &dirbases,
                    960:                                     pmap_alloc_chunk * INTEL_PGBYTES)
                    961:                                                        != KERN_SUCCESS)
                    962:                        panic("pmap_create.1");
                    963: 
                    964:                for (i = pmap_alloc_chunk; i > 0 ; i--) {
                    965:                        p = (pmap_t) zalloc(pmap_zone);
                    966:                        if (p == PMAP_NULL)
                    967:                                panic("pmap_create.2");
                    968: 
                    969:                        /*
                    970:                         *      Initialize pmap.  Don't bother with
                    971:                         *      ref count as cache list is threaded
                    972:                         *      through it.  It'll be set on cache removal.
                    973:                         */
                    974:                        p->dirbase = (pt_entry_t *) dirbases;
                    975:                        dirbases += INTEL_PGBYTES;
                    976:                        memcpy(p->dirbase, kpde, INTEL_PGBYTES);
                    977:                        p->pdirbase = kvtophys((vm_offset_t)p->dirbase);
                    978: 
                    979:                        simple_lock_init(&p->lock, ETAP_VM_PMAP);
                    980:                        p->cpus_using = 0;
                    981: 
                    982:                        /*
                    983:                         *      Initialize statistics.
                    984:                         */
                    985:                        stats = &p->stats;
                    986:                        stats->resident_count = 0;
                    987:                        stats->wired_count = 0;
                    988:                        
                    989:                        /*
                    990:                         *      Insert into cache
                    991:                         */
                    992:                        simple_lock(&pmap_cache_lock);
                    993:                        p->ref_count = (int) pmap_cache_list;
                    994:                        pmap_cache_list = p;
                    995:                        pmap_cache_count++;
                    996:                        simple_unlock(&pmap_cache_lock);
                    997:                }
                    998:                simple_lock(&pmap_cache_lock);
                    999:        }
                   1000: 
                   1001:        assert(p->stats.resident_count == 0);
                   1002:        assert(p->stats.wired_count == 0);
                   1003:        p->stats.resident_count = 0;
                   1004:        p->stats.wired_count = 0;
                   1005: 
                   1006:        pmap_cache_list = (pmap_t) p->ref_count;
                   1007:        p->ref_count = 1;
                   1008:        pmap_cache_count--;
                   1009:        simple_unlock(&pmap_cache_lock);
                   1010: 
                   1011:        return(p);
                   1012: }
                   1013: 
                   1014: /*
                   1015:  *     Retire the given physical map from service.
                   1016:  *     Should only be called if the map contains
                   1017:  *     no valid mappings.
                   1018:  */
                   1019: 
                   1020: void
                   1021: pmap_destroy(
                   1022:        register pmap_t p)
                   1023: {
                   1024:        register pt_entry_t     *pdep;
                   1025:        register vm_offset_t    pa;
                   1026:        register int            c;
                   1027:        spl_t                   s;
                   1028:        register vm_page_t      m;
                   1029: 
                   1030:        if (p == PMAP_NULL)
                   1031:                return;
                   1032: 
                   1033:        SPLVM(s);
                   1034:        simple_lock(&p->lock);
                   1035:        c = --p->ref_count;
                   1036:        if (c == 0) {
                   1037:                register int    my_cpu;
                   1038: 
                   1039:                mp_disable_preemption();
                   1040:                my_cpu = cpu_number();
                   1041: 
                   1042:                /* 
                   1043:                 * If some cpu is not using the physical pmap pointer that it
                   1044:                 * is supposed to be (see set_dirbase), we might be using the
                   1045:                 * pmap that is being destroyed! Make sure we are
                   1046:                 * physically on the right pmap:
                   1047:                 */
                   1048: 
                   1049: 
                   1050:                if (real_pmap[my_cpu] == p) {
                   1051:                        PMAP_CPU_CLR(p, my_cpu);
                   1052:                        real_pmap[my_cpu] = kernel_pmap;
                   1053:                        PMAP_RELOAD_TLBS();
                   1054:                }
                   1055:                mp_enable_preemption();
                   1056:        }
                   1057:        simple_unlock(&p->lock);
                   1058:        SPLX(s);
                   1059: 
                   1060:        if (c != 0) {
                   1061:            return;     /* still in use */
                   1062:        }
                   1063: 
                   1064:        /*
                   1065:         *      Free the memory maps, then the
                   1066:         *      pmap structure.
                   1067:         */
                   1068:        pdep = p->dirbase;
                   1069:        while (pdep < &p->dirbase[pdenum(p, LINEAR_KERNEL_ADDRESS)]) {
                   1070:            if (*pdep & INTEL_PTE_VALID) {
                   1071:                pa = pte_to_pa(*pdep);
                   1072:                vm_object_lock(pmap_object);
                   1073:                m = vm_page_lookup(pmap_object, pa);
                   1074:                if (m == VM_PAGE_NULL)
                   1075:                    panic("pmap_destroy: pte page not in object");
                   1076:                vm_page_lock_queues();
                   1077:                vm_page_free(m);
                   1078:                inuse_ptepages_count--;
                   1079:                vm_object_unlock(pmap_object);
                   1080:                vm_page_unlock_queues();
                   1081: 
                   1082:                /*
                   1083:                 *      Clear pdes, this might be headed for the cache.
                   1084:                 */
                   1085:                c = ptes_per_vm_page;
                   1086:                do {
                   1087:                    *pdep = 0;
                   1088:                    pdep++;
                   1089:                } while (--c > 0);
                   1090:            }
                   1091:            else {
                   1092:                pdep += ptes_per_vm_page;
                   1093:            }
                   1094:        
                   1095:        }
                   1096:        assert(p->stats.resident_count == 0);
                   1097:        assert(p->stats.wired_count == 0);
                   1098: 
                   1099:        /*
                   1100:         *      Add to cache if not already full
                   1101:         */
                   1102:        simple_lock(&pmap_cache_lock);
                   1103:        if (pmap_cache_count <= pmap_cache_max) {
                   1104:                p->ref_count = (int) pmap_cache_list;
                   1105:                pmap_cache_list = p;
                   1106:                pmap_cache_count++;
                   1107:                simple_unlock(&pmap_cache_lock);
                   1108:        }
                   1109:        else {
                   1110:                simple_unlock(&pmap_cache_lock);
                   1111:                kmem_free(kernel_map, (vm_offset_t)p->dirbase, INTEL_PGBYTES);
                   1112:                zfree(pmap_zone, (vm_offset_t) p);
                   1113:        }
                   1114: }
                   1115: 
                   1116: /*
                   1117:  *     Add a reference to the specified pmap.
                   1118:  */
                   1119: 
                   1120: void
                   1121: pmap_reference(
                   1122:        register pmap_t p)
                   1123: {
                   1124:        spl_t   s;
                   1125: 
                   1126:        if (p != PMAP_NULL) {
                   1127:                SPLVM(s);
                   1128:                simple_lock(&p->lock);
                   1129:                p->ref_count++;
                   1130:                simple_unlock(&p->lock);
                   1131:                SPLX(s);
                   1132:        }
                   1133: }
                   1134: 
                   1135: /*
                   1136:  *     Remove a range of hardware page-table entries.
                   1137:  *     The entries given are the first (inclusive)
                   1138:  *     and last (exclusive) entries for the VM pages.
                   1139:  *     The virtual address is the va for the first pte.
                   1140:  *
                   1141:  *     The pmap must be locked.
                   1142:  *     If the pmap is not the kernel pmap, the range must lie
                   1143:  *     entirely within one pte-page.  This is NOT checked.
                   1144:  *     Assumes that the pte-page exists.
                   1145:  */
                   1146: 
                   1147: /* static */
                   1148: void
                   1149: pmap_remove_range(
                   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:            pa = pte_to_pa(*cpte);
                   1171:            if (pa == 0)
                   1172:                continue;
                   1173: 
                   1174:            num_removed++;
                   1175:            if (iswired(*cpte))
                   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:        assert(pmap->stats.resident_count >= num_removed);
                   1258:        pmap->stats.resident_count -= num_removed;
                   1259:        assert(pmap->stats.wired_count >= num_unwired);
                   1260:        pmap->stats.wired_count -= num_unwired;
                   1261: }
                   1262: 
                   1263: /*
                   1264:  *     Remove the given range of addresses
                   1265:  *     from the specified map.
                   1266:  *
                   1267:  *     It is assumed that the start and end are properly
                   1268:  *     rounded to the hardware page size.
                   1269:  */
                   1270: 
                   1271: void
                   1272: pmap_remove(
                   1273:        pmap_t          map,
                   1274:        vm_offset_t     s,
                   1275:        vm_offset_t     e)
                   1276: {
                   1277:        spl_t                   spl;
                   1278:        register pt_entry_t     *pde;
                   1279:        register pt_entry_t     *spte, *epte;
                   1280:        vm_offset_t             l;
                   1281: 
                   1282:        if (map == PMAP_NULL)
                   1283:                return;
                   1284: 
                   1285:        PMAP_READ_LOCK(map, spl);
                   1286: 
                   1287:        pde = pmap_pde(map, s);
                   1288: 
                   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_FLUSH_TLBS();
                   1304: 
                   1305:        PMAP_READ_UNLOCK(map, spl);
                   1306: }
                   1307: 
                   1308: /*
                   1309:  *     Routine:        pmap_page_protect
                   1310:  *
                   1311:  *     Function:
                   1312:  *             Lower the permission for all mappings to a given
                   1313:  *             page.
                   1314:  */
                   1315: void
                   1316: pmap_page_protect(
                   1317:        vm_offset_t     phys,
                   1318:        vm_prot_t       prot)
                   1319: {
                   1320:        pv_entry_t              pv_h, prev;
                   1321:        register pv_entry_t     pv_e;
                   1322:        register pt_entry_t     *pte;
                   1323:        int                     pai;
                   1324:        register pmap_t         pmap;
                   1325:        spl_t                   spl;
                   1326:        boolean_t               remove;
                   1327: 
                   1328:        assert(phys != vm_page_fictitious_addr);
                   1329:        if (!valid_page(phys)) {
                   1330:            /*
                   1331:             *  Not a managed page.
                   1332:             */
                   1333:            return;
                   1334:        }
                   1335: 
                   1336:        /*
                   1337:         * Determine the new protection.
                   1338:         */
                   1339:        switch (prot) {
                   1340:            case VM_PROT_READ:
                   1341:            case VM_PROT_READ|VM_PROT_EXECUTE:
                   1342:                remove = FALSE;
                   1343:                break;
                   1344:            case VM_PROT_ALL:
                   1345:                return; /* nothing to do */
                   1346:            default:
                   1347:                remove = TRUE;
                   1348:                break;
                   1349:        }
                   1350: 
                   1351:        /*
                   1352:         *      Lock the pmap system first, since we will be changing
                   1353:         *      several pmaps.
                   1354:         */
                   1355: 
                   1356:        PMAP_WRITE_LOCK(spl);
                   1357: 
                   1358:        pai = pa_index(phys);
                   1359:        pv_h = pai_to_pvh(pai);
                   1360: 
                   1361:        /*
                   1362:         * Walk down PV list, changing or removing all mappings.
                   1363:         * We do not have to lock the pv_list because we have
                   1364:         * the entire pmap system locked.
                   1365:         */
                   1366:        if (pv_h->pmap != PMAP_NULL) {
                   1367: 
                   1368:            prev = pv_e = pv_h;
                   1369:            do {
                   1370:                pmap = pv_e->pmap;
                   1371:                /*
                   1372:                 * Lock the pmap to block pmap_extract and similar routines.
                   1373:                 */
                   1374:                simple_lock(&pmap->lock);
                   1375: 
                   1376:                {
                   1377:                    register vm_offset_t va;
                   1378: 
                   1379:                    va = pv_e->va;
                   1380:                    pte = pmap_pte(pmap, va);
                   1381: 
                   1382:                    /*
                   1383:                     * Consistency checks.
                   1384:                     */
                   1385:                    /* assert(*pte & INTEL_PTE_VALID); XXX */
                   1386:                    /* assert(pte_to_phys(*pte) == phys); */
                   1387: 
                   1388:                    /*
                   1389:                     * Invalidate TLBs for all CPUs using this mapping.
                   1390:                     */
                   1391:                    PMAP_INVALIDATE_PAGE(pmap, va);
                   1392:                }
                   1393: 
                   1394:                /*
                   1395:                 * Remove the mapping if new protection is NONE
                   1396:                 * or if write-protecting a kernel mapping.
                   1397:                 */
                   1398:                if (remove || pmap == kernel_pmap) {
                   1399:                    /*
                   1400:                     * Remove the mapping, collecting any modify bits.
                   1401:                     */
                   1402:                    if (iswired(*pte))
                   1403:                        panic("pmap_remove_all removing a wired page");
                   1404: 
                   1405:                    {
                   1406:                        register int    i = ptes_per_vm_page;
                   1407: 
                   1408:                        do {
                   1409:                            pmap_phys_attributes[pai] |=
                   1410:                                *pte & (PHYS_MODIFIED|PHYS_REFERENCED);
                   1411:                            *pte++ = 0;
                   1412:                        } while (--i > 0);
                   1413:                    }
                   1414: 
                   1415:                    assert(pmap->stats.resident_count >= 1);
                   1416:                    pmap->stats.resident_count--;
                   1417: 
                   1418:                    /*
                   1419:                     * Remove the pv_entry.
                   1420:                     */
                   1421:                    if (pv_e == pv_h) {
                   1422:                        /*
                   1423:                         * Fix up head later.
                   1424:                         */
                   1425:                        pv_h->pmap = PMAP_NULL;
                   1426:                    }
                   1427:                    else {
                   1428:                        /*
                   1429:                         * Delete this entry.
                   1430:                         */
                   1431:                        prev->next = pv_e->next;
                   1432:                        PV_FREE(pv_e);
                   1433:                    }
                   1434:                }
                   1435:                else {
                   1436:                    /*
                   1437:                     * Write-protect.
                   1438:                     */
                   1439:                    register int i = ptes_per_vm_page;
                   1440: 
                   1441:                    do {
                   1442:                        *pte &= ~INTEL_PTE_WRITE;
                   1443:                        pte++;
                   1444:                    } while (--i > 0);
                   1445: 
                   1446:                    /*
                   1447:                     * Advance prev.
                   1448:                     */
                   1449:                    prev = pv_e;
                   1450:                }
                   1451: 
                   1452:                simple_unlock(&pmap->lock);
                   1453: 
                   1454:            } while ((pv_e = prev->next) != PV_ENTRY_NULL);
                   1455: 
                   1456:            /*
                   1457:             * If pv_head mapping was removed, fix it up.
                   1458:             */
                   1459:            if (pv_h->pmap == PMAP_NULL) {
                   1460:                pv_e = pv_h->next;
                   1461:                if (pv_e != PV_ENTRY_NULL) {
                   1462:                    *pv_h = *pv_e;
                   1463:                    PV_FREE(pv_e);
                   1464:                }
                   1465:            }
                   1466:        }
                   1467: 
                   1468:        PMAP_WRITE_UNLOCK(spl);
                   1469: }
                   1470: 
                   1471: /*
                   1472:  *     Set the physical protection on the
                   1473:  *     specified range of this map as requested.
                   1474:  *     Will not increase permissions.
                   1475:  */
                   1476: void
                   1477: pmap_protect(
                   1478:        pmap_t          map,
                   1479:        vm_offset_t     s,
                   1480:        vm_offset_t     e,
                   1481:        vm_prot_t       prot)
                   1482: {
                   1483:        register pt_entry_t     *pde;
                   1484:        register pt_entry_t     *spte, *epte;
                   1485:        vm_offset_t             l;
                   1486:        spl_t           spl;
                   1487: 
                   1488: 
                   1489:        if (map == PMAP_NULL)
                   1490:                return;
                   1491: 
                   1492:        /*
                   1493:         * Determine the new protection.
                   1494:         */
                   1495:        switch (prot) {
                   1496:            case VM_PROT_READ:
                   1497:            case VM_PROT_READ|VM_PROT_EXECUTE:
                   1498:                break;
                   1499:            case VM_PROT_READ|VM_PROT_WRITE:
                   1500:            case VM_PROT_ALL:
                   1501:                return; /* nothing to do */
                   1502:            default:
                   1503:                pmap_remove(map, s, e);
                   1504:                return;
                   1505:        }
                   1506: 
                   1507:        /*
                   1508:         * If write-protecting in the kernel pmap,
                   1509:         * remove the mappings; the i386 ignores
                   1510:         * the write-permission bit in kernel mode.
                   1511:         *
                   1512:         * XXX should be #if'd for i386
                   1513:         */
                   1514: 
                   1515:        if (cpuid_family == CPUID_FAMILY_386)
                   1516:            if (map == kernel_pmap) {
                   1517:                    pmap_remove(map, s, e);
                   1518:                    return;
                   1519:            }
                   1520: 
                   1521:        SPLVM(spl);
                   1522:        simple_lock(&map->lock);
                   1523: 
                   1524: 
                   1525:        pde = pmap_pde(map, s);
                   1526:        while (s < e) {
                   1527:            l = (s + PDE_MAPPED_SIZE) & ~(PDE_MAPPED_SIZE-1);
                   1528:            if (l > e)
                   1529:                l = e;
                   1530:            if (*pde & INTEL_PTE_VALID) {
                   1531:                spte = (pt_entry_t *)ptetokv(*pde);
                   1532:                spte = &spte[ptenum(s)];
                   1533:                epte = &spte[intel_btop(l-s)];
                   1534: 
                   1535:                while (spte < epte) {
                   1536:                    if (*spte & INTEL_PTE_VALID)
                   1537:                        *spte &= ~INTEL_PTE_WRITE;
                   1538:                    spte++;
                   1539:                }
                   1540:            }
                   1541:            s = l;
                   1542:            pde++;
                   1543:        }
                   1544: 
                   1545:        PMAP_FLUSH_TLBS();
                   1546: 
                   1547:        simple_unlock(&map->lock);
                   1548:        SPLX(spl);
                   1549: }
                   1550: 
                   1551: 
                   1552: 
                   1553: /*
                   1554:  *     Insert the given physical page (p) at
                   1555:  *     the specified virtual address (v) in the
                   1556:  *     target physical map with the protection requested.
                   1557:  *
                   1558:  *     If specified, the page will be wired down, meaning
                   1559:  *     that the related pte cannot be reclaimed.
                   1560:  *
                   1561:  *     NB:  This is the only routine which MAY NOT lazy-evaluate
                   1562:  *     or lose information.  That is, this routine must actually
                   1563:  *     insert this page into the given map NOW.
                   1564:  */
                   1565: void
                   1566: pmap_enter(
                   1567:        register pmap_t         pmap,
                   1568:        vm_offset_t             v,
                   1569:        register vm_offset_t    pa,
                   1570:        vm_prot_t               prot,
                   1571:        boolean_t               wired)
                   1572: {
                   1573:        register pt_entry_t     *pte;
                   1574:        register pv_entry_t     pv_h;
                   1575:        register int            i, pai;
                   1576:        pv_entry_t              pv_e;
                   1577:        pt_entry_t              template;
                   1578:        spl_t                   spl;
                   1579:        vm_offset_t             old_pa;
                   1580: 
                   1581:        XPR(0x80000000, "%x/%x: pmap_enter %x/%x/%x\n",
                   1582:            current_thread()->top_act,
                   1583:            current_thread(), 
                   1584:            pmap, v, pa);
                   1585: 
                   1586:        assert(pa != vm_page_fictitious_addr);
                   1587:        if (pmap_debug)
                   1588:                printf("pmap(%x, %x)\n", v, pa);
                   1589:        if (pmap == PMAP_NULL)
                   1590:                return;
                   1591: 
                   1592:        if (cpuid_family == CPUID_FAMILY_386)
                   1593:        if (pmap == kernel_pmap && (prot & VM_PROT_WRITE) == 0
                   1594:            && !wired /* hack for io_wire */ ) {
                   1595:            /*
                   1596:             *  Because the 386 ignores write protection in kernel mode,
                   1597:             *  we cannot enter a read-only kernel mapping, and must
                   1598:             *  remove an existing mapping if changing it.
                   1599:             *
                   1600:             *  XXX should be #if'd for i386
                   1601:             */
                   1602:            PMAP_READ_LOCK(pmap, spl);
                   1603: 
                   1604:            pte = pmap_pte(pmap, v);
                   1605:            if (pte != PT_ENTRY_NULL && pte_to_pa(*pte) != 0) {
                   1606:                /*
                   1607:                 *      Invalidate the translation buffer,
                   1608:                 *      then remove the mapping.
                   1609:                 */
                   1610:                PMAP_INVALIDATE_PAGE(pmap, v);
                   1611:                pmap_remove_range(pmap, v, pte,
                   1612:                                  pte + ptes_per_vm_page);
                   1613:            }
                   1614:            PMAP_READ_UNLOCK(pmap, spl);
                   1615:            return;
                   1616:        }
                   1617: 
                   1618:        /*
                   1619:         *      Must allocate a new pvlist entry while we're unlocked;
                   1620:         *      zalloc may cause pageout (which will lock the pmap system).
                   1621:         *      If we determine we need a pvlist entry, we will unlock
                   1622:         *      and allocate one.  Then we will retry, throughing away
                   1623:         *      the allocated entry later (if we no longer need it).
                   1624:         */
                   1625:        pv_e = PV_ENTRY_NULL;
                   1626: Retry:
                   1627:        PMAP_READ_LOCK(pmap, spl);
                   1628: 
                   1629:        /*
                   1630:         *      Expand pmap to include this pte.  Assume that
                   1631:         *      pmap is always expanded to include enough hardware
                   1632:         *      pages to map one VM page.
                   1633:         */
                   1634: 
                   1635:        while ((pte = pmap_pte(pmap, v)) == PT_ENTRY_NULL) {
                   1636:                /*
                   1637:                 *      Must unlock to expand the pmap.
                   1638:                 */
                   1639:                PMAP_READ_UNLOCK(pmap, spl);
                   1640: 
                   1641:                pmap_expand(pmap, v);
                   1642: 
                   1643:                PMAP_READ_LOCK(pmap, spl);
                   1644:        }
                   1645:        /*
                   1646:         *      Special case if the physical page is already mapped
                   1647:         *      at this address.
                   1648:         */
                   1649:        old_pa = pte_to_pa(*pte);
                   1650:        if (old_pa == pa) {
                   1651:            /*
                   1652:             *  May be changing its wired attribute or protection
                   1653:             */
                   1654:                
                   1655:            template = pa_to_pte(pa) | INTEL_PTE_VALID;
                   1656:            if (pmap != kernel_pmap)
                   1657:                template |= INTEL_PTE_USER;
                   1658:            if (prot & VM_PROT_WRITE)
                   1659:                template |= INTEL_PTE_WRITE;
                   1660:            if (wired) {
                   1661:                template |= INTEL_PTE_WIRED;
                   1662:                if (!iswired(*pte))
                   1663:                    pmap->stats.wired_count++;
                   1664:            }
                   1665:            else {
                   1666:                if (iswired(*pte)) {
                   1667:                    assert(pmap->stats.wired_count >= 1);
                   1668:                    pmap->stats.wired_count--;
                   1669:                }
                   1670:            }
                   1671: 
                   1672:            PMAP_INVALIDATE_PAGE(pmap, v);
                   1673: 
                   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:            goto Done;
                   1684:        }
                   1685: 
                   1686:        /*
                   1687:         *      Outline of code from here:
                   1688:         *         1) If va was mapped, update TLBs, remove the mapping
                   1689:         *            and remove old pvlist entry.
                   1690:         *         2) Add pvlist entry for new mapping
                   1691:         *         3) Enter new mapping.
                   1692:         *
                   1693:         *      SHARING_FAULTS complicates this slightly in that it cannot
                   1694:         *      replace the mapping, but must remove it (because adding the
                   1695:         *      pvlist entry for the new mapping may remove others), and
                   1696:         *      hence always enters the new mapping at step 3)
                   1697:         *
                   1698:         *      If the old physical page is not managed step 1) is skipped
                   1699:         *      (except for updating the TLBs), and the mapping is
                   1700:         *      overwritten at step 3).  If the new physical page is not
                   1701:         *      managed, step 2) is skipped.
                   1702:         */
                   1703: 
                   1704:        if (old_pa != (vm_offset_t) 0) {
                   1705: 
                   1706:            PMAP_INVALIDATE_PAGE(pmap, v);
                   1707: 
                   1708: #if    DEBUG_PTE_PAGE
                   1709:            if (pmap != kernel_pmap)
                   1710:                ptep_check(get_pte_page(pte));
                   1711: #endif /* DEBUG_PTE_PAGE */
                   1712: 
                   1713:            /*
                   1714:             *  Don't do anything to pages outside valid memory here.
                   1715:             *  Instead convince the code that enters a new mapping
                   1716:             *  to overwrite the old one.
                   1717:             */
                   1718: 
                   1719:            if (valid_page(old_pa)) {
                   1720: 
                   1721:                pai = pa_index(old_pa);
                   1722:                LOCK_PVH(pai);
                   1723: 
                   1724:                assert(pmap->stats.resident_count >= 1);
                   1725:                pmap->stats.resident_count--;
                   1726:                if (iswired(*pte)) {
                   1727:                    assert(pmap->stats.wired_count >= 1);
                   1728:                    pmap->stats.wired_count--;
                   1729:                }
                   1730:                i = ptes_per_vm_page;
                   1731:                do {
                   1732:                    pmap_phys_attributes[pai] |=
                   1733:                        *pte & (PHYS_MODIFIED|PHYS_REFERENCED);
                   1734:                    WRITE_PTE(pte, 0)
                   1735:                    pte++;
                   1736:                    pte_increment_pa(template);
                   1737:                } while (--i > 0);
                   1738: 
                   1739:                /*
                   1740:                 * Put pte back to beginning of page since it'll be
                   1741:                 * used later to enter the new page.
                   1742:                 */
                   1743:                pte -= ptes_per_vm_page;
                   1744: 
                   1745:                /*
                   1746:                 *      Remove the mapping from the pvlist for
                   1747:                 *      this physical page.
                   1748:                 */
                   1749:                {
                   1750:                    register pv_entry_t prev, cur;
                   1751: 
                   1752:                    pv_h = pai_to_pvh(pai);
                   1753:                    if (pv_h->pmap == PMAP_NULL) {
                   1754:                        panic("pmap_enter: null pv_list!");
                   1755:                    }
                   1756:                    if (pv_h->va == v && pv_h->pmap == pmap) {
                   1757:                        /*
                   1758:                         * Header is the pv_entry.  Copy the next one
                   1759:                         * to header and free the next one (we cannot
                   1760:                         * free the header)
                   1761:                         */
                   1762:                        cur = pv_h->next;
                   1763:                        if (cur != PV_ENTRY_NULL) {
                   1764:                            *pv_h = *cur;
                   1765:                            pv_e = cur;
                   1766:                        }
                   1767:                        else {
                   1768:                            pv_h->pmap = PMAP_NULL;
                   1769:                        }
                   1770:                    }
                   1771:                    else {
                   1772:                        cur = pv_h;
                   1773:                        do {
                   1774:                            prev = cur;
                   1775:                            if ((cur = prev->next) == PV_ENTRY_NULL) {
                   1776:                                panic("pmap_enter: mapping not in pv_list!");
                   1777:                            }
                   1778:                        } while (cur->va != v || cur->pmap != pmap);
                   1779:                        prev->next = cur->next;
                   1780:                        pv_e = cur;
                   1781:                    }
                   1782:                }
                   1783:                UNLOCK_PVH(pai);
                   1784:            }
                   1785:            else {
                   1786: 
                   1787:                /*
                   1788:                 *      old_pa is not managed.  Pretend it's zero so code
                   1789:                 *      at Step 3) will enter new mapping (overwriting old
                   1790:                 *      one).  Do removal part of accounting.
                   1791:                 */
                   1792:                old_pa = (vm_offset_t) 0;
                   1793:                assert(pmap->stats.resident_count >= 1);
                   1794:                pmap->stats.resident_count--;
                   1795:                if (iswired(*pte)) {
                   1796:                    assert(pmap->stats.wired_count >= 1);
                   1797:                    pmap->stats.wired_count--;
                   1798:                }
                   1799:            }
                   1800:        }
                   1801: 
                   1802:        if (valid_page(pa)) {
                   1803: 
                   1804:            /*
                   1805:             *  Step 2) Enter the mapping in the PV list for this
                   1806:             *  physical page.
                   1807:             */
                   1808: 
                   1809:            pai = pa_index(pa);
                   1810: 
                   1811: 
                   1812: #if SHARING_FAULTS
                   1813: RetryPvList:
                   1814:            /*
                   1815:             * We can return here from the sharing fault code below
                   1816:             * in case we removed the only entry on the pv list and thus
                   1817:             * must enter the new one in the list header.
                   1818:             */
                   1819: #endif /* SHARING_FAULTS */
                   1820:            LOCK_PVH(pai);
                   1821:            pv_h = pai_to_pvh(pai);
                   1822: 
                   1823:            if (pv_h->pmap == PMAP_NULL) {
                   1824:                /*
                   1825:                 *      No mappings yet
                   1826:                 */
                   1827:                pv_h->va = v;
                   1828:                pv_h->pmap = pmap;
                   1829:                pv_h->next = PV_ENTRY_NULL;
                   1830:            }
                   1831:            else {
                   1832: #if    DEBUG
                   1833:                {
                   1834:                    /*
                   1835:                     * check that this mapping is not already there
                   1836:                     * or there is no alias for this mapping in the same map
                   1837:                     */
                   1838:                    pv_entry_t  e = pv_h;
                   1839:                    while (e != PV_ENTRY_NULL) {
                   1840:                        if (e->pmap == pmap && e->va == v)
                   1841:                             panic("pmap_enter: already in pv_list");
                   1842:                        e = e->next;
                   1843:                    }
                   1844:                }
                   1845: #endif /* DEBUG */
                   1846: #if SHARING_FAULTS
                   1847:                 {
                   1848:                     /*
                   1849:                      * do sharing faults.
                   1850:                      * if we find an entry on this pv list in the same address
                   1851:                     * space, remove it.  we know there will not be more
                   1852:                     * than one. 
                   1853:                     */
                   1854:                    pv_entry_t  e = pv_h;
                   1855:                     pt_entry_t      *opte;
                   1856: 
                   1857:                    while (e != PV_ENTRY_NULL) {
                   1858:                        if (e->pmap == pmap) {
                   1859:                             /*
                   1860:                             *  Remove it, drop pv list lock first.
                   1861:                             */
                   1862:                             UNLOCK_PVH(pai);
                   1863: 
                   1864:                             opte = pmap_pte(pmap, e->va);
                   1865:                             assert(opte != PT_ENTRY_NULL);
                   1866:                             /*
                   1867:                             *  Invalidate the translation buffer,
                   1868:                             *  then remove the mapping.
                   1869:                             */
                   1870:                             PMAP_INVALIDATE_PAGE(pmap, e->va);
                   1871:                              pmap_remove_range(pmap, e->va, opte,
                   1872:                                                       opte + ptes_per_vm_page);
                   1873:                             /*
                   1874:                              * We could have remove the head entry,
                   1875:                              * so there could be no more entries
                   1876:                              * and so we have to use the pv head entry.
                   1877:                              * so, go back to the top and try the entry
                   1878:                              * again.
                   1879:                              */
                   1880:                             goto RetryPvList;
                   1881:                        }
                   1882:                         e = e->next;
                   1883:                    }
                   1884: 
                   1885:                    /*
                   1886:                      * check that this mapping is not already there
                   1887:                      */
                   1888:                    e = pv_h;
                   1889:                    while (e != PV_ENTRY_NULL) {
                   1890:                        if (e->pmap == pmap)
                   1891:                             panic("pmap_enter: alias in pv_list");
                   1892:                        e = e->next;
                   1893:                    }
                   1894:                }
                   1895: #endif /* SHARING_FAULTS */
                   1896: #if DEBUG_ALIAS
                   1897:                 {
                   1898:                     /*
                   1899:                      * check for aliases within the same address space.
                   1900:                      */
                   1901:                    pv_entry_t  e = pv_h;
                   1902:                     vm_offset_t     rpc = get_rpc();
                   1903: 
                   1904:                    while (e != PV_ENTRY_NULL) {
                   1905:                        if (e->pmap == pmap) {
                   1906:                             /*
                   1907:                              * log this entry in the alias ring buffer
                   1908:                             * if it's not there already.
                   1909:                              */
                   1910:                             struct pmap_alias *pma;
                   1911:                             int ii, logit;
                   1912: 
                   1913:                             logit = TRUE;
                   1914:                             for (ii = 0; ii < pmap_alias_index; ii++) {
                   1915:                                 if (pmap_aliasbuf[ii].rpc == rpc) {
                   1916:                                     /* found it in the log already */
                   1917:                                     logit = FALSE;
                   1918:                                     break;
                   1919:                                }
                   1920:                            }
                   1921:                             if (logit) {
                   1922:                                 pma = &pmap_aliasbuf[pmap_alias_index];
                   1923:                                 pma->pmap = pmap;
                   1924:                                 pma->va = v;
                   1925:                                 pma->rpc = rpc;
                   1926:                                 pma->cookie = PMAP_ALIAS_COOKIE;
                   1927:                                 if (++pmap_alias_index >= PMAP_ALIAS_MAX)
                   1928:                                     panic("pmap_enter: exhausted alias log");
                   1929:                            }
                   1930:                        }
                   1931:                         e = e->next;
                   1932:                    }
                   1933:                }
                   1934: #endif /* DEBUG_ALIAS */
                   1935:                /*
                   1936:                 *      Add new pv_entry after header.
                   1937:                 */
                   1938:                if (pv_e == PV_ENTRY_NULL) {
                   1939:                    PV_ALLOC(pv_e);
                   1940:                    if (pv_e == PV_ENTRY_NULL) {
                   1941:                        UNLOCK_PVH(pai);
                   1942:                        PMAP_READ_UNLOCK(pmap, spl);
                   1943: 
                   1944:                        /*
                   1945:                         * Refill from zone.
                   1946:                         */
                   1947:                        pv_e = (pv_entry_t) zalloc(pv_list_zone);
                   1948:                        goto Retry;
                   1949:                    }
                   1950:                }
                   1951:                pv_e->va = v;
                   1952:                pv_e->pmap = pmap;
                   1953:                pv_e->next = pv_h->next;
                   1954:                pv_h->next = pv_e;
                   1955:                /*
                   1956:                 *      Remember that we used the pvlist entry.
                   1957:                 */
                   1958:                pv_e = PV_ENTRY_NULL;
                   1959:            }
                   1960:            UNLOCK_PVH(pai);
                   1961:        }
                   1962: 
                   1963:        /*
                   1964:         * Step 3) Enter and count the mapping.
                   1965:         */
                   1966: 
                   1967:        pmap->stats.resident_count++;
                   1968: 
                   1969:        /*
                   1970:         *      Build a template to speed up entering -
                   1971:         *      only the pfn changes.
                   1972:         */
                   1973:        template = pa_to_pte(pa) | INTEL_PTE_VALID;
                   1974:        if (pmap != kernel_pmap)
                   1975:                template |= INTEL_PTE_USER;
                   1976:        if (prot & VM_PROT_WRITE)
                   1977:                template |= INTEL_PTE_WRITE;
                   1978:        if (wired) {
                   1979:                template |= INTEL_PTE_WIRED;
                   1980:                pmap->stats.wired_count++;
                   1981:        }
                   1982:        i = ptes_per_vm_page;
                   1983:        do {
                   1984:                WRITE_PTE(pte, template)
                   1985:                pte++;
                   1986:                pte_increment_pa(template);
                   1987:        } while (--i > 0);
                   1988: Done:
                   1989:        if (pv_e != PV_ENTRY_NULL) {
                   1990:            PV_FREE(pv_e);
                   1991:        }
                   1992: 
                   1993:        PMAP_READ_UNLOCK(pmap, spl);
                   1994: }
                   1995: 
                   1996: /*
                   1997:  *     Routine:        pmap_change_wiring
                   1998:  *     Function:       Change the wiring attribute for a map/virtual-address
                   1999:  *                     pair.
                   2000:  *     In/out conditions:
                   2001:  *                     The mapping must already exist in the pmap.
                   2002:  */
                   2003: void
                   2004: pmap_change_wiring(
                   2005:        register pmap_t map,
                   2006:        vm_offset_t     v,
                   2007:        boolean_t       wired)
                   2008: {
                   2009:        register pt_entry_t     *pte;
                   2010:        register int            i;
                   2011:        spl_t                   spl;
                   2012: 
                   2013:        /*
                   2014:         *      We must grab the pmap system lock because we may
                   2015:         *      change a pte_page queue.
                   2016:         */
                   2017:        PMAP_READ_LOCK(map, spl);
                   2018: 
                   2019:        if ((pte = pmap_pte(map, v)) == PT_ENTRY_NULL)
                   2020:                panic("pmap_change_wiring: pte missing");
                   2021: 
                   2022:        if (wired && !iswired(*pte)) {
                   2023:            /*
                   2024:             *  wiring down mapping
                   2025:             */
                   2026:            map->stats.wired_count++;
                   2027:            i = ptes_per_vm_page;
                   2028:            do {
                   2029:                *pte++ |= INTEL_PTE_WIRED;
                   2030:            } while (--i > 0);
                   2031:        }
                   2032:        else if (!wired && iswired(*pte)) {
                   2033:            /*
                   2034:             *  unwiring mapping
                   2035:             */
                   2036:            assert(map->stats.wired_count >= 1);
                   2037:            map->stats.wired_count--;
                   2038:            i = ptes_per_vm_page;
                   2039:            do {
                   2040:                *pte++ &= ~INTEL_PTE_WIRED;
                   2041:            } while (--i > 0);
                   2042:        }
                   2043: 
                   2044:        PMAP_READ_UNLOCK(map, spl);
                   2045: }
                   2046: 
                   2047: /*
                   2048:  *     Routine:        pmap_extract
                   2049:  *     Function:
                   2050:  *             Extract the physical page address associated
                   2051:  *             with the given map/virtual_address pair.
                   2052:  */
                   2053: 
                   2054: vm_offset_t
                   2055: pmap_extract(
                   2056:        register pmap_t pmap,
                   2057:        vm_offset_t     va)
                   2058: {
                   2059:        register pt_entry_t     *pte;
                   2060:        register vm_offset_t    pa;
                   2061:        spl_t                   spl;
                   2062: 
                   2063:        SPLVM(spl);
                   2064:        simple_lock(&pmap->lock);
                   2065:        if ((pte = pmap_pte(pmap, va)) == PT_ENTRY_NULL)
                   2066:            pa = (vm_offset_t) 0;
                   2067:        else if (!(*pte & INTEL_PTE_VALID))
                   2068:            pa = (vm_offset_t) 0;
                   2069:        else
                   2070:            pa = pte_to_pa(*pte) + (va & INTEL_OFFMASK);
                   2071:        simple_unlock(&pmap->lock);
                   2072:        SPLX(spl);
                   2073:        return(pa);
                   2074: }
                   2075: 
                   2076: /*
                   2077:  *     Routine:        pmap_expand
                   2078:  *
                   2079:  *     Expands a pmap to be able to map the specified virtual address.
                   2080:  *
                   2081:  *     Allocates new virtual memory for the P0 or P1 portion of the
                   2082:  *     pmap, then re-maps the physical pages that were in the old
                   2083:  *     pmap to be in the new pmap.
                   2084:  *
                   2085:  *     Must be called with the pmap system and the pmap unlocked,
                   2086:  *     since these must be unlocked to use vm_allocate or vm_deallocate.
                   2087:  *     Thus it must be called in a loop that checks whether the map
                   2088:  *     has been expanded enough.
                   2089:  *     (We won't loop forever, since page tables aren't shrunk.)
                   2090:  */
                   2091: void
                   2092: pmap_expand(
                   2093:        register pmap_t         map,
                   2094:        register vm_offset_t    v)
                   2095: {
                   2096:        pt_entry_t              *pdp;
                   2097:        register vm_page_t      m;
                   2098:        register vm_offset_t    pa;
                   2099:        register int            i;
                   2100:        spl_t                   spl;
                   2101: 
                   2102:        if (map == kernel_pmap)
                   2103:            panic("pmap_expand");
                   2104: 
                   2105:        /*
                   2106:         *      We cannot allocate the pmap_object in pmap_init,
                   2107:         *      because it is called before the zone package is up.
                   2108:         *      Allocate it now if it is missing.
                   2109:         */
                   2110:        if (pmap_object == VM_OBJECT_NULL)
                   2111:            pmap_object = vm_object_allocate(avail_end);
                   2112: 
                   2113:        /*
                   2114:         *      Allocate a VM page for the level 2 page table entries.
                   2115:         */
                   2116:        while ((m = vm_page_grab()) == VM_PAGE_NULL)
                   2117:                VM_PAGE_WAIT();
                   2118: 
                   2119:        /*
                   2120:         *      Map the page to its physical address so that it
                   2121:         *      can be found later.
                   2122:         */
                   2123:        pa = m->phys_addr;
                   2124:        vm_object_lock(pmap_object);
                   2125:        vm_page_insert(m, pmap_object, pa);
                   2126:        vm_page_lock_queues();
                   2127:        vm_page_wire(m);
                   2128:        inuse_ptepages_count++;
                   2129:        vm_object_unlock(pmap_object);
                   2130:        vm_page_unlock_queues();
                   2131: 
                   2132:        /*
                   2133:         *      Zero the page.
                   2134:         */
                   2135:        memset((void *)phystokv(pa), 0, PAGE_SIZE);
                   2136: 
                   2137:        PMAP_READ_LOCK(map, spl);
                   2138:        /*
                   2139:         *      See if someone else expanded us first
                   2140:         */
                   2141:        if (pmap_pte(map, v) != PT_ENTRY_NULL) {
                   2142:                PMAP_READ_UNLOCK(map, spl);
                   2143:                vm_object_lock(pmap_object);
                   2144:                vm_page_lock_queues();
                   2145:                vm_page_free(m);
                   2146:                inuse_ptepages_count--;
                   2147:                vm_page_unlock_queues();
                   2148:                vm_object_unlock(pmap_object);
                   2149:                return;
                   2150:        }
                   2151: 
                   2152:        /*
                   2153:         *      Set the page directory entry for this page table.
                   2154:         *      If we have allocated more than one hardware page,
                   2155:         *      set several page directory entries.
                   2156:         */
                   2157: 
                   2158:        i = ptes_per_vm_page;
                   2159:        pdp = &map->dirbase[pdenum(map, v) & ~(i-1)];
                   2160:        do {
                   2161:            *pdp = pa_to_pte(pa)
                   2162:                | INTEL_PTE_VALID
                   2163:                | INTEL_PTE_USER
                   2164:                | INTEL_PTE_WRITE;
                   2165:            pdp++;
                   2166:            pa += INTEL_PGBYTES;
                   2167:        } while (--i > 0);
                   2168: 
                   2169:        PMAP_READ_UNLOCK(map, spl);
                   2170:        return;
                   2171: }
                   2172: 
                   2173: /*
                   2174:  *     Copy the range specified by src_addr/len
                   2175:  *     from the source map to the range dst_addr/len
                   2176:  *     in the destination map.
                   2177:  *
                   2178:  *     This routine is only advisory and need not do anything.
                   2179:  */
                   2180: #if    0
                   2181: void
                   2182: pmap_copy(
                   2183:        pmap_t          dst_pmap,
                   2184:        pmap_t          src_pmap,
                   2185:        vm_offset_t     dst_addr,
                   2186:        vm_size_t       len,
                   2187:        vm_offset_t     src_addr)
                   2188: {
                   2189: #ifdef lint
                   2190:        dst_pmap++; src_pmap++; dst_addr++; len++; src_addr++;
                   2191: #endif /* lint */
                   2192: }
                   2193: #endif/*       0 */
                   2194: 
                   2195: int    collect_ref;
                   2196: int    collect_unref;
                   2197: 
                   2198: /*
                   2199:  *     Routine:        pmap_collect
                   2200:  *     Function:
                   2201:  *             Garbage collects the physical map system for
                   2202:  *             pages which are no longer used.
                   2203:  *             Success need not be guaranteed -- that is, there
                   2204:  *             may well be pages which are not referenced, but
                   2205:  *             others may be collected.
                   2206:  *     Usage:
                   2207:  *             Called by the pageout daemon when pages are scarce.
                   2208:  */
                   2209: void
                   2210: pmap_collect(
                   2211:        pmap_t          p)
                   2212: {
                   2213:        register pt_entry_t     *pdp, *ptp;
                   2214:        pt_entry_t              *eptp;
                   2215:        vm_offset_t             pa;
                   2216:        int                     wired;
                   2217:        spl_t                   spl;
                   2218: 
                   2219:        if (p == PMAP_NULL)
                   2220:                return;
                   2221: 
                   2222:        if (p == kernel_pmap)
                   2223:                return;
                   2224: 
                   2225:        /*
                   2226:         *      Garbage collect map.
                   2227:         */
                   2228:        PMAP_READ_LOCK(p, spl);
                   2229:        PMAP_FLUSH_TLBS();
                   2230: 
                   2231:        for (pdp = p->dirbase;
                   2232:             pdp < &p->dirbase[pdenum(p, LINEAR_KERNEL_ADDRESS)];
                   2233:             pdp += ptes_per_vm_page)
                   2234:        {
                   2235:            if (*pdp & INTEL_PTE_VALID) 
                   2236:              if(*pdp & INTEL_PTE_REF) {
                   2237:                *pdp &= ~INTEL_PTE_REF;
                   2238:                collect_ref++;
                   2239:              } else {
                   2240:                collect_unref++;
                   2241:                pa = pte_to_pa(*pdp);
                   2242:                ptp = (pt_entry_t *)phystokv(pa);
                   2243:                eptp = ptp + NPTES*ptes_per_vm_page;
                   2244: 
                   2245:                /*
                   2246:                 * If the pte page has any wired mappings, we cannot
                   2247:                 * free it.
                   2248:                 */
                   2249:                wired = 0;
                   2250:                {
                   2251:                    register pt_entry_t *ptep;
                   2252:                    for (ptep = ptp; ptep < eptp; ptep++) {
                   2253:                        if (iswired(*ptep)) {
                   2254:                            wired = 1;
                   2255:                            break;
                   2256:                        }
                   2257:                    }
                   2258:                }
                   2259:                if (!wired) {
                   2260:                    /*
                   2261:                     * Remove the virtual addresses mapped by this pte page.
                   2262:                     */
                   2263:                    pmap_remove_range(p,
                   2264:                                pdetova(pdp - p->dirbase),
                   2265:                                ptp,
                   2266:                                eptp);
                   2267: 
                   2268:                    /*
                   2269:                     * Invalidate the page directory pointer.
                   2270:                     */
                   2271:                    {
                   2272:                        register int i = ptes_per_vm_page;
                   2273:                        register pt_entry_t *pdep = pdp;
                   2274:                        do {
                   2275:                            *pdep++ = 0;
                   2276:                        } while (--i > 0);
                   2277:                    }
                   2278: 
                   2279:                    PMAP_READ_UNLOCK(p, spl);
                   2280: 
                   2281:                    /*
                   2282:                     * And free the pte page itself.
                   2283:                     */
                   2284:                    {
                   2285:                        register vm_page_t m;
                   2286: 
                   2287:                        vm_object_lock(pmap_object);
                   2288:                        m = vm_page_lookup(pmap_object, pa);
                   2289:                        if (m == VM_PAGE_NULL)
                   2290:                            panic("pmap_collect: pte page not in object");
                   2291:                        vm_page_lock_queues();
                   2292:                        vm_page_free(m);
                   2293:                        inuse_ptepages_count--;
                   2294:                        vm_page_unlock_queues();
                   2295:                        vm_object_unlock(pmap_object);
                   2296:                    }
                   2297: 
                   2298:                    PMAP_READ_LOCK(p, spl);
                   2299:                }
                   2300:            }
                   2301:        }
                   2302:        PMAP_READ_UNLOCK(p, spl);
                   2303:        return;
                   2304: 
                   2305: }
                   2306: 
                   2307: /*
                   2308:  *     Routine:        pmap_kernel
                   2309:  *     Function:
                   2310:  *             Returns the physical map handle for the kernel.
                   2311:  */
                   2312: #if    0
                   2313: pmap_t
                   2314: pmap_kernel(void)
                   2315: {
                   2316:        return (kernel_pmap);
                   2317: }
                   2318: #endif/*       0 */
                   2319: 
                   2320: /*
                   2321:  *     pmap_zero_page zeros the specified (machine independent) page.
                   2322:  *     See machine/phys.c or machine/phys.s for implementation.
                   2323:  */
                   2324: #if    0
                   2325: void
                   2326: pmap_zero_page(
                   2327:        register vm_offset_t    phys)
                   2328: {
                   2329:        register int    i;
                   2330: 
                   2331:        assert(phys != vm_page_fictitious_addr);
                   2332:        i = PAGE_SIZE / INTEL_PGBYTES;
                   2333:        phys = intel_pfn(phys);
                   2334: 
                   2335:        while (i--)
                   2336:                zero_phys(phys++);
                   2337: }
                   2338: #endif/*       0 */
                   2339: 
                   2340: /*
                   2341:  *     pmap_copy_page copies the specified (machine independent) page.
                   2342:  *     See machine/phys.c or machine/phys.s for implementation.
                   2343:  */
                   2344: #if    0
                   2345: void
                   2346: pmap_copy_page(
                   2347:        vm_offset_t     src,
                   2348:        vm_offset_t     dst)
                   2349: {
                   2350:        int     i;
                   2351: 
                   2352:        assert(src != vm_page_fictitious_addr);
                   2353:        assert(dst != vm_page_fictitious_addr);
                   2354:        i = PAGE_SIZE / INTEL_PGBYTES;
                   2355: 
                   2356:        while (i--) {
                   2357:                copy_phys(intel_pfn(src), intel_pfn(dst));
                   2358:                src += INTEL_PGBYTES;
                   2359:                dst += INTEL_PGBYTES;
                   2360:        }
                   2361: }
                   2362: #endif/*       0 */
                   2363: 
                   2364: /*
                   2365:  *     Routine:        pmap_pageable
                   2366:  *     Function:
                   2367:  *             Make the specified pages (by pmap, offset)
                   2368:  *             pageable (or not) as requested.
                   2369:  *
                   2370:  *             A page which is not pageable may not take
                   2371:  *             a fault; therefore, its page table entry
                   2372:  *             must remain valid for the duration.
                   2373:  *
                   2374:  *             This routine is merely advisory; pmap_enter
                   2375:  *             will specify that these pages are to be wired
                   2376:  *             down (or not) as appropriate.
                   2377:  */
                   2378: void
                   2379: pmap_pageable(
                   2380:        pmap_t          pmap,
                   2381:        vm_offset_t     start,
                   2382:        vm_offset_t     end,
                   2383:        boolean_t       pageable)
                   2384: {
                   2385: #ifdef lint
                   2386:        pmap++; start++; end++; pageable++;
                   2387: #endif /* lint */
                   2388: }
                   2389: 
                   2390: /*
                   2391:  *     Clear specified attribute bits.
                   2392:  */
                   2393: void
                   2394: phys_attribute_clear(
                   2395:        vm_offset_t     phys,
                   2396:        int             bits)
                   2397: {
                   2398:        pv_entry_t              pv_h;
                   2399:        register pv_entry_t     pv_e;
                   2400:        register pt_entry_t     *pte;
                   2401:        int                     pai;
                   2402:        register pmap_t         pmap;
                   2403:        spl_t                   spl;
                   2404: 
                   2405:        assert(phys != vm_page_fictitious_addr);
                   2406:        if (!valid_page(phys)) {
                   2407:            /*
                   2408:             *  Not a managed page.
                   2409:             */
                   2410:            return;
                   2411:        }
                   2412: 
                   2413:        /*
                   2414:         *      Lock the pmap system first, since we will be changing
                   2415:         *      several pmaps.
                   2416:         */
                   2417: 
                   2418:        PMAP_WRITE_LOCK(spl);
                   2419: 
                   2420:        pai = pa_index(phys);
                   2421:        pv_h = pai_to_pvh(pai);
                   2422: 
                   2423:        /*
                   2424:         * Walk down PV list, clearing all modify or reference bits.
                   2425:         * We do not have to lock the pv_list because we have
                   2426:         * the entire pmap system locked.
                   2427:         */
                   2428:        if (pv_h->pmap != PMAP_NULL) {
                   2429:            /*
                   2430:             * There are some mappings.
                   2431:             */
                   2432:            for (pv_e = pv_h; pv_e != PV_ENTRY_NULL; pv_e = pv_e->next) {
                   2433: 
                   2434:                pmap = pv_e->pmap;
                   2435:                /*
                   2436:                 * Lock the pmap to block pmap_extract and similar routines.
                   2437:                 */
                   2438:                simple_lock(&pmap->lock);
                   2439: 
                   2440:                {
                   2441:                    register vm_offset_t va;
                   2442: 
                   2443:                    va = pv_e->va;
                   2444:                    pte = pmap_pte(pmap, va);
                   2445: 
                   2446: #if    0
                   2447:                    /*
                   2448:                     * Consistency checks.
                   2449:                     */
                   2450:                    assert(*pte & INTEL_PTE_VALID);
                   2451:                    /* assert(pte_to_phys(*pte) == phys); */
                   2452: #endif
                   2453: 
                   2454:                    /*
                   2455:                     * Invalidate TLBs for all CPUs using this mapping.
                   2456:                     */
                   2457:                    PMAP_INVALIDATE_PAGE(pmap, va);
                   2458:                }
                   2459: 
                   2460:                /*
                   2461:                 * Clear modify or reference bits.
                   2462:                 */
                   2463:                {
                   2464:                    register int        i = ptes_per_vm_page;
                   2465:                    do {
                   2466:                        *pte++ &= ~bits;
                   2467:                    } while (--i > 0);
                   2468:                }
                   2469:                simple_unlock(&pmap->lock);
                   2470:            }
                   2471:        }
                   2472: 
                   2473:        pmap_phys_attributes[pai] &= ~bits;
                   2474: 
                   2475:        PMAP_WRITE_UNLOCK(spl);
                   2476: }
                   2477: 
                   2478: /*
                   2479:  *     Check specified attribute bits.
                   2480:  */
                   2481: boolean_t
                   2482: phys_attribute_test(
                   2483:        vm_offset_t     phys,
                   2484:        int             bits)
                   2485: {
                   2486:        pv_entry_t              pv_h;
                   2487:        register pv_entry_t     pv_e;
                   2488:        register pt_entry_t     *pte;
                   2489:        int                     pai;
                   2490:        register pmap_t         pmap;
                   2491:        spl_t                   spl;
                   2492: 
                   2493:        assert(phys != vm_page_fictitious_addr);
                   2494:        if (!valid_page(phys)) {
                   2495:            /*
                   2496:             *  Not a managed page.
                   2497:             */
                   2498:            return (FALSE);
                   2499:        }
                   2500: 
                   2501:        /*
                   2502:         *      Lock the pmap system first, since we will be checking
                   2503:         *      several pmaps.
                   2504:         */
                   2505: 
                   2506:        PMAP_WRITE_LOCK(spl);
                   2507: 
                   2508:        pai = pa_index(phys);
                   2509:        pv_h = pai_to_pvh(pai);
                   2510: 
                   2511:        if (pmap_phys_attributes[pai] & bits) {
                   2512:            PMAP_WRITE_UNLOCK(spl);
                   2513:            return (TRUE);
                   2514:        }
                   2515: 
                   2516:        /*
                   2517:         * Walk down PV list, checking all mappings.
                   2518:         * We do not have to lock the pv_list because we have
                   2519:         * the entire pmap system locked.
                   2520:         */
                   2521:        if (pv_h->pmap != PMAP_NULL) {
                   2522:            /*
                   2523:             * There are some mappings.
                   2524:             */
                   2525:            for (pv_e = pv_h; pv_e != PV_ENTRY_NULL; pv_e = pv_e->next) {
                   2526: 
                   2527:                pmap = pv_e->pmap;
                   2528:                /*
                   2529:                 * Lock the pmap to block pmap_extract and similar routines.
                   2530:                 */
                   2531:                simple_lock(&pmap->lock);
                   2532: 
                   2533:                {
                   2534:                    register vm_offset_t va;
                   2535: 
                   2536:                    va = pv_e->va;
                   2537:                    pte = pmap_pte(pmap, va);
                   2538: 
                   2539: #if    0
                   2540:                    /*
                   2541:                     * Consistency checks.
                   2542:                     */
                   2543:                    assert(*pte & INTEL_PTE_VALID);
                   2544:                    /* assert(pte_to_phys(*pte) == phys); */
                   2545: #endif
                   2546:                }
                   2547: 
                   2548:                /*
                   2549:                 * Check modify or reference bits.
                   2550:                 */
                   2551:                {
                   2552:                    register int        i = ptes_per_vm_page;
                   2553: 
                   2554:                    do {
                   2555:                        if (*pte++ & bits) {
                   2556:                            simple_unlock(&pmap->lock);
                   2557:                            PMAP_WRITE_UNLOCK(spl);
                   2558:                            return (TRUE);
                   2559:                        }
                   2560:                    } while (--i > 0);
                   2561:                }
                   2562:                simple_unlock(&pmap->lock);
                   2563:            }
                   2564:        }
                   2565:        PMAP_WRITE_UNLOCK(spl);
                   2566:        return (FALSE);
                   2567: }
                   2568: 
                   2569: /*
                   2570:  *     Set specified attribute bits.
                   2571:  */
                   2572: void
                   2573: phys_attribute_set(
                   2574:        vm_offset_t     phys,
                   2575:        int             bits)
                   2576: {
                   2577:        int                     spl;
                   2578: 
                   2579:        assert(phys != vm_page_fictitious_addr);
                   2580:        if (!valid_page(phys)) {
                   2581:            /*
                   2582:             *  Not a managed page.
                   2583:             */
                   2584:            return;
                   2585:        }
                   2586: 
                   2587:        /*
                   2588:         *      Lock the pmap system and set the requested bits in
                   2589:         *      the phys attributes array.  Don't need to bother with
                   2590:         *      ptes because the test routine looks here first.
                   2591:         */
                   2592: 
                   2593:        PMAP_WRITE_LOCK(spl);
                   2594:        pmap_phys_attributes[pa_index(phys)] |= bits;
                   2595:        PMAP_WRITE_UNLOCK(spl);
                   2596: }
                   2597: 
                   2598: /*
                   2599:  *     Set the modify bit on the specified physical page.
                   2600:  */
                   2601: 
                   2602: void pmap_set_modify(
                   2603:        register vm_offset_t    phys)
                   2604: {
                   2605:        phys_attribute_set(phys, PHYS_MODIFIED);
                   2606: }
                   2607: 
                   2608: /*
                   2609:  *     Clear the modify bits on the specified physical page.
                   2610:  */
                   2611: 
                   2612: void
                   2613: pmap_clear_modify(
                   2614:        register vm_offset_t    phys)
                   2615: {
                   2616:        phys_attribute_clear(phys, PHYS_MODIFIED);
                   2617: }
                   2618: 
                   2619: /*
                   2620:  *     pmap_is_modified:
                   2621:  *
                   2622:  *     Return whether or not the specified physical page is modified
                   2623:  *     by any physical maps.
                   2624:  */
                   2625: 
                   2626: boolean_t
                   2627: pmap_is_modified(
                   2628:        register vm_offset_t    phys)
                   2629: {
                   2630:        return (phys_attribute_test(phys, PHYS_MODIFIED));
                   2631: }
                   2632: 
                   2633: /*
                   2634:  *     pmap_clear_reference:
                   2635:  *
                   2636:  *     Clear the reference bit on the specified physical page.
                   2637:  */
                   2638: 
                   2639: void
                   2640: pmap_clear_reference(
                   2641:        vm_offset_t     phys)
                   2642: {
                   2643:        phys_attribute_clear(phys, PHYS_REFERENCED);
                   2644: }
                   2645: 
                   2646: /*
                   2647:  *     pmap_is_referenced:
                   2648:  *
                   2649:  *     Return whether or not the specified physical page is referenced
                   2650:  *     by any physical maps.
                   2651:  */
                   2652: 
                   2653: boolean_t
                   2654: pmap_is_referenced(
                   2655:        vm_offset_t     phys)
                   2656: {
                   2657:        return (phys_attribute_test(phys, PHYS_REFERENCED));
                   2658: }
                   2659: 
                   2660: /*
                   2661:  *     Set the modify bit on the specified range
                   2662:  *     of this map as requested.
                   2663:  *
                   2664:  *     This optimization stands only if each time the dirty bit
                   2665:  *     in vm_page_t is tested, it is also tested in the pmap.
                   2666:  */
                   2667: void
                   2668: pmap_modify_pages(
                   2669:        pmap_t          map,
                   2670:        vm_offset_t     s,
                   2671:        vm_offset_t     e)
                   2672: {
                   2673:        spl_t                   spl;
                   2674:        register pt_entry_t     *pde;
                   2675:        register pt_entry_t     *spte, *epte;
                   2676:        vm_offset_t             l;
                   2677: 
                   2678:        if (map == PMAP_NULL)
                   2679:                return;
                   2680: 
                   2681:        PMAP_READ_LOCK(map, spl);
                   2682: 
                   2683:        pde = pmap_pde(map, s);
                   2684:        while (s && s < e) {
                   2685:            l = (s + PDE_MAPPED_SIZE) & ~(PDE_MAPPED_SIZE-1);
                   2686:            if (l > e)
                   2687:                l = e;
                   2688:            if (*pde & INTEL_PTE_VALID) {
                   2689:                spte = (pt_entry_t *)ptetokv(*pde);
                   2690:                if (l) {
                   2691:                   spte = &spte[ptenum(s)];
                   2692:                   epte = &spte[intel_btop(l-s)];
                   2693:                } else {
                   2694:                   epte = &spte[intel_btop(PDE_MAPPED_SIZE)];
                   2695:                   spte = &spte[ptenum(s)];
                   2696:                }
                   2697:                while (spte < epte) {
                   2698:                    if (*spte & INTEL_PTE_VALID) {
                   2699:                        *spte |= (INTEL_PTE_MOD | INTEL_PTE_WRITE);
                   2700:                    }
                   2701:                    spte++;
                   2702:                }
                   2703:            }
                   2704:            s = l;
                   2705:            pde++;
                   2706:        }
                   2707:        PMAP_FLUSH_TLBS();
                   2708:        PMAP_READ_UNLOCK(map, spl);
                   2709: }
                   2710: 
                   2711: 
                   2712: #if    NCPUS > 1
                   2713: 
                   2714: void inline
                   2715: pmap_wait_for_clear()
                   2716: {
                   2717:        register int            my_cpu;
                   2718:        spl_t                   s;
                   2719:        register pmap_t         my_pmap;
                   2720: 
                   2721:        mp_disable_preemption();
                   2722:        my_cpu = cpu_number();
                   2723:        
                   2724: 
                   2725:        my_pmap = real_pmap[my_cpu];
                   2726: 
                   2727:        if (!(my_pmap && pmap_in_use(my_pmap, my_cpu)))
                   2728:                my_pmap = kernel_pmap;
                   2729: 
                   2730:        /*
                   2731:         *      Raise spl to splhigh (above splip) to block out pmap_extract
                   2732:         *      from IO code (which would put this cpu back in the active
                   2733:         *      set).
                   2734:         */
                   2735:        s = splhigh();
                   2736: 
                   2737:        /*
                   2738:         *      Wait for any pmap updates in progress, on either user
                   2739:         *      or kernel pmap.
                   2740:         */
                   2741:         while (*(volatile hw_lock_t)&my_pmap->lock.interlock ||
                   2742:          *(volatile hw_lock_t)&kernel_pmap->lock.interlock) {
                   2743:                continue;
                   2744:        }
                   2745: 
                   2746:        splx(s);
                   2747:        mp_enable_preemption();
                   2748: }
                   2749: 
                   2750: void
                   2751: pmap_flush_tlb_interrupt(void) {
                   2752:        pmap_wait_for_clear();
                   2753: 
                   2754:        flush_tlb();
                   2755: }
                   2756: 
                   2757: void
                   2758: pmap_reload_tlb_interrupt(void) {
                   2759:        pmap_wait_for_clear();
                   2760: 
                   2761:        set_cr3(kernel_pmap->pdirbase);
                   2762: }
                   2763: 
                   2764:        
                   2765: #endif /* NCPUS > 1 */
                   2766: 
                   2767: #if    MACH_KDB
                   2768: 
                   2769: /* show phys page mappings and attributes */
                   2770: 
                   2771: extern void    db_show_page(vm_offset_t pa);
                   2772: 
                   2773: void
                   2774: db_show_page(vm_offset_t pa)
                   2775: {
                   2776:        pv_entry_t      pv_h;
                   2777:        int             pai;
                   2778:        char            attr;
                   2779:        
                   2780:        pai = pa_index(pa);
                   2781:        pv_h = pai_to_pvh(pai);
                   2782: 
                   2783:        attr = pmap_phys_attributes[pai];
                   2784:        printf("phys page %x ", pa);
                   2785:        if (attr & PHYS_MODIFIED)
                   2786:                printf("modified, ");
                   2787:        if (attr & PHYS_REFERENCED)
                   2788:                printf("referenced, ");
                   2789:        if (pv_h->pmap || pv_h->next)
                   2790:                printf(" mapped at\n");
                   2791:        else
                   2792:                printf(" not mapped\n");
                   2793:        for (; pv_h; pv_h = pv_h->next)
                   2794:                if (pv_h->pmap)
                   2795:                        printf("%x in pmap %x\n", pv_h->va, pv_h->pmap);
                   2796: }
                   2797: 
                   2798: #endif /* MACH_KDB */
                   2799: 
                   2800: #if    MACH_KDB
                   2801: void db_kvtophys(vm_offset_t);
                   2802: void db_show_vaddrs(pt_entry_t  *);
                   2803: 
                   2804: /*
                   2805:  *     print out the results of kvtophys(arg)
                   2806:  */
                   2807: void
                   2808: db_kvtophys(
                   2809:        vm_offset_t     vaddr)
                   2810: {
                   2811:        db_printf("0x%x", kvtophys(vaddr));
                   2812: }
                   2813: 
                   2814: /*
                   2815:  *     Walk the pages tables.
                   2816:  */
                   2817: void
                   2818: db_show_vaddrs(
                   2819:        pt_entry_t      *dirbase)
                   2820: {
                   2821:        pt_entry_t      *ptep, *pdep, tmp;
                   2822:        int             x, y, pdecnt, ptecnt;
                   2823: 
                   2824:        if (dirbase == 0) {
                   2825:                dirbase = kernel_pmap->dirbase;
                   2826:        }
                   2827:        if (dirbase == 0) {
                   2828:                db_printf("need a dirbase...\n");
                   2829:                return;
                   2830:        }
                   2831:        dirbase = (pt_entry_t *) ((unsigned long) dirbase & ~INTEL_OFFMASK);
                   2832: 
                   2833:        db_printf("dirbase: 0x%x\n", dirbase);
                   2834: 
                   2835:        pdecnt = ptecnt = 0;
                   2836:        pdep = &dirbase[0];
                   2837:        for (y = 0; y < NPDES; y++, pdep++) {
                   2838:                if (((tmp = *pdep) & INTEL_PTE_VALID) == 0) {
                   2839:                        continue;
                   2840:                }
                   2841:                pdecnt++;
                   2842:                ptep = (pt_entry_t *) ((*pdep) & ~INTEL_OFFMASK);
                   2843:                db_printf("dir[%4d]: 0x%x\n", y, *pdep);
                   2844:                for (x = 0; x < NPTES; x++, ptep++) {
                   2845:                        if (((tmp = *ptep) & INTEL_PTE_VALID) == 0) {
                   2846:                                continue;
                   2847:                        }
                   2848:                        ptecnt++;
                   2849:                        db_printf("   tab[%4d]: 0x%x, va=0x%x, pa=0x%x\n",
                   2850:                                x,
                   2851:                                *ptep,
                   2852:                                (y << 22) | (x << 12),
                   2853:                                *ptep & ~INTEL_OFFMASK);
                   2854:                }
                   2855:        }
                   2856: 
                   2857:        db_printf("total: %d tables, %d page table entries.\n", pdecnt, ptecnt);
                   2858: 
                   2859: }
                   2860: #endif /* MACH_KDB */
                   2861: 
                   2862: #include <mach_vm_debug.h>
                   2863: #if    MACH_VM_DEBUG
                   2864: #include <vm/vm_debug.h>
                   2865: 
                   2866: int
                   2867: pmap_list_resident_pages(
                   2868:        register pmap_t         pmap,
                   2869:        register vm_offset_t    *listp,
                   2870:        register int            space)
                   2871: {
                   2872:        return 0;
                   2873: }
                   2874: #endif /* MACH_VM_DEBUG */
                   2875: 
                   2876: #ifdef MACH_BSD
                   2877: /*
                   2878:  * pmap_pagemove
                   2879:  *
                   2880:  * BSD support routine to reassign virtual addresses.
                   2881:  */
                   2882: 
                   2883: void
                   2884: pmap_movepage(unsigned long from, unsigned long to, vm_size_t size)
                   2885: {
                   2886:        spl_t   spl;
                   2887:        pt_entry_t      *pte, saved_pte;
                   2888:        /* Lock the kernel map */
                   2889: 
                   2890: 
                   2891:        while (size > 0) {
                   2892:                PMAP_READ_LOCK(kernel_pmap, spl);
                   2893:                pte = pmap_pte(kernel_pmap, from);
                   2894:                if (pte == NULL)
                   2895:                        panic("pmap_pagemove from pte NULL");
                   2896:                saved_pte = *pte;
                   2897:                PMAP_READ_UNLOCK(kernel_pmap, spl);
                   2898: 
                   2899:                pmap_enter(kernel_pmap, to, i386_trunc_page(*pte),
                   2900:                        VM_PROT_READ|VM_PROT_WRITE, *pte & INTEL_PTE_WIRED);
                   2901: 
                   2902:                pmap_remove(kernel_pmap, from, from+PAGE_SIZE);
                   2903: 
                   2904:                PMAP_READ_LOCK(kernel_pmap, spl);
                   2905:                pte = pmap_pte(kernel_pmap, to);
                   2906:                if (pte == NULL)
                   2907:                        panic("pmap_pagemove 'to' pte NULL");
                   2908: 
                   2909:                *pte = saved_pte;
                   2910:                PMAP_READ_UNLOCK(kernel_pmap, spl);
                   2911: 
                   2912:                from += PAGE_SIZE;
                   2913:                to += PAGE_SIZE;
                   2914:                size -= PAGE_SIZE;
                   2915:        }
                   2916: 
                   2917:        /* Get the processors to update the TLBs */
                   2918:        PMAP_FLUSH_TLBS();
                   2919: 
                   2920: }
                   2921: #endif
                   2922: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.