Annotation of Gnu-Mach/i386/intel/pmap.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

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