Annotation of OSKit-Mach/i386/intel/pmap.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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