home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / machsun3.tz / machsun3 / mk.kernel / sun3 / pmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  63.4 KB  |  2,898 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1992 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  Software.Distribution@CS.CMU.EDU
  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.  * HISTORY
  28.  * $Log:    pmap.c,v $
  29.  * Revision 2.15  92/01/14  16:47:13  rpd
  30.  *     Removed pmap_list_resident_pages.
  31.  *     [91/12/31            rpd]
  32.  * 
  33.  * Revision 2.14  91/07/31  18:14:03  dbg
  34.  *     pmap_activate and pmap_deactivate are unnecessary.
  35.  *     [91/07/15            dbg]
  36.  * 
  37.  * Revision 2.13  91/06/19  11:59:23  rvb
  38.  *     cputypes.h->platforms.h
  39.  *     [91/06/12  13:46:46  rvb]
  40.  * 
  41.  * Revision 2.12  91/05/18  14:38:04  rpd
  42.  *     Replaced pmap_valid_page with pmap_free_pages, pmap_next_page,
  43.  *     and pmap_virtual_space.  Changed the arguments to pmap_init.
  44.  *     [91/05/15            rpd]
  45.  * 
  46.  *     Removed pmap_update.
  47.  *     Added vm_page_fictitious_addr assertions.
  48.  *     [91/04/12            rpd]
  49.  * 
  50.  * Revision 2.11  91/03/16  14:59:06  rpd
  51.  *     bzero pmap after getting it from zalloc.
  52.  *     [91/03/15            rwd]
  53.  * 
  54.  *     Updated for new kmem_alloc interface.
  55.  *     [91/03/03            rpd]
  56.  * 
  57.  * Revision 2.10  90/10/25  14:47:38  rwd
  58.  *     Change asm instructions to Debugger().
  59.  *     [90/10/17            rwd]
  60.  *     Added hardware_reference_bits runtime switch.
  61.  *     [90/10/13            rpd]
  62.  * 
  63.  * Revision 2.9  90/08/06  15:07:57  rwd
  64.  *     Pmap_protect bug fixes from rpd.
  65.  *     [90/08/03            rwd]
  66.  * 
  67.  * Revision 2.8  90/06/02  15:07:01  rpd
  68.  *     Added dummy pmap_list_resident_pages, under MACH_VM_DEBUG.
  69.  *     [90/05/31            rpd]
  70.  * 
  71.  *     Removed references to kernel_vm_space.
  72.  *     [90/04/29            rpd]
  73.  * 
  74.  * Revision 2.7  90/03/14  21:11:35  rwd
  75.  *     Remove page_copy,data_copy since the new bcopy is faster.
  76.  *     [90/02/08            rwd]
  77.  * 
  78.  * Revision 2.6  90/02/22  20:04:42  dbg
  79.  *     Remove pmap_set_modify.  Make pmap_protect do a pmap_remove if
  80.  *     protection is VM_PROT_NONE.
  81.  *     [90/02/19            dbg]
  82.  * 
  83.  * Revision 2.5  90/01/19  14:35:00  rwd
  84.  *     Get changes from rfr.  pmap_set_modify.
  85.  *     [90/01/05            rwd]
  86.  * 
  87.  * Revision 2.4  89/09/08  11:27:25  dbg
  88.  *     Remove call to kallocinit; it is now in vm_mem_init.
  89.  *     [89/09/06            dbg]
  90.  * 
  91.  * Revision 2.3  89/08/31  16:19:20  rwd
  92.  *     Fixed include references
  93.  *     [89/08/15            rwd]
  94.  * 
  95.  * Revision 2.2  89/08/11  17:56:32  rwd
  96.  *     Picked up version from rfr.
  97.  *     [89/08/11            rwd]
  98.  * 
  99.  * Revision 2.9  89/04/23  13:23:13  gm0w
  100.  *     Fixed pmap_enter() not to panic if it is asked to map in
  101.  *     physical page 0 and added check for valid pme when checking
  102.  *     to see if mapping has been made already.  Fix from jjc.
  103.  *     [89/04/23            gm0w]
  104.  * 
  105.  * Revision 2.8  89/03/09  21:37:13  rpd
  106.  *     More cleanup.
  107.  * 
  108.  * Revision 2.7  89/02/25  19:46:31  gm0w
  109.  *     Added new copyright, fixed includes, and removed else leg
  110.  *     of CMU and MACH conditionals as part of kernel cleanup.
  111.  *     [89/02/10            jjc]
  112.  * 
  113.  * Revision 2.6  88/12/19  02:50:05  mwyoung
  114.  *     Remove lint.
  115.  *     [88/12/18            mwyoung]
  116.  *     
  117.  *     Added pmap_valid_page.
  118.  *     [88/12/13  03:35:17  mwyoung]
  119.  *     
  120.  *     Excised uses of PHYS_TO_VM_PAGE.
  121.  *     [88/12/09            mwyoung]
  122.  *     
  123.  *     Add pmap_verify_free().
  124.  *     [88/12/07  16:36:19  mwyoung]
  125.  * 
  126.  * Revision 2.5  88/11/21  16:58:03  rvb
  127.  *     Pme_zero will always allocate a pmeg if necessary, but only
  128.  *     "reserve" it if requested.
  129.  *     Also some what earlier we changed pme_to_epa to use 78 vs 7f8 to
  130.  *     mask just the high nibble vs the whole byte -- which was wrong.
  131.  *     [88/11/11            rvb]
  132.  * 
  133.  * 28-Apr-88  Robert Baron (rvb) at Carnegie-Mellon University
  134.  *    I forgot to do a Cache_Flush_Context before the segments are
  135.  *    invalidates in unload.
  136.  *
  137.  *  3-Feb-88  Robert Baron (rvb) at Carnegie-Mellon University
  138.  *    Created by dbg.   Finished and debugged by rvb:
  139.  *        1.    Added pmeg wired bit vector since there was no
  140.  *        room in the pme.
  141.  *        2.    Definition of epa (extended physical page address)
  142.  *        3.    pmeg cache in pmap -- loaded/unloaded during activate
  143.  *        4.    context wiring has gone away because of 3.
  144.  *    TODO:
  145.  *        a.    one context get/set around each routine
  146.  *        b.    have pv_list scanners use a dedicated seg va to
  147.  *        map cached pmegs thru
  148.  */
  149.  
  150. /*
  151.  *    Rewrite sun3/pmap.c following vax protocols.
  152.  */
  153.  
  154. #include <cpus.h>
  155. #include <platforms.h>
  156.  
  157. #include <machine/machparam.h>
  158.  
  159. #include <mach/boolean.h>
  160. #include <kern/thread.h>
  161. #include <kern/zalloc.h>
  162.  
  163. #include <kern/lock.h>
  164. #include <kern/queue.h>
  165.  
  166. #include <vm/pmap.h>
  167. #include <vm/vm_map.h>
  168. #include <vm/vm_kern.h>
  169. #include <vm/vm_page.h>
  170. #include <mach/vm_param.h>
  171. #include <mach/vm_prot.h>
  172.  
  173. #include <sun3/cpu.h>
  174.  
  175.  
  176. #if    SUN3_260
  177. #define SUN_VAC 1
  178. #define Cache_Flush_Context(c)    if (vac) cache_flush_context(c)
  179. #define Cache_Flush_Seg(c, v)    if (vac) cache_flush_seg(c, v)
  180. #define Cache_Flush_Page(c, v)    if (vac) cache_flush_page(c, v)
  181. #define Cache_Flush_Range(c, s, e, t)    \
  182.         if (vac) { \
  183.             if (s == trunc_pmeg(s) && \
  184.             e == trunc_pmeg(e)) { \
  185.             cache_flush_seg(c, s); \
  186.             } \
  187.             else for (t = s; t < e; t += NBPG) { \
  188.             cache_flush_page(c, t); \
  189.             } \
  190.         }
  191. #define Vac_Physflush(p, s) vac_physflush(p, s)
  192. #else    SUN3_260
  193. #define Cache_Flush_Context(c)
  194. #define Cache_Flush_Seg(c, v)
  195. #define Cache_Flush_Page(c, v)
  196. #define Cache_Flush_Range(c, s, e, t)
  197. #define Vac_Physflush(p, s)
  198. #endif    SUN3_260
  199.  
  200. #define queue_detach(e)        queue_init(e)
  201. #define queue_detached(e)    queue_empty(e)
  202.  
  203. /*
  204.  *    For each managed physical page, there is a list of all currently
  205.  *    valid virtual mappings of that page.  An entry is a pv_entry_t;
  206.  *    pv_head_table is the array of list headers.
  207.  */
  208.  
  209. typedef    struct pv_entry    {
  210.     struct pv_entry    *next;        /* next pv_entry */
  211.     pmap_t        pmap;        /* pmap where mapping lies */
  212.     vm_offset_t    va;        /* virtual address for mapping */
  213. } *pv_entry_t;
  214. #define PV_ENTRY_NULL    ((pv_entry_t)0)
  215.  
  216. pv_entry_t    pv_head_table;        /* array of entries, one per physical page */
  217. zone_t        pv_list_zone;        /* zone for more pv_entries */
  218.  
  219. /*
  220.  *    Index into pv_head_table and the phys_attribute table starting
  221.  *    at vm_first_phys.
  222.  *    N.B. you should make sure that the argument is really a pa and not an
  223.  *    epa, before you use pa_index. (see below)
  224.  */
  225. #define pa_index(pa)    (atop(pa - vm_first_phys))
  226. #define pai_to_pvh(pai)    (&pv_head_table[pai])
  227.  
  228. /*
  229.  *    Physical page attributes for managed pages.  Use same bit offset as high
  230.  *    order byte in pme.
  231.  */
  232. #define PHYS_MODIFIED    0x01        /* page modified */
  233. #define PHYS_REFERENCED    0x02        /* page referenced */
  234. #define PHYS_NOCACHE    0x10        /* page cannot be cached */
  235. #define PHYS_NOMATCH    0x20        /* mappings don't match for va-cache */
  236.  
  237. char    *phys_attributes;        /* attribute list for mapped pages */
  238.  
  239. /*
  240.  *    First and last physical addresses that we maintain any information
  241.  *    for.  Initialized to zero so that pmap operations done before
  242.  *    pmap_init won't touch any non-existent structures.
  243.  */
  244. vm_offset_t    vm_first_phys = (vm_offset_t) 0;
  245. vm_offset_t    vm_last_phys  = (vm_offset_t) 0;
  246. /*
  247.  *    SUN's physical address space is 34 bits; the two extra are type bits.
  248.  *     BUT since sun does not even need 32 bits of physical address for each
  249.  *    type, we will incorporate the 2 type bits into the top nibble.  We call
  250.  *    these extended physical addresses, epa's.
  251.  */
  252.  
  253. /*
  254.  *    'x' must have EPA_NC off
  255.  */
  256. #define managed_epa(x)    ( (!(x & EPA_TYPE)) && \
  257.               (x < vm_last_phys) && (x >= vm_first_phys))
  258.  
  259. /*
  260.  *    epa returned will never have EPA_NC on.
  261.  */
  262. #define pme_to_epa(pme)    ( (((pme & 0x7ffff) << PGSHIFT) & (~EPA_XTYPE)) | \
  263.               ((pme & 0x78000) ? EPA_F : 0) | \
  264.               ((pme & PG_TYPE) << 2) )
  265. #define epa_equal(epa0, epa1) ((epa0&~EPA_F) == (epa1&~EPA_F))
  266.  
  267. /*
  268.  *    EPA_NC will be propagated to PG_NC
  269.  */
  270. #define epa_to_pme(pa)    ( pa & EPA_F ? \
  271.               ( ((pa | EPA_NBL)   >> PGSHIFT) & 0x7ffff) | ( (pa & EPA_XTYPE) >> 2) : \
  272.               ( ((pa &~EPA_XTYPE) >> PGSHIFT) & 0x7ffff) | ( (pa & EPA_XTYPE) >> 2))
  273.  
  274. #define inc_pme(pme) (pme+=1)
  275.  
  276. /*
  277.  *    pmegs are allocated one at a time
  278.  */
  279. struct    pmeg {
  280.     queue_chain_t    link;        /* link in active or free queues */
  281.     pmap_t        pmap;        /* pmap this page is allocated to */
  282.     vm_offset_t    va;        /* first virtual address mapped by
  283.                        this page */
  284.     short        use_count;    /* number of mappings in use */
  285.     short        cache_idx;    /* index in pmap's pmeg cache */
  286.     unsigned long    wired;        /* specific pages that are wired */
  287. };
  288.  
  289. typedef    struct pmeg    *pmeg_t;
  290. #define PMEG_NULL    ((pmeg_t)0)
  291. #define is_pmeg_wired(pmegp, v) (pmegp->wired & (1 << (( (v - pmegp->va) >> PGSHIFT) & 0xf)))
  292.  
  293. struct pmeg    pmeg_array[NPMEG];    /* one pmeg_t for each possible
  294.                        mapping page */
  295.  
  296. queue_head_t    pmeg_active_queue;    /* list of all active pme pages */
  297. queue_head_t    pmeg_free_queue;    /* list of all free pme pages */
  298.  
  299. int        pmeg_free_count;
  300. int        pmeg_active_count;
  301. int        pmeg_wired_count;
  302. int        pmeg_max_wired;
  303. int        pmeg_max_active;
  304.  
  305. #define seg_to_pmeg(seg)    (&pmeg_array[seg])
  306. #define pmeg_to_seg(pmeg)    (pmeg - pmeg_array)
  307.  
  308. #define pmeg_map_size    (NBSG)
  309. #define trunc_pmeg(v)    ((v) & ~(pmeg_map_size - 1))
  310. #define round_pmeg(v)    (trunc_pmeg((v) + pmeg_map_size - 1))
  311.  
  312. #if    0
  313. /*
  314.  *    Contexts are also allocated among the pmaps.
  315.  * temporarily in pmap.h so genassym.c can define ctx->num.
  316.  * someday this field will be in pmap also and used from there.
  317.  */
  318. struct    context {
  319.     queue_chain_t    link;        /* link in active or free queues */
  320.     pmap_t        pmap;        /* pmap this context is allocated to */
  321.     int        num;        /* context number for hardware */
  322. };
  323. #endif    0
  324. typedef    struct context    *context_t;
  325. #define CONTEXT_NULL    ((context_t)0)
  326.  
  327. struct context    context_array[NCONTEXT];/* one for each context */
  328.  
  329.  
  330. queue_head_t    context_active_queue;    /* list of all active contexts */
  331. queue_head_t    context_free_queue;    /* list of all free contexts */
  332.  
  333. int        context_free_count;
  334. int        context_active_count;
  335.  
  336. /*
  337.  *    Locking and TLB invalidation
  338.  *
  339.  *    We only support a one-processor SUN at the moment, but all
  340.  *    of the macros are defined so they can be used in the right places.
  341.  */
  342. #if    NCPUS > 1
  343.     OOPS...
  344. #else    NCPUS > 1
  345.  
  346. lock_data_t    pmap_system_lock;
  347.  
  348. #define SPLVM(spl)    { spl = splvm(); }
  349. #define SPLX(spl)    { splx(spl); }
  350.  
  351. #define PMAP_READ_LOCK(pmap, spl)    SPLVM(spl)
  352. #define PMAP_WRITE_LOCK(spl)        SPLVM(spl)
  353. #define PMAP_READ_UNLOCK(pmap, spl)    SPLX(spl)
  354. #define PMAP_WRITE_UNLOCK(spl)        SPLX(spl)
  355. #define PMAP_WRITE_TO_READ_LOCK(pmap)
  356.  
  357. #define LOCK_PVH(index)
  358. #define UNLOCK_PVH(index)
  359.  
  360. #endif    NCPUS > 1
  361.  
  362. void    pmap_remove_range();    /* forward */
  363. void    context_allocate();
  364. void    context_free();
  365.  
  366. /*
  367.  *    Kernel pmap
  368.  */
  369. struct pmap    kernel_pmap_store;    /* structure */
  370. pmap_t        kernel_pmap;        /* pointer to it */
  371.  
  372. int    pmes_per_vm_page;        /* number of hardware pages per MACH VM page */
  373. int    vac = 0;            /* SUN_VAC virtual address cache */
  374.  
  375. boolean_t    pmap_initialized = FALSE;/* Has pmap_init finished? */
  376.  
  377.     /* make sure we are not doing really bad things. use when hardware is going catatonic */
  378. #define PARANOIA    0
  379.  
  380.     /* time consuming checks */
  381. #define CHECK        0
  382. #if    CHECK
  383. #define Use_Check(x)    use_check(x)
  384. #else    CHECK
  385. #define Use_Check(x)
  386. #endif    CHECK
  387.  
  388.     /* simple consistency checks */
  389. #define SAFE        1
  390. #if    SAFE
  391. #else    SAFE
  392. #endif    SAFE
  393.  
  394.     /* enable debugging printout on pmap_watch */
  395. #define WATCH        1
  396. #if    WATCH
  397. int        pmap_watch = 0;
  398. vm_offset_t    pmap_watch_va = (vm_offset_t) -1;
  399. vm_offset_t    pmap_watch_epa = (vm_offset_t) -1;
  400. #endif    WATCH
  401.  
  402. #define VM_FIRST_ADDRESS    0
  403. #define VM_LAST_ADDRESS        KERNELBASE
  404.  
  405. /*
  406.  *    Map memory at initialization.  The physical addresses being
  407.  *    mapped are not managed and are never unmapped.
  408.  *
  409.  *    For now, VM is already on, we only need to map the
  410.  *    specified memory.
  411.  */
  412. vm_offset_t pmap_map(virt, start, end, prot)
  413.     register vm_offset_t    virt;
  414.     register vm_offset_t    start;
  415.     register vm_offset_t    end;
  416.     register int        prot;
  417. {
  418.     register int        ps = PAGE_SIZE;
  419.  
  420.     while (start < end) {
  421.         pmap_enter(kernel_pmap, virt, start, prot, FALSE);
  422.         virt += ps;
  423.         start += ps;
  424.     }
  425.     return(virt);
  426. }
  427.  
  428. void    pmap_bootstrap()
  429. {
  430.     pmeg_t        pmegp;
  431.     context_t    context;
  432.     int        i;
  433.     int        vxx = (NSEGMAP - 2) * NBSG;    /* scratch */
  434.     vm_offset_t    v;
  435.  
  436.     pmes_per_vm_page = PAGE_SIZE / NBPG;
  437.  
  438.     lock_init(&pmap_system_lock, FALSE);
  439.  
  440.     kernel_pmap = &kernel_pmap_store;
  441.  
  442.     simple_lock_init(&kernel_pmap->lock);
  443.     kernel_pmap->ref_count = 1;
  444.         /* kernel gets the first context */
  445.     kernel_pmap->context = &context_array[0];
  446.     context_array[0].num = KCONTEXT;
  447.  
  448.     queue_init(&pmeg_free_queue);
  449.     queue_init(&pmeg_active_queue);
  450.  
  451.         /* pmegp is now SEGINV which belongs to the kernel */
  452.     pmeg_array[SEGINV].va = -1;        /* see pmeg_reserve */
  453.     for (i = 0, pmegp = &pmeg_array[0]; i < NPMEG ; i++, pmegp++) {
  454.         if (pmegp->va) { /* belongs to kernel via pmeg_reserve */
  455.         pmegp->pmap = PMAP_NULL;    /* permanent */
  456.         pmegp->use_count = 2*NPAGSEG;    /* all mappings in use */
  457.         pmeg_wired_count++;
  458.         queue_detach( (queue_t) pmegp);
  459.     } else {
  460.         setsgmap(vxx, i);
  461.         for (v = vxx; v < vxx+NBSG; v += NBPG)
  462.             setpgmap(v, 0);
  463.         pmegp->va = 0;
  464.         pmegp->cache_idx = 0;
  465.         pmegp->use_count = 0;
  466.         enqueue_tail(&pmeg_free_queue, (queue_entry_t) pmegp);
  467.         pmeg_free_count++;
  468.         }
  469.     }
  470.     pmeg_max_wired = pmeg_wired_count;
  471.  
  472.     queue_init(&context_free_queue);
  473.     queue_init(&context_active_queue);
  474.     context = &context_array[0];
  475.     for (i = 0; i < NCONTEXT; i++, context++) {
  476.         context->num = i;
  477.         if (i == KCONTEXT) {
  478.         queue_detach( (queue_t) context);
  479.         continue;
  480.         }
  481.         enqueue_tail(&context_free_queue, (queue_entry_t) context);
  482.     }
  483.     context_free_count = NCONTEXT - 1;
  484. }
  485.  
  486. extern    vm_offset_t    virtual_avail, virtual_end;
  487. extern    vm_offset_t    avail_start, avail_end;
  488. extern vm_offset_t    hole_start, hole_end;
  489. extern vm_offset_t    avail_next;
  490. extern unsigned int    avail_remaining;
  491.  
  492. unsigned int pmap_free_pages()
  493. {
  494.     return avail_remaining;
  495. }
  496.  
  497. boolean_t pmap_next_page(addrp)
  498.     vm_offset_t *addrp;
  499. {
  500.     if (avail_next == avail_end)
  501.         return FALSE;
  502.  
  503.     /* skip the hole */
  504.  
  505.     if (avail_next == hole_start)
  506.         avail_next = hole_end;
  507.  
  508.     *addrp = avail_next;
  509.     avail_next += PAGE_SIZE;
  510.     avail_remaining--;
  511.     return TRUE;
  512. }
  513.  
  514. void pmap_virtual_space(startp, endp)
  515.     vm_offset_t *startp;
  516.     vm_offset_t *endp;
  517. {
  518.     *startp = virtual_avail;
  519.     *endp = virtual_end;
  520. }
  521.  
  522. void    pmap_init()
  523. {
  524.     int        npages;
  525.     int        s;
  526.     vm_offset_t    addr;
  527.  
  528.     /*
  529.      *    Allocate and clear memory for the pv_head_table and the
  530.      *    phys_attribute list.
  531.      */
  532.     npages = atop(mem_size);
  533.     s = (vm_size_t)(sizeof(struct pv_entry) * npages
  534.             + npages);
  535.     s = round_page(s);
  536.     (void) kmem_alloc_wired(kernel_map, &addr, s);
  537.     blkclr((caddr_t) addr, s);
  538.  
  539.     pv_head_table = (pv_entry_t)addr;
  540.     phys_attributes = (char *) addr + (npages * sizeof(struct pv_entry));
  541.  
  542.     vm_first_phys = avail_start;
  543.     vm_last_phys = avail_end;
  544.  
  545.     /*
  546.      *    Create the zone of physical maps,
  547.      *    and of the physical-to-virtual entries.
  548.      */
  549.     s = (vm_size_t) sizeof(struct pmap);
  550.     pmap_zone = zinit(s, 400*s, 4096, FALSE, "pmap"); /* XXX */
  551.     s = (vm_size_t) sizeof(struct pv_entry);
  552.     pv_list_zone = zinit(s, 10000*s, 4096, FALSE, "pv_list"); /* XXX */
  553.  
  554.     printf("SPACE FREE:   ToTaL    = %x[%d]\n",
  555.         atop(avail_end), atop(avail_end));
  556.     printf("SPACE FREE: after load = %x[%d]\n",
  557.         atop(avail_end - avail_start), atop(avail_end - avail_start));
  558.     printf("SPACE FREE:  pmap_init = %x[%d]\n",
  559.         vm_page_free_count, vm_page_free_count);
  560.  
  561.     pmap_initialized = TRUE;
  562. }
  563.  
  564.  
  565. /*
  566.  *    Does a page table entry actually exist?
  567.  */
  568. #define pmeg_valid(pmap, va)    (getsegmap(pmap->context->num, va) != SEGINV)
  569.  
  570. pmeg_t    get_pmeg(pmap, va)
  571.     pmap_t        pmap;
  572.     vm_offset_t    va;
  573. {
  574.     int seg;
  575.     seg = getsegmap(pmap->context->num, va);
  576.     if (seg == SEGINV)
  577.         return(PMEG_NULL);
  578.     return (seg_to_pmeg(seg));
  579. }
  580.  
  581. /*
  582.  *    Reserve named pme group for kernel.
  583.  */
  584. void    pmeg_reserve(v)
  585.     vm_offset_t v;
  586. {
  587.     int            seg = getsgmap(v);
  588.     register pmeg_t        pmegp;
  589.  
  590. #if    SAFE
  591.     if ((int) kernel_pmap)
  592.         panic("pmeg_reserve: too late.");
  593.     if (seg == SEGINV)
  594.         panic ("can not reserve SEGINV");
  595. #endif    SAFE
  596.     pmegp = seg_to_pmeg(seg);
  597.  
  598. #if    SAFE
  599.     if (pmegp->va != ((vm_offset_t) 0))
  600.         panic("pmeg_reserve: already reserved");
  601. #endif    SAFE
  602.     pmegp->va = v;            /* implies reserved by kernel */
  603. }
  604.  
  605. /*
  606.  *    Allocate a pme page from the free list.
  607.  */
  608. pmeg_t    free_pmeg_alloc(pmap, va)
  609.     pmap_t        pmap;
  610.     vm_offset_t    va;
  611. {
  612.     pmeg_t        pmegp;
  613.     int        i;
  614.  
  615.     if (queue_empty(&pmeg_free_queue)) {
  616.         return (PMEG_NULL);
  617.     }
  618.  
  619.     pmegp = (pmeg_t) dequeue_head(&pmeg_free_queue);
  620.     pmeg_free_count--;
  621. #if    SAFE
  622.     if (pmegp->pmap != PMAP_NULL || pmegp->va != (vm_offset_t)0){
  623.         printf("pmeg in use = %x[#%x], va = %x\n",
  624.             pmegp, pmegp-pmeg_array, pmegp->va);
  625.         panic("free_pmegp_alloc");
  626.     }
  627. #endif    SAFE
  628.  
  629.     va = trunc_pmeg(va);
  630.  
  631.     pmegp->pmap = pmap;
  632.     pmegp->va   = va;
  633.  
  634.     if (pmap == kernel_pmap) {
  635.         /*
  636.          *    Pme groups in kernel pmap are mapped into all
  637.          *    contexts, and are wired.
  638.          */
  639.         for (i = 0; i < NCONTEXT; i++)
  640.         setsegmap(i, va, pmeg_to_seg(pmegp));
  641.         pmeg_wired_count++;
  642.         queue_detach( (queue_t) pmegp);
  643.     }
  644.     else {
  645.         register int idx;
  646.  
  647.         idx = pmap->cache_idx++;
  648.         pmap_cache_validate(pmap);
  649.  
  650.         pmap->cache_ptr->cache[idx] = (int) va | pmeg_to_seg(pmegp);
  651.         pmegp->cache_idx = idx;
  652.         setsegmap(pmap->context->num, va, pmeg_to_seg(pmegp));
  653.         enqueue_tail(&pmeg_active_queue, (queue_entry_t) pmegp);
  654.         pmeg_active_count++;
  655.         if (pmeg_active_count > pmeg_max_active)
  656.         pmeg_max_active = pmeg_active_count;
  657.     }
  658.  
  659.     return(pmegp);
  660. }
  661.  
  662. /*
  663.  *    Allocate a pme page, possibly recycling one from another pmap.
  664.  */
  665. pmeg_t    pmeg_alloc(pmap, va)
  666.     pmap_t        pmap;
  667.     vm_offset_t    va;
  668. {
  669.     pmeg_t    pmegp;
  670.  
  671.     if (queue_empty(&pmeg_free_queue)) {
  672.         pmap_t        old_pmap;
  673.         vm_offset_t        old_va;
  674.  
  675.         /*
  676.          *    No free pme pages.  recycle one.
  677.          */
  678.         pmegp = (pmeg_t) queue_first(&pmeg_active_queue);
  679.         if (pmegp == PMEG_NULL) {
  680.         panic("not enough pme pages");
  681.         }
  682.         /*
  683.          *    Free the pme page.
  684.          */
  685. #if    SAFE
  686.         if (pmegp->pmap == PMAP_NULL)
  687.         panic("pmeg_alloc: freeing permanent pmeg");
  688. #endif    SAFE
  689.         old_pmap = pmegp->pmap;
  690.         old_va = pmegp->va;
  691.         if (old_pmap->context == CONTEXT_NULL)
  692.         context_allocate(old_pmap);
  693.         simple_lock(&old_pmap->lock);
  694.         Cache_Flush_Seg(old_pmap->context->num, old_va);
  695.         pmap_remove_range(old_pmap,
  696.                       old_va,
  697.                   old_va + pmeg_map_size,
  698.                   TRUE);
  699.         simple_unlock(&old_pmap->lock);
  700.  
  701.         /*
  702.          *    Should put the pme page at the head of the free queue.
  703.          */
  704.     }
  705.     return (free_pmeg_alloc(pmap, va));
  706. }
  707.  
  708. /*
  709.  *    Free a pme page.
  710.  */
  711. void    pmeg_free(pmegp)
  712.     pmeg_t        pmegp;
  713. {
  714.     int        i;
  715.  
  716. #if    SAFE
  717.     if (pmegp->pmap == PMAP_NULL)
  718.         panic("pmeg_free: freeing permanent pmeg");
  719.  
  720.     if (pmegp->wired) {
  721.         printf("wired = %x, pmeg = %x[#%x]\n",
  722.             pmegp->wired, pmegp, pmegp-pmeg_array);
  723.         panic("pmeg_free");
  724.     }
  725. #endif    SAFE
  726. #if    PARANOIA
  727.         /* pmeg's freed should be empty */
  728.     {
  729.         vm_offset_t    v;
  730.         int        pme;
  731.         for (i = 0, v = pmegp->va; i < NPAGSEG; i++, v += NBPG) {
  732.             if (pme = getpagemap(pmegp->pmap->context->num, v)) {
  733.                 printf("pme = %x, pmeg = %x[#%x], va = %x\n",
  734.                     pme, pmegp, pmegp-pmeg_array, v);
  735.                 panic("pmeg_free");
  736.             }
  737.         }
  738.     }
  739. #endif    PARANOIA
  740.     if (pmegp->pmap == kernel_pmap) {
  741.         /*
  742.          *    Must remove kernel pme group from all contexts.
  743.          */
  744.         for (i = 0; i < NCONTEXT; i++)
  745.         setsegmap(i, pmegp->va, SEGINV);
  746.         pmeg_wired_count--;
  747.     }
  748.     else {
  749.         register int idx; 
  750.         register int pi;
  751.         pmap_t    pmap = pmegp->pmap;
  752.  
  753.         pmap_cache_validate(pmap);
  754.         idx = --(pmap->cache_idx);
  755.         pi  = pmegp->cache_idx;
  756.  
  757.         
  758.         /*
  759.          * Debugging check to be removed at a later date. -rfr
  760.          */
  761.         if (pi > pmap->cache_idx) printf("Increasing pmap size!\n");
  762.  
  763.         if (idx != pi) {
  764. #define cache_to_seg(x) (x&0xff)
  765. #define cache_to_va(x) ((vm_offset_t) (x&~0xff))
  766.         pmap->cache_ptr->cache[pi] = pmap->cache_ptr->cache[idx];
  767.         seg_to_pmeg(cache_to_seg(pmap->cache_ptr->cache[idx]))->cache_idx = pi;
  768.         }
  769.         pmap->cache_ptr->cache[idx] = 0;
  770.         pmegp->cache_idx = 0;
  771.  
  772.         setsegmap(pmegp->pmap->context->num, pmegp->va, SEGINV);
  773.  
  774. #if    PARANOIA
  775.         if (queue_detached( (queue_t) pmegp)) {
  776.         printf("freeing wired pmeg %x[#%x]\n",
  777.             pmegp, pmegp-pmeg_array);
  778.         panic("pmeg_free");
  779.         }
  780.         /* pmeg's should be on the active q,
  781.            if they are to be removed from it */
  782.         if (pmeg_remq_ck(&pmeg_active_queue, "pmeg_active_queue", pmegp))
  783. #endif    PARANOIA
  784.         remqueue(&pmeg_active_queue, (queue_entry_t) pmegp);
  785.         pmeg_active_count--;
  786.     }
  787.  
  788.     pmegp->pmap = PMAP_NULL;
  789.     pmegp->va = (vm_offset_t) 0;
  790.     pmegp->use_count = 0;
  791.  
  792. #if    CHECK
  793.     pmeg_enq_ck(&pmeg_free_queue, "pmeg_free_queue", pmegp);
  794. #endif    CHECK
  795.     enqueue_head(&pmeg_free_queue, (queue_entry_t) pmegp);
  796.     pmeg_free_count++;
  797. }
  798.  
  799. /*
  800.  *    Wire down a pme page, preventing it from being recycled.
  801.  */
  802. void    pmeg_wire(pmegp, va)
  803.     pmeg_t    pmegp;
  804. {
  805.     register int    page = ( (va - pmegp->va) >> PGSHIFT) & 0xf;
  806.  
  807. #if    SAFE
  808.     if (pmegp->pmap == PMAP_NULL)
  809.         panic("pmeg_wire: wiring permanent pmeg");
  810. #endif    SAFE
  811.  
  812.     if (pmegp->pmap != kernel_pmap && !pmegp->wired) {
  813.         remqueue(&pmeg_active_queue, (queue_entry_t) pmegp);
  814.         queue_detach( (queue_t) pmegp);
  815.         pmeg_active_count--;
  816.         pmeg_wired_count++;
  817.         if (pmeg_wired_count > pmeg_max_wired)
  818.             pmeg_max_wired = pmeg_wired_count;
  819.     }
  820.  
  821.     if (!(pmegp->wired & (1 << page))) {
  822.         pmegp->wired |= 1 << page;
  823.     }
  824. }
  825.  
  826. /*
  827.  *    Unwire a pme page, allowing it to be recycled.
  828.  */
  829. void    pmeg_unwire(pmegp, va)
  830.     pmeg_t    pmegp;
  831. {
  832.     register int    page = ( (va - pmegp->va) >> PGSHIFT) & 0xf;
  833.  
  834. #if    SAFE
  835.     if (pmegp->pmap == PMAP_NULL)
  836.         panic("pmeg_unwire: unwiring permanent pmeg");
  837. #endif    SAFE
  838.     if (pmegp->wired & (1 << page)) {
  839.         pmegp->wired &= ~(1 << page);
  840.  
  841.         if (pmegp->pmap != kernel_pmap && !pmegp->wired) {
  842. #if    SAFE
  843.             if (!queue_detached( (queue_t) pmegp)) {
  844.                 printf("pmeg not wired %x[#%x]\n",
  845.                     pmegp, pmegp-pmeg_array);
  846.                 panic("pmeg_unwire");
  847.             }
  848. #endif    SAFE
  849.  
  850.             enqueue_tail(&pmeg_active_queue, (queue_entry_t) pmegp);
  851.             pmeg_wired_count--;
  852.             pmeg_active_count++;
  853.         }
  854.     } else {
  855.         panic("pmeg_unwire: not wired");
  856.     }
  857. }
  858.  
  859. /*
  860.  *    Allocate a context for the specified pmap.  May grab one from
  861.  *    another pmap.
  862.  */
  863. void    context_allocate(pmap)
  864.     pmap_t        pmap;
  865. {
  866.     context_t context;
  867.  
  868.     if (queue_empty(&context_free_queue)) {
  869.         /*
  870.          *    No free contexts - recycle one.
  871.          */
  872.  
  873.         context = (context_t) queue_first(&context_active_queue);
  874.         if (context == CONTEXT_NULL)
  875.         panic("no active contexts");
  876.         context_free(context->pmap);
  877.     }
  878.  
  879.     context = (context_t)dequeue_head(&context_free_queue);
  880.     context_free_count--;
  881.  
  882. #if    SAFE
  883.     if (context->pmap != PMAP_NULL) {
  884.         panic("context in use");
  885.     }
  886. #endif    SAFE
  887.  
  888.     context->pmap = pmap;
  889.     pmap->context = context;
  890.     context_load(pmap);
  891.  
  892.     enqueue_tail(&context_active_queue, (queue_entry_t)context);
  893.     context_active_count++;
  894. }
  895.  
  896. /*
  897.  *    Free a context in use by a pmap.
  898.  */
  899. void    context_free(pmap)
  900.     pmap_t        pmap;
  901. {
  902.     context_t    context = pmap->context;
  903.  
  904.     if (context == CONTEXT_NULL)
  905.         return;
  906.     if (context->num == getcontext())
  907.         panic("context_free: freeing self");
  908.     context_unload(pmap);
  909.     pmap->context = CONTEXT_NULL;
  910.     context->pmap = PMAP_NULL;
  911.  
  912.     remqueue(&context_active_queue, (queue_entry_t) context);
  913.     context_active_count--;
  914.     enqueue_head(&context_free_queue, (queue_entry_t) context);
  915.     context_free_count++;
  916. }
  917.  
  918. context_load(pmap)
  919.     pmap_t        pmap;
  920. {
  921.     register int    i;
  922.     register int    *cp;
  923.     register int    cnum = pmap->context->num;
  924.     register int     idx;
  925.  
  926.     pmap_cache_validate(pmap);
  927.     idx = pmap->cache_idx;
  928.     cp = (int *)pmap->cache_ptr;
  929.  
  930.     for (i = 0; i < idx; i++, cp++) {
  931.         setsegmap(cnum, *cp, *cp);
  932.     }
  933. }
  934.  
  935.  
  936. context_unload(pmap)
  937.     pmap_t        pmap;
  938. {
  939.     register int     idx;
  940.     register int    i;
  941.     register int    *cp;
  942.     register int    cnum = pmap->context->num;
  943.  
  944.     pmap_cache_validate(pmap);
  945.  
  946.     idx = pmap->cache_idx;
  947.     cp  = (int *)pmap->cache_ptr;
  948.  
  949.     Cache_Flush_Context(cnum);
  950.     for (i = 0; i < idx; i++, cp++) {
  951.         setsegmap(cnum, *cp, SEGINV);
  952.     }
  953. }
  954.  
  955. cache_destroy(pmap)
  956.     pmap_t        pmap;
  957. {
  958.     register vm_offset_t    v;
  959.  
  960.     while (pmap->cache_idx > 0) {
  961.         v  = cache_to_va(pmap->cache_ptr->cache[0]);
  962.         pmap_remove_range(pmap, v, v + NBSG, TRUE);
  963.     }
  964.  
  965.     pmap_cache_invalidate(pmap);
  966. }
  967.  
  968. /*
  969.  *    Create and return a physical map.
  970.  *
  971.  *    If the size specified for the map
  972.  *    is zero, the map is an actual physical
  973.  *    map, and may be referenced by the
  974.  *    hardware.
  975.  *
  976.  *    If the size specified is non-zero,
  977.  *    the map will be used in software only, and
  978.  *    is bounded by that size.
  979.  */
  980. pmap_t    pmap_create(size)
  981.     vm_size_t    size;
  982. {
  983.     register pmap_t        pmap;
  984.  
  985.     if (size != 0) {
  986.         return(PMAP_NULL);
  987.     }
  988.  
  989.     pmap = (pmap_t) zalloc(pmap_zone);
  990.     if (pmap == PMAP_NULL) {
  991.         panic("pmap_create");
  992.     }
  993.  
  994.     bzero(pmap, sizeof *pmap);
  995.     simple_lock_init(&pmap->lock);
  996.     pmap->context = CONTEXT_NULL;
  997.     pmap_cache_validate(pmap);
  998.     pmap->cache_idx = 0;
  999.     pmap->ref_count = 1;
  1000.  
  1001.     pmap->stats.resident_count = 0;
  1002.     pmap->stats.wired_count = 0;
  1003.  
  1004.     return (pmap);
  1005. }
  1006.  
  1007. /*
  1008.  *    Retire the given physical map from service.
  1009.  *    Should only be called if the map contains
  1010.  *    no valid mappings.
  1011.  */
  1012. void    pmap_destroy(pmap)
  1013.     pmap_t    pmap;
  1014. {
  1015.     if (pmap != PMAP_NULL) {
  1016.         register int s;
  1017.  
  1018.         SPLVM(s);
  1019.         simple_lock(&pmap->lock);
  1020.         if (--pmap->ref_count > 0) {
  1021.         simple_unlock(&pmap->lock);
  1022.         SPLX(s);
  1023.         return;
  1024.         }
  1025.         SPLX(s);
  1026.  
  1027.         if (pmap->cache_idx) {
  1028.         printf("pmap_destroy: cache_idx pmap %x #%x\n", pmap, pmap->context->num);
  1029.         if (pmap->context == CONTEXT_NULL) {
  1030.             printf("pmap_destroy: no context but cached\n");
  1031.             context_allocate(pmap);
  1032.         }
  1033.         simple_lock(pmap->lock);
  1034.         Cache_Flush_Context(pmap->context->num);
  1035.         cache_destroy(pmap);
  1036.         simple_unlock(pmap->lock);
  1037.         }
  1038.         if (pmap->context != CONTEXT_NULL) {
  1039.         context_free(pmap);
  1040.         }
  1041.  
  1042. #if    SAFE
  1043.         if (pmap->cache_idx)
  1044.         panic("pmap_destroy: cache_idx");
  1045. #endif    SAFE
  1046.  
  1047.         pmap_cache_invalidate(pmap);
  1048.         zfree(pmap_zone, (vm_offset_t)pmap);
  1049.     }
  1050. }
  1051.  
  1052. /*
  1053.  *    Add a reference to the specified pmap.
  1054.  */
  1055. void    pmap_reference(pmap)
  1056.     pmap_t    pmap;
  1057. {
  1058.     if (pmap != PMAP_NULL) {
  1059.         int    s;
  1060.  
  1061.         SPLVM(s);
  1062.         simple_lock(&pmap->lock);
  1063.         pmap->ref_count++;
  1064.         simple_unlock(&pmap->lock);
  1065.         SPLX(s);
  1066.     }
  1067. }
  1068.  
  1069. /*
  1070.  *    Remove a range of mapping entries.
  1071.  *    The range must lie entirely within one pmeg (this is NOT checked).
  1072.  *
  1073.  *    The pmap must be locked, and have a context.
  1074.  */
  1075. void    pmap_remove_range(pmap, sva, eva, free_if_empty)
  1076.     pmap_t        pmap;
  1077.     vm_offset_t    sva, eva;
  1078.     boolean_t    free_if_empty;
  1079. {
  1080.     vm_offset_t    cva, lva;
  1081.     int        lpme, pme;
  1082.     vm_offset_t    epa;
  1083.     pv_entry_t    pv_h, cur, prev;
  1084.     int        pai, i;
  1085.     int        num_removed;
  1086.     pmeg_t        pmegp;
  1087.  
  1088.     if (pmap->context == CONTEXT_NULL)
  1089.         context_allocate(pmap);
  1090.  
  1091.     pmegp = get_pmeg(pmap, sva);
  1092. #if    WATCH
  1093.     if (pmap_watch) {
  1094.         printf("pmap_RANGE(pmap %x, va %x, eva %x, free_if_mt %x) #%x\n",
  1095.             pmap, sva, eva, free_if_empty, pmegp-pmeg_array);
  1096.     }
  1097. #endif    WATCH
  1098.     num_removed = 0;
  1099.     Use_Check(pmegp);
  1100.  
  1101.     for (cva = sva; cva < eva; cva += PAGE_SIZE) {
  1102.         pme = getpagemap(pmap->context->num, cva);
  1103.         if ((pme & PG_V) == 0)
  1104.         continue;
  1105.  
  1106. #if    WATCH
  1107.         if (pmap_watch_va != (vm_offset_t) -1 && cva == pmap_watch_va) {
  1108.         printf("va match\n");
  1109.         Debugger("Pmap");
  1110.         }
  1111. #endif    WATCH
  1112.         num_removed++;
  1113.         if (is_pmeg_wired(pmegp, cva)) {
  1114.             pmeg_unwire(pmegp, cva);
  1115.         pmap->stats.wired_count--;
  1116.         }
  1117.         epa = pme_to_epa(pme);
  1118. #if    WATCH
  1119.         if (pmap_watch_epa != (vm_offset_t) -1 && epa == pmap_watch_epa) {
  1120.         pr_pvlist(epa);
  1121.         printf("epa of cva match\n");
  1122.         Debugger("Pmap");
  1123.         }
  1124. #endif    WATCH
  1125.         if (!managed_epa(epa)) {
  1126.         /*
  1127.          *    Not managed memory.  Don`t remove from pv_list
  1128.          *    or collect modify bits; just clear the pmes.
  1129.          */
  1130.         i = pmes_per_vm_page;
  1131.         lva = cva;
  1132.         do {
  1133.             setpagemap(pmap->context->num, lva, 0);
  1134.             lva += NBPG;
  1135.         } while (--i > 0);
  1136.         continue;
  1137.         }
  1138.         /* so below epa is managed */
  1139.         pai = pa_index(epa);
  1140.         LOCK_PVH(pai);
  1141.  
  1142.         /*
  1143.          *    Get the modify bits.
  1144.          */
  1145.         i = pmes_per_vm_page;
  1146.         lva = cva;
  1147.         do {
  1148.         lpme = changepagemap(pmap->context->num, lva, 0, 0);
  1149.         phys_attributes[pai] |= pme_mr(lpme);
  1150.         lva += NBPG;
  1151.         } while (--i > 0);
  1152.  
  1153.         /*
  1154.          *    Remove mapping from the pvlist.
  1155.          */
  1156.         pv_h = pai_to_pvh(pai);
  1157.         if (pv_h->pmap == PMAP_NULL) {
  1158.         panic("pmap_remove_range: null pv_list!");
  1159.         }
  1160.         if (pv_h->va == cva && pv_h->pmap == pmap) {
  1161.         cur = pv_h->next;
  1162.         if (cur != PV_ENTRY_NULL) {
  1163.             *pv_h = *cur;
  1164.             zfree(pv_list_zone, (vm_offset_t) cur);
  1165.         }
  1166.         else {
  1167.             pv_h->pmap = PMAP_NULL;
  1168.             phys_attributes[pai] &= ~(PHYS_NOCACHE | PHYS_NOMATCH);
  1169.         }
  1170.         }
  1171.         else {
  1172.         prev = pv_h;
  1173.         while ((cur = prev->next) != PV_ENTRY_NULL) {
  1174.             if (cur->va == cva && cur->pmap == pmap)
  1175.             break;
  1176.             prev = cur;
  1177.         }
  1178.         if (cur == PV_ENTRY_NULL) {
  1179.             panic("pmap_remove_range: mapping not in pv_list!");
  1180.         }
  1181.         prev->next = cur->next;
  1182.         zfree(pv_list_zone, (vm_offset_t) cur);
  1183.         }
  1184.         UNLOCK_PVH(pai);
  1185.     }
  1186.  
  1187.     /*
  1188.      *    Update the counts.
  1189.      */
  1190.     pmap->stats.resident_count -= num_removed;
  1191.  
  1192.     /*
  1193.      *    See whether this pme page can be freed.
  1194.      */
  1195.     pmegp->use_count   -= num_removed;
  1196.     Use_Check(pmegp);
  1197.     if (pmegp->use_count == 0 && free_if_empty) {
  1198.         pmeg_free(pmegp);
  1199.     }
  1200. }
  1201.  
  1202. /*
  1203.  *    Remove the given range of addresses from the
  1204.  *    specified map.
  1205.  *
  1206.  *    It is assume that the start and end are properly rounded
  1207.  *    to the machine's page size.
  1208.  */
  1209.  
  1210. void    pmap_remove(pmap, s, e)
  1211.     pmap_t    pmap;
  1212. {
  1213.     int        spl;
  1214.     register vm_offset_t    l, c;
  1215.  
  1216.     if (pmap == PMAP_NULL)
  1217.         return;
  1218.  
  1219.     if (pmap->context == CONTEXT_NULL)
  1220.         context_allocate(pmap);
  1221.  
  1222.     PMAP_READ_LOCK(pmap, spl);
  1223.  
  1224.     if (pmap == kernel_pmap) {
  1225.         if (s < VM_MIN_KERNEL_ADDRESS)
  1226.         s = VM_MIN_KERNEL_ADDRESS;
  1227.         if (e > VM_MAX_KERNEL_ADDRESS)
  1228.         e = VM_MAX_KERNEL_ADDRESS;
  1229.     }
  1230.     else {
  1231.         if (e > VM_MAX_ADDRESS)
  1232.         e = VM_MAX_ADDRESS;
  1233.     }
  1234.  
  1235.     while (s < e) {
  1236.         l = round_pmeg(s + 1);
  1237.         if (l > e)
  1238.         l = e;
  1239.         if (pmeg_valid(pmap, s)) {
  1240.         Cache_Flush_Range(pmap->context->num, s, l, c);
  1241.         pmap_remove_range(pmap, s, l, TRUE);
  1242.         }
  1243.         s = l;
  1244.     }
  1245.  
  1246.     PMAP_READ_UNLOCK(pmap, spl);
  1247. }
  1248.  
  1249. /*
  1250.  *    Removes the specified physical page from all physical maps
  1251.  *    in which it resides.  Saves reference and modify bits.
  1252.  */
  1253. void    pmap_remove_all(epa)
  1254.     vm_offset_t    epa;
  1255. {
  1256.     pv_entry_t    pv_h, cur;
  1257.     int        pme;
  1258.     vm_offset_t    va, lva;
  1259.     pmap_t        pmap;
  1260.     register int    i;
  1261.     int        spl, pai;
  1262.     pmeg_t        pmegp;
  1263. #if    WATCH
  1264.     static int    last_vm;
  1265.  
  1266. #ifdef    lint
  1267.     if (last_vm++) return;
  1268. #endif    lint
  1269.  
  1270.     last_vm = -1;
  1271.  
  1272.     if (pmap_watch) {
  1273.         printf("pmap_ALL(epa %x)\n", epa);
  1274.     }
  1275. #endif    WATCH
  1276.  
  1277.     assert(epa != vm_page_fictitious_addr);
  1278.  
  1279.     epa &= ~EPA_NC;
  1280.     if (!managed_epa(epa)) {
  1281.         /*
  1282.          *    Not a managed page.
  1283.          */
  1284.         return;
  1285.     }
  1286. #if    WATCH
  1287.     if (pmap_watch_epa != (vm_offset_t) -1 && epa == pmap_watch_epa) {
  1288.         pr_pvlist(epa);
  1289.         printf("epa match\n");
  1290.         Debugger("Pmap");
  1291.     }
  1292. #endif    WATCH
  1293.     /*
  1294.      *    Lock the pmap system first, since we will be changing
  1295.      *    several pmaps.
  1296.      */
  1297.  
  1298.     PMAP_WRITE_LOCK(spl);
  1299.  
  1300.     /*
  1301.      *    Walk down PV list, removing all mappings.
  1302.      */
  1303.     pai = pa_index(epa);
  1304.     pv_h = pai_to_pvh(pai);
  1305.  
  1306.     while ((pmap = pv_h->pmap) != PMAP_NULL) {
  1307.         va = pv_h->va;
  1308. #if    WATCH
  1309.         last_vm = va;
  1310.         if (pmap_watch_va != (vm_offset_t) -1 && va == pmap_watch_va) {
  1311.         printf("va of epa match\n");
  1312.         Debugger("Pmap");
  1313.         }
  1314. #endif    WATCH
  1315.         if (pmap->context == CONTEXT_NULL)
  1316.         context_allocate(pmap);
  1317.  
  1318.         simple_lock(&pmap->lock);
  1319.         pme = getpagemap(pmap->context->num, va);
  1320. #if    SAFE
  1321.         if ((pme & PG_V) == 0) {
  1322.         panic("pmap_remove_all: pme in list but not in map");
  1323.         }
  1324.         if (! epa_equal(pme_to_epa(pme), epa)) {
  1325.         panic("pmap_remove_all: pme does not point to page");
  1326.         }
  1327. #endif    SAFE
  1328.         pmap->stats.resident_count--;
  1329.         pmegp = get_pmeg(pmap, va);
  1330.         Use_Check(pmegp);
  1331.         if (is_pmeg_wired(pmegp, va)) {
  1332.         printf("pmap_remove_all: removing a wired page\n");
  1333.         continue;
  1334.         }
  1335.         if ((cur = pv_h->next) != PV_ENTRY_NULL) {
  1336.         *pv_h = *cur;
  1337.         zfree(pv_list_zone, (vm_offset_t) cur);
  1338.         }
  1339.         else {
  1340.         pv_h->pmap = PMAP_NULL;
  1341.         }
  1342.         i = pmes_per_vm_page;
  1343.         lva = va;
  1344. #if    PARANOIA
  1345.         /* record va/epa/obj/data paged out */
  1346.         if (va > KERNELBASE)
  1347.             ppg_out(va, epa);
  1348. #endif    PARANOIA
  1349.         do {
  1350.         Cache_Flush_Page(pmap->context->num, lva);
  1351.         pme = changepagemap(pmap->context->num, lva, 0, 0);
  1352.         phys_attributes[pai] |= pme_mr(pme);
  1353.         lva += NBPG;
  1354.         } while (--i > 0);
  1355. #if    PARANOIA
  1356.         /* record va/epa/obj/data paged out */
  1357.         if (va > KERNELBASE)
  1358.             ppg_attr(va, epa);
  1359. #endif    PARANOIA
  1360.  
  1361.         if (--pmegp->use_count == 0) {
  1362.         pmeg_free(pmegp);
  1363.         }
  1364.         Use_Check(pmegp);
  1365.         simple_unlock(&pmap->lock);
  1366.     }
  1367.  
  1368.     phys_attributes[pai] &= ~(PHYS_NOCACHE | PHYS_NOMATCH);
  1369.     PMAP_WRITE_UNLOCK(spl);
  1370. }
  1371.  
  1372. pr_pvlist(epa)
  1373.     vm_offset_t    epa;
  1374. {
  1375.     pv_entry_t    pv_h;
  1376.     int        pme;
  1377.     vm_offset_t    va;
  1378.     pmap_t        pmap;
  1379.     int        spl, pai;
  1380.     pmeg_t        pmegp;
  1381.  
  1382.     printf("pr_pvlist(epa %x)\n", epa);
  1383.  
  1384.     epa &= ~EPA_NC;
  1385.     if (!managed_epa(epa)) {
  1386.         /*
  1387.          *    Not a managed page.
  1388.          */
  1389.         return;
  1390.     }
  1391.  
  1392.     /*
  1393.      *    Lock the pmap system first, since we will be changing
  1394.      *    several pmaps.
  1395.      */
  1396.  
  1397.     PMAP_WRITE_LOCK(spl);
  1398.  
  1399.     /*
  1400.      *    Walk down PV list, removing all mappings.
  1401.      */
  1402.     pai = pa_index(epa);
  1403.     pv_h = pai_to_pvh(pai);
  1404.  
  1405.     while ((pmap = pv_h->pmap) != PMAP_NULL) {
  1406.         va = pv_h->va;
  1407.         printf("    pr_pvlist: va = %x epa = %x pmap = %x\n", va, epa, pmap);
  1408.  
  1409.         if (pmap->context == CONTEXT_NULL)
  1410.         context_allocate(pmap);
  1411.  
  1412.         simple_lock(&pmap->lock);
  1413.         pme = getpagemap(pmap->context->num, va);
  1414.         if ((pme & PG_V) == 0) {
  1415.         printf("pr_pvlist: pme in list but not in map\n");
  1416.         }
  1417.         if (! epa_equal(pme_to_epa(pme), epa)) {
  1418.         printf("pr_pvlist: pme does not point to page\n");
  1419.         }
  1420.         pmegp = get_pmeg(pmap, va);
  1421.         if (is_pmeg_wired(pmegp, va)) {
  1422.         panic("pr_pvlist: removing a wired page");
  1423.         }
  1424.         pv_h = pv_h->next;
  1425.         simple_unlock(&pmap->lock);
  1426.         if (!pv_h)
  1427.             break;
  1428.     }
  1429.     PMAP_WRITE_UNLOCK(spl);
  1430. }
  1431.  
  1432. boolean_t pmap_verify_free(phys)
  1433.     vm_offset_t    phys;
  1434. {
  1435.     pv_entry_t    pv_h;
  1436.     int        pai;
  1437.     int        spl;
  1438.     boolean_t    result;
  1439.  
  1440.     assert(phys != vm_page_fictitious_addr);
  1441.  
  1442.     if (!pmap_initialized)
  1443.         return(TRUE);
  1444.  
  1445.     phys &= ~EPA_NC;
  1446.     if (!managed_epa(phys))
  1447.         return(FALSE);
  1448.  
  1449.     PMAP_WRITE_LOCK(spl);
  1450.  
  1451.     pai = pa_index(phys);
  1452.     pv_h = pai_to_pvh(pai);
  1453.  
  1454.     result = (pv_h->pmap == PMAP_NULL);
  1455.     PMAP_WRITE_UNLOCK(spl);
  1456.  
  1457.     return(result);
  1458. }
  1459.  
  1460.  
  1461. /*
  1462.  *    Removes write privileges from all physical maps for the
  1463.  *    specified physical page.
  1464.  */
  1465. void    pmap_copy_on_write(epa)
  1466.     vm_offset_t    epa;
  1467. {
  1468.     pv_entry_t    pv_e;
  1469.     pmap_t        pmap;
  1470.     vm_offset_t    va;
  1471.     int        pme, i, spl;
  1472.  
  1473.     assert(phys != vm_page_fictitious_addr);
  1474.  
  1475.     epa &= ~EPA_NC;
  1476.     if (!managed_epa(epa)) {
  1477.         return;
  1478.     }
  1479.  
  1480.     /*
  1481.      *    Lock the entire pmap system, since we may be changing
  1482.      *    several maps.
  1483.      */
  1484.     PMAP_WRITE_LOCK(spl);
  1485.  
  1486.     pv_e = pai_to_pvh(pa_index(epa));
  1487.     if (pv_e->pmap == PMAP_NULL) {
  1488.         PMAP_WRITE_UNLOCK(spl);
  1489.         return;
  1490.     }
  1491.  
  1492.     while (pv_e != PV_ENTRY_NULL) {
  1493.         pmap = pv_e->pmap;
  1494.         va = pv_e->va;
  1495.         if (pmap->context == CONTEXT_NULL)
  1496.         context_allocate(pmap);
  1497.  
  1498.         simple_lock(&pmap->lock);
  1499.  
  1500.         i = pmes_per_vm_page;
  1501.         do {
  1502.         /*
  1503.          *    Turn off write permission for each mapping.
  1504.          *    We only have to flush the cache if the mapping
  1505.          *    is writeable.
  1506.          */
  1507.         pme = getpagemap(pmap->context->num, va);
  1508.         if (pme & PG_W) {
  1509.             Cache_Flush_Page(pmap->context->num, va);
  1510.             setpagemap(pmap->context->num, va, pme & ~PG_W);
  1511.         }
  1512.         va += NBPG;
  1513.         } while (--i > 0);
  1514.  
  1515.         simple_unlock(&pmap->lock);
  1516.         pv_e = pv_e->next;
  1517.     }
  1518. }
  1519.  
  1520. /*
  1521.  *    Set the protection on the specified range of this pmap as requested.
  1522.  */
  1523. void    pmap_protect(pmap, s, e, prot)
  1524.     pmap_t    pmap;
  1525.     vm_offset_t    s, e;
  1526.     vm_prot_t    prot;
  1527. {
  1528.     register int        new_prot;
  1529.     register vm_offset_t    l, c;
  1530.     register int        pme;
  1531.     int            spl;
  1532.     int            cnum;
  1533.  
  1534.     if (pmap == PMAP_NULL)
  1535.         return;
  1536.  
  1537.     if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
  1538.         pmap_remove(pmap, s, e);
  1539.         return;
  1540.     }
  1541.  
  1542.     if (prot & VM_PROT_WRITE)
  1543.         return;
  1544.  
  1545.     if (pmap->context == CONTEXT_NULL)
  1546.         context_allocate(pmap);
  1547.  
  1548.     cnum = pmap->context->num;
  1549.  
  1550.     new_prot = sun_protection(pmap, prot);
  1551.  
  1552.     SPLVM(spl);
  1553.     simple_lock(&pmap->lock);
  1554.  
  1555.     if (pmap == kernel_pmap) {
  1556.         if (s < VM_MIN_KERNEL_ADDRESS)
  1557.         s = VM_MIN_KERNEL_ADDRESS;
  1558.         if (e > VM_MAX_KERNEL_ADDRESS)
  1559.         e = VM_MAX_KERNEL_ADDRESS;
  1560.     }
  1561.     else {
  1562.         if (e > VM_MAX_ADDRESS)
  1563.         e = VM_MAX_ADDRESS;
  1564.     }
  1565.  
  1566.     while (s < e) {
  1567.         l = round_pmeg(s + 1);
  1568.         if (l > e)
  1569.         l = e;
  1570.         if (pmeg_valid(pmap, s)) {
  1571.         Cache_Flush_Range(cnum, s, l, c);
  1572.         for (c = s; c < l; c += NBPG) {
  1573.             pme = changepagemap(cnum, c, ~PG_PROT, new_prot);
  1574.             if ( ! (pme & PG_V))
  1575.                 setpagemap(cnum, c, 0);
  1576.         }
  1577.         }
  1578.     s = l;
  1579.     }
  1580.  
  1581.     simple_unlock(&pmap->lock);
  1582.     SPLX(spl);
  1583. }
  1584.  
  1585. /*
  1586.  *    Insert the given physical page (p) at
  1587.  *    the specified virtual address (v) in the
  1588.  *    target physical map with the protection requested.
  1589.  *
  1590.  *    If specified, the page will be wired down, meaning
  1591.  *    that the related pme can not be reclaimed.
  1592.  *
  1593.  *    NB:  This is the only routine which MAY NOT lazy-evaluate
  1594.  *    or lose information.  That is, this routine must actually
  1595.  *    insert this page into the given map NOW.
  1596.  */
  1597. void    pmap_enter(pmap, va, epa, prot, wired)
  1598.     pmap_t        pmap;
  1599.     vm_offset_t    va;
  1600.     vm_offset_t    epa;
  1601.     vm_prot_t    prot;
  1602.     boolean_t    wired;
  1603. {
  1604.     int        new_prot;
  1605.     pv_entry_t    pv_e, pv_h;
  1606.     pmeg_t        pmegp;
  1607.     int        pme, newpme;
  1608.     vm_offset_t    old_epa;
  1609.     int        i;
  1610.     vm_offset_t    lva;
  1611.     int        spl;
  1612.     int        pai;
  1613.  
  1614.     assert(epa != vm_page_fictitious_addr);
  1615.  
  1616.     if (pmap == PMAP_NULL) {
  1617.         return;
  1618.     }
  1619.  
  1620.     /*
  1621.      *    Set up the template for the new page table entry.
  1622.      *        EPA_NC gets propagated to PG_NC.
  1623.      */
  1624.     new_prot = sun_protection(pmap, prot);
  1625.     newpme = PG_V | new_prot | epa_to_pme(epa);
  1626.     epa &= ~EPA_NC;
  1627.  
  1628.     /*
  1629.      *    Must allocate a new pvlist entry while we're unlocked;
  1630.      *    zalloc may cause pageout (which will lock the pmap system).
  1631.      *    If we determine we need a pvlist entry, we will unlock
  1632.      *    and allocate one.  Then we will retry, throwing away
  1633.      *    the allocated entry later (if we no longer need it).
  1634.      */
  1635.     pv_e = PV_ENTRY_NULL;
  1636.  
  1637. Retry:
  1638.     PMAP_READ_LOCK(pmap, spl);
  1639.  
  1640.     /*
  1641.      *    Get a context.
  1642.      */
  1643.     while (pmap->context == CONTEXT_NULL) {
  1644.         PMAP_READ_UNLOCK(pmap, spl);
  1645.         context_allocate(pmap);
  1646.         PMAP_READ_LOCK(pmap, spl);
  1647.     }
  1648.  
  1649.     /*
  1650.      *    Get a pme page for this mapping.
  1651.      */
  1652.     if (!pmeg_valid(pmap, va)) {
  1653.         /*
  1654.         *    First try to get a free page-table page.
  1655.         */
  1656.         pmegp = free_pmeg_alloc(pmap, va);
  1657.         if (pmegp == PMEG_NULL) {
  1658.         /*
  1659.          *    No free pme pages.  Must get the write lock on
  1660.          *    the pmap system to grab one away from another
  1661.          *    pmap.
  1662.          */
  1663.         PMAP_READ_UNLOCK(pmap, spl);
  1664.         PMAP_WRITE_LOCK(spl);
  1665.         /*
  1666.          *    Should check for our context going away here...
  1667.          */
  1668.         if (pmap->context == CONTEXT_NULL) {
  1669.             /* lost it */
  1670.             PMAP_WRITE_UNLOCK(spl);
  1671.             goto Retry;
  1672.         }
  1673.         pmegp = pmeg_alloc(pmap, va);
  1674.         PMAP_WRITE_TO_READ_LOCK(pmap);
  1675.         }
  1676.     } else
  1677.         pmegp = get_pmeg(pmap, va);
  1678. #if    WATCH
  1679.     if (pmap_watch) {
  1680.         printf("pmap_enter(pmap %x, va %x, epa %x, prot %x, wired %x) #%x\n",
  1681.             pmap, va, epa, prot, wired, pmegp-pmeg_array);
  1682.     }
  1683.     if (pmap_watch_va != (vm_offset_t) -1 && va == pmap_watch_va) {
  1684.         printf("va match\n");
  1685.         Debugger("Pmap");
  1686.     }
  1687.     if (pmap_watch_epa != (vm_offset_t) -1 && epa == pmap_watch_epa) {
  1688.         pr_pvlist(epa);
  1689.         printf("epa match\n");
  1690.         Debugger("Pmap");
  1691.     }
  1692. #endif    WATCH
  1693.  
  1694.     Use_Check(pmegp);
  1695.     pme = getpagemap(pmap->context->num, va);
  1696.     old_epa = pme_to_epa(pme);
  1697.     if ((pme & PG_V) && epa_equal(old_epa, epa)) {
  1698.         /*
  1699.          *    Special case if the physical page is already mapped
  1700.          *    at this address.  May be changing its wired attribute
  1701.          *    or protection.
  1702.          */
  1703.         if (wired && ! is_pmeg_wired(pmegp, va)) {
  1704.         pmap->stats.wired_count++;
  1705.         pmeg_wire(pmegp, va);
  1706.         }
  1707.         else if (!wired && is_pmeg_wired(pmegp, va)) {
  1708.         pmap->stats.wired_count--;
  1709.         pmeg_unwire(pmegp, va);
  1710.         }
  1711.  
  1712.         i = pmes_per_vm_page;
  1713.         lva = va;
  1714.         do {
  1715.         Cache_Flush_Page(pmap->context->num, lva);
  1716.         changepagemap(pmap->context->num, lva, PG_M|PG_R, newpme);
  1717.         lva += NBPG;
  1718.         inc_pme(newpme);
  1719.         } while (--i > 0);
  1720.     }
  1721.     else {
  1722.         /*
  1723.          *    Remove old mapping from the PV list if necessary.
  1724.          */
  1725.         if (! epa_equal(old_epa, 0)) {
  1726. #if    SUN_VAC
  1727.         if (vac) {
  1728.             i = pmes_per_vm_page;
  1729.             lva = va;
  1730.             do {
  1731.             Cache_Flush_Page(pmap->context->num, lva);
  1732.             lva += NBPG;
  1733.             } while (--i > 0);
  1734.         }
  1735. #endif    SUN_VAC
  1736.         pmap_remove_range(pmap, va, va + PAGE_SIZE, FALSE);
  1737.         }
  1738.         if (managed_epa(epa)) {
  1739.  
  1740.         pai = pa_index(epa);
  1741.         LOCK_PVH(pai);
  1742.         pv_h = pai_to_pvh(pai);
  1743.  
  1744.         if (pv_h->pmap == PMAP_NULL) {
  1745.             /*
  1746.              *    No mappings yet - put at head.
  1747.              */
  1748.             pv_h->va = va;
  1749.             pv_h->pmap = pmap;
  1750.             pv_h->next = PV_ENTRY_NULL;
  1751.             if (newpme & PG_NC)
  1752.             phys_attributes[pai] |= PHYS_NOCACHE;
  1753.         }
  1754.         else {
  1755.             if (pv_e == PV_ENTRY_NULL) {
  1756.             /*
  1757.              *    Must unlock the map to allocate from a zone.
  1758.              */
  1759.             UNLOCK_PVH(pai);
  1760.             PMAP_READ_UNLOCK(pmap, spl);
  1761.             pv_e = (pv_entry_t) zalloc(pv_list_zone);
  1762.             goto Retry;
  1763.             }
  1764.             /*
  1765.              *    Insert new entry after header, then check whether
  1766.              *    we can still cache the mappings.
  1767.              */
  1768.             pv_e->va = va;
  1769.             pv_e->pmap = pmap;
  1770.             pv_e->next = pv_h->next;
  1771.             pv_h->next = pv_e;
  1772.  
  1773.             if (phys_attributes[pai] & (PHYS_NOMATCH | PHYS_NOCACHE)) {
  1774.             newpme |= PG_NC;
  1775.             }
  1776.             else if (newpme & PG_NC) {
  1777.             phys_attributes[pai] |= PHYS_NOCACHE;
  1778.             pv_uncache(pv_h);
  1779.             }
  1780.             else if ((va & 0x1FFFF) != (pv_h->va & 0x1FFFF)){
  1781.             newpme |= PG_NC;
  1782.             phys_attributes[pai] |= PHYS_NOMATCH;
  1783.             pv_uncache(pv_h);
  1784.             }
  1785.             
  1786.             /*
  1787.              *    We used the pvlist entry - don't deallocate it.
  1788.              */
  1789.             pv_e = PV_ENTRY_NULL;
  1790.         }
  1791.         UNLOCK_PVH(pai);
  1792.         }
  1793.  
  1794.         /*
  1795.          *    And count the mapping.
  1796.          */
  1797.         pmap->stats.resident_count++;
  1798.         pmegp->use_count++;
  1799.         if (wired) {
  1800.         pmap->stats.wired_count++;
  1801.         pmeg_wire(pmegp, va);
  1802.         }
  1803.         
  1804.         i = pmes_per_vm_page;
  1805.         lva = va;
  1806.         do {
  1807.         setpagemap(pmap->context->num, lva, newpme);
  1808.         lva += NBPG;
  1809.         inc_pme(newpme);
  1810.         } while (--i > 0);
  1811.     }
  1812. #if    PARANOIA
  1813.         /* check va/epa/obj/data paged back in */
  1814.     if (va > KERNELBASE)
  1815.         ppg_in(va, epa);
  1816. #endif    PARANOIA
  1817.  
  1818.     Use_Check(pmegp);
  1819.     PMAP_READ_UNLOCK(pmap, spl);
  1820.  
  1821.     if (pv_e != PV_ENTRY_NULL) {
  1822.         zfree(pv_list_zone, (vm_offset_t) pv_e);
  1823.     }
  1824. }
  1825.  
  1826. /*
  1827.  *    Routine:    pmap_change_wiring
  1828.  *    Function:    Change the wiring attribute for a map/virtual-address
  1829.  *            pair.
  1830.  *    In/out conditions:
  1831.  *            The mapping must already exist in the pmap.
  1832.  */
  1833. void    pmap_change_wiring(pmap, va, wired)
  1834.     register pmap_t    pmap;
  1835.     vm_offset_t    va;
  1836.     boolean_t    wired;
  1837. {
  1838.     long            pme;
  1839.     pmeg_t            pmegp;
  1840.     vm_offset_t        lva;
  1841.     int            i;
  1842.     int            spl;
  1843.  
  1844.     if (pmap == PMAP_NULL)
  1845.         return;
  1846.  
  1847.     if (pmap->context == CONTEXT_NULL)
  1848.         context_allocate(pmap);
  1849.  
  1850.     /*
  1851.      *    Must grab the pmap system lock because we may change
  1852.      *    a pmeg queue.
  1853.      */
  1854.     PMAP_READ_LOCK(map, spl);
  1855.  
  1856. #if    SAFE
  1857.     if (!pmeg_valid(pmap, va))
  1858.         panic("pmap_change_wiring: pme invalid");
  1859. #endif    SAFE
  1860.     pmegp = get_pmeg(pmap, va);
  1861.  
  1862.     pme = getpagemap(pmap->context->num, va);
  1863.     if (wired && ! is_pmeg_wired(pmegp, va)) {
  1864.         /*
  1865.          *    Wiring down mapping
  1866.          */
  1867.         pmap->stats.wired_count++;
  1868.         pmeg_wire(pmegp, va);
  1869.     }
  1870.     else if (!wired && is_pmeg_wired(pmegp, va)) {
  1871.         /*
  1872.          *    Unwiring mapping.
  1873.          */
  1874.         pmap->stats.wired_count--;
  1875.         pmeg_unwire(pmegp, va);
  1876.     }
  1877.  
  1878.     i = pmes_per_vm_page;
  1879.     lva = va;
  1880.     do {
  1881.         pme = getpagemap(pmap->context->num, lva);
  1882.         if ((pme & PG_V) == 0)
  1883.         panic("pmap_change_wiring");
  1884.         /* the wire bit is not kept in the pme */
  1885.         lva += NBPG;
  1886.     } while (--i > 0);
  1887.  
  1888.     PMAP_READ_UNLOCK(pmap, spl);
  1889. }
  1890.  
  1891. /*
  1892.  *    Routine:    pmap_extract
  1893.  *    Function:
  1894.  *        Extract the physical page address associated
  1895.  *        with the given map/virtual_address pair.
  1896.  */
  1897.  
  1898. vm_offset_t pmap_extract(pmap, va)
  1899.     register pmap_t    pmap;
  1900.     vm_offset_t    va;
  1901. {
  1902.     long            pme;
  1903.     vm_offset_t        epa;
  1904.     int            spl;
  1905.  
  1906.     if (pmap == PMAP_NULL){
  1907.         printf("pmap_extract: null pmap\n");
  1908.         return(0);
  1909.     }
  1910.     if (pmap->context == CONTEXT_NULL)
  1911.         context_allocate(pmap);
  1912.  
  1913.     SPLVM(spl);
  1914.     simple_lock(&pmap->lock);
  1915.  
  1916.     pme = getpagemap(pmap->context->num, va);
  1917.  
  1918.     if ((pme & PG_V) == 0)
  1919.         epa = (vm_offset_t) 0;
  1920.     else {
  1921.         epa = (vm_offset_t) pme_to_epa(pme);
  1922.         epa |= va & (NBPG-1);    /* offset within page */
  1923.     }
  1924.     simple_unlock(&pmap->lock);
  1925.     SPLX(spl);
  1926.  
  1927.     return (epa);
  1928. }
  1929.  
  1930. /*
  1931.  *    Routine:    pmap_access
  1932.  *    Function:
  1933.  *        Returns whether there is a valid mapping for the
  1934.  *        given virtual address stored in the given physical map.
  1935.  */
  1936.  
  1937. boolean_t pmap_access(pmap, va)
  1938.     pmap_t        pmap;
  1939.     vm_offset_t    va;
  1940. {
  1941.     long            pme;
  1942.     boolean_t        ok;
  1943.     int            spl;
  1944.  
  1945.     if (pmap == PMAP_NULL){
  1946.         printf("pmap_access: null pmap\n");
  1947.         return(FALSE);
  1948.     }
  1949.     if (pmap->context == CONTEXT_NULL)
  1950.         context_allocate(pmap);
  1951.  
  1952.     SPLVM(spl);
  1953.     simple_lock(&pmap->lock);
  1954.  
  1955.     pme = getpagemap(pmap->context->num, va);
  1956.  
  1957.     if ((pme & PG_V) == 0)
  1958.         ok = FALSE;
  1959.     else
  1960.         ok = TRUE;
  1961.  
  1962.     simple_unlock(&pmap->lock);
  1963.     SPLX(spl);
  1964.     return (ok);
  1965. }
  1966.  
  1967. /*
  1968.  *    Copy the range specified by src_addr/len
  1969.  *    from the source map to the range dst_addr/len
  1970.  *    in the destination map.
  1971.  *
  1972.  *    This routine is only advisory and need not do anything.
  1973.  */
  1974. void pmap_copy(dst_pmap, src_pmap, dst_addr, len, src_addr)
  1975.     pmap_t        dst_pmap;
  1976.     pmap_t        src_pmap;
  1977.     vm_offset_t    dst_addr;
  1978.     vm_size_t    len;
  1979.     vm_offset_t    src_addr;
  1980. {
  1981. #ifdef    lint
  1982.     dst_pmap++; src_pmap++; dst_addr++; len++; src_addr++;
  1983. #endif    lint
  1984. }
  1985.  
  1986. /*
  1987.  *    Routine:    pmap_collect
  1988.  *    Function:
  1989.  *        Garbage collects the physical map system for
  1990.  *        pages which are no longer used.
  1991.  *        Success need not be guaranteed -- that is, there
  1992.  *        may well be pages which are not referenced, but
  1993.  *        others may be collected.
  1994.  *    Usage:
  1995.  *        Called by the pageout daemon when pages are scarce.
  1996.  */
  1997. void pmap_collect(pmap)
  1998. pmap_t    pmap;
  1999. {
  2000. }
  2001.  
  2002. #ifdef    unneeded
  2003. /*
  2004.  *    Routine:    pmap_activate
  2005.  *    Function:
  2006.  *        Binds the given physical map to the given
  2007.  *        processor, and returns a hardware map description.
  2008.  */
  2009. void pmap_activate(pmap, th, cpu)
  2010.     register pmap_t    pmap;
  2011.     thread_t    th;
  2012.     int        cpu;
  2013. {
  2014.     PMAP_ACTIVATE(pmap, th, cpu);
  2015. }
  2016.  
  2017. /*
  2018.  *    Routine:    pmap_deactivate
  2019.  *    Function:
  2020.  *        Indicates that the given physical map is no longer
  2021.  *        in use on the specified processor.  (This is a macro
  2022.  *        in pmap.h)
  2023.  */
  2024. void pmap_deactivate(pmap, th, what_cpu)
  2025.     pmap_t        pmap;
  2026.     thread_t    th;
  2027.     int        what_cpu;
  2028. {
  2029. #ifdef    lint
  2030.     th++; what_cpu++;
  2031. #endif    lint
  2032. #if    NCPUS > 1
  2033.     ; YOU LOSE ;
  2034. #endif    NCPUS > 1
  2035.     PMAP_DEACTIVATE(pmap, th, what_cpu);
  2036. }
  2037. #endif    unneeded
  2038.  
  2039. /*
  2040.  *    Routine:    pmap_kernel
  2041.  *    Function:
  2042.  *        Returns the physical map handle for the kernel.
  2043.  */
  2044. pmap_t pmap_kernel()
  2045. {
  2046.         return (kernel_pmap);
  2047. }
  2048.  
  2049.  
  2050. /*
  2051.  *    Given a map and a machine independent protection code,
  2052.  *    convert to a sun protection code.
  2053.  */
  2054. int sun_protection(pmap, prot)
  2055.     pmap_t        pmap;
  2056.     vm_prot_t    prot;
  2057. {
  2058.     register int    p;
  2059.  
  2060.     p = (pmap == kernel_pmap) ? PG_S : 0;
  2061.     if (prot & VM_PROT_WRITE)
  2062.         p |= PG_W;
  2063.     return(p);
  2064. }
  2065.  
  2066. /*
  2067.  *    Clear the modify bits on the specified physical page.
  2068.  *
  2069.  *    XXX this does not yet work if the physical page is in
  2070.  *        any maps
  2071.  */
  2072.  
  2073. void pmap_clear_modify(epa)
  2074.     register vm_offset_t    epa;
  2075. {
  2076.     assert(epa != vm_page_fictitious_addr);
  2077.  
  2078.     epa &= ~EPA_NC;
  2079.     if (managed_epa(epa))
  2080.         update_phys_attributes(epa, 0, PHYS_MODIFIED);
  2081. }
  2082.  
  2083. /*
  2084.  *    pmap_is_modified:
  2085.  *
  2086.  *    Return whether or not the specified physical page is modified
  2087.  *    by any physical maps.
  2088.  *
  2089.  *    XXX this does not yet return complete information if the page
  2090.  *        is in any pmaps - pmap_remove_all should have just
  2091.  *        been called
  2092.  *        
  2093.  */
  2094.  
  2095. boolean_t pmap_is_modified(epa)
  2096.     register vm_offset_t    epa;
  2097. {
  2098.     assert(epa != vm_page_fictitious_addr);
  2099.  
  2100.     epa &= ~EPA_NC;
  2101.     if (managed_epa(epa))
  2102.         return update_phys_attributes(epa, PHYS_MODIFIED, 0);
  2103.     else
  2104.         return (FALSE);
  2105. }
  2106.  
  2107. /*
  2108.  *    Do we use the hardware's reference bits?
  2109.  */
  2110. boolean_t hardware_reference_bits = TRUE;
  2111.  
  2112. /*
  2113.  *    pmap_clear_reference:
  2114.  *
  2115.  *    Clear the reference bit on the specified physical page.
  2116.  *
  2117.  *    XXX this does not yet work if the physical page is in
  2118.  *        any maps
  2119.  */
  2120.  
  2121. void pmap_clear_reference(epa)
  2122.     vm_offset_t    epa;
  2123. {
  2124.     assert(epa != vm_page_fictitious_addr);
  2125.  
  2126.     if (hardware_reference_bits) {
  2127.         epa &= ~EPA_NC;
  2128.         if (managed_epa(epa))
  2129.         update_phys_attributes(epa, 0, PHYS_REFERENCED);
  2130.     } else
  2131.         pmap_remove_all(epa);
  2132. }
  2133.  
  2134. /*
  2135.  *    pmap_is_referenced:
  2136.  *
  2137.  *    Return whether or not the specified physical page is referenced
  2138.  *    by any physical maps.
  2139.  *
  2140.  *    XXX this does not yet return complete information if the page
  2141.  *        is in any pmaps - pmap_remove_all should have just
  2142.  *        been called
  2143.  */
  2144.  
  2145. boolean_t pmap_is_referenced(epa)
  2146.     vm_offset_t    epa;
  2147. {
  2148.     assert(epa != vm_page_fictitious_addr);
  2149.  
  2150.     if (hardware_reference_bits) {
  2151.         epa &= ~EPA_NC;
  2152.         if (managed_epa(epa)) {
  2153.         return update_phys_attributes(epa, PHYS_REFERENCED, 0);
  2154.         } else
  2155.         return (FALSE);
  2156.     } else
  2157.         return (FALSE);
  2158. }
  2159.  
  2160. update_phys_attributes(pa, check, clr)
  2161.     vm_offset_t    pa;
  2162. {
  2163.     pv_entry_t    pv_h;
  2164.     int        pme;
  2165.     vm_offset_t    va;
  2166.     pmap_t        pmap;
  2167.     register int    i;
  2168.     int        pai;
  2169.     int        change = -1;        /* i.e. don't change pme */
  2170.     change &= ~ ( ((clr&PHYS_MODIFIED) ? PG_M : 0) | ((clr&PHYS_REFERENCED) ? PG_R : 0) );
  2171.  
  2172.     /*
  2173.      *    Walk down PV list, let pmap_remove_all do all the hairy
  2174.      *    consistency checks
  2175.      */
  2176.     pai = pa_index(pa);
  2177.     pv_h = pai_to_pvh(pai);
  2178.  
  2179.     if (!clr)
  2180.         if ((phys_attributes[pai] & check) == check)
  2181.             return 1;
  2182.     while ((pmap = pv_h->pmap) != PMAP_NULL) {
  2183.         va = pv_h->va;
  2184.         if (pmap->context == CONTEXT_NULL)
  2185.         context_allocate(pmap);
  2186.  
  2187.         simple_lock(&pmap->lock);
  2188.  
  2189.         i = pmes_per_vm_page;
  2190.         do {
  2191.         Cache_Flush_Page(pmap->context->num, va);
  2192.         pme = changepagemap(pmap->context->num, va, change, 0);
  2193.         phys_attributes[pai] |= pme_mr(pme);
  2194.         if (!clr)
  2195.             if ((phys_attributes[pai] & check) == check) {
  2196.                 simple_unlock(&pmap->lock);
  2197.                 return 1;
  2198.             }
  2199.  
  2200.         va += NBPG;
  2201.         } while (--i > 0);
  2202.  
  2203.         simple_unlock(&pmap->lock);
  2204.  
  2205.         if ((pv_h = pv_h->next) == PV_ENTRY_NULL) {
  2206.             break;
  2207.         }
  2208.  
  2209.     }
  2210.     phys_attributes[pai] &= ~ clr;
  2211.     return ((phys_attributes[pai] & check) == check);
  2212. }
  2213.  
  2214. /*
  2215.  *    Routine:    pmap_pageable
  2216.  *    Function:
  2217.  *        Make the specified pages (by pmap, offset)
  2218.  *        pageable (or not) as requested.
  2219.  *
  2220.  *        A page which is not pageable may not take
  2221.  *        a fault; therefore, its page table entry
  2222.  *        must remain valid for the duration.
  2223.  *
  2224.  *        This routine is merely advisory; pmap_enter
  2225.  *        will specify that these pages are to be wired
  2226.  *        down (or not) as appropriate.
  2227.  *
  2228.  */
  2229. void pmap_pageable(pmap, start, end, pageable)
  2230.     pmap_t        pmap;
  2231.     vm_offset_t    start;
  2232.     vm_offset_t    end;
  2233.     boolean_t    pageable;
  2234. {
  2235. #ifdef    lint
  2236.     pmap++; start++; end++; pageable++;
  2237. #endif    lint
  2238. }
  2239.  
  2240. /*
  2241.  *    Make each virtual page in the pv list not cacheable from the given
  2242.  *    pv_entry to the end of the list
  2243.  */
  2244. pv_uncache(pv_e)
  2245.     pv_entry_t    pv_e;
  2246. {
  2247.     register pv_entry_t    cur;
  2248.     register pmap_t        pmap;
  2249.     register vm_offset_t    va;
  2250.     int            i;
  2251.  
  2252.     for (cur = pv_e; cur != PV_ENTRY_NULL && cur->pmap != PMAP_NULL;
  2253.             cur = cur->next){
  2254.         pmap = cur->pmap;
  2255.         va = cur->va;
  2256.         if (pmap->context == CONTEXT_NULL)
  2257.         context_allocate(pmap);
  2258.         i = pmes_per_vm_page;
  2259.         do {
  2260.         Cache_Flush_Page(pmap->context->num, va);
  2261.         changepagemap(pmap->context->num, va, -1, PG_NC);
  2262.         } while (--i > 0);
  2263.     }
  2264. }
  2265.  
  2266. void
  2267. page_zero(dst) 
  2268. register int * dst;
  2269. {
  2270.     register int cnt;
  2271.     for (cnt = NBPG/4; cnt != 0; cnt-=32) {
  2272.         *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0;
  2273.         *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0;
  2274.         *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0;
  2275.         *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0;
  2276.         *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0;
  2277.         *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0;
  2278.         *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0;
  2279.         *dst++ = 0; *dst++ = 0; *dst++ = 0; *dst++ = 0;
  2280.     }
  2281. }
  2282.  
  2283.  
  2284. /*
  2285.  *    Routines to manipulate memory via physical addresses.
  2286.  */
  2287.  
  2288. /*
  2289.  *    pmap_zero_page zeros the specified (machine independent)
  2290.  *    page by mapping the page into virtual memory and using
  2291.  *    bzero to clear its contents, one machine dependent page
  2292.  *    at a time.
  2293.  */
  2294. pmap_zero_page(epa)
  2295.     register vm_offset_t    epa;
  2296. {
  2297.     register vm_offset_t    va;
  2298.     register int        i, pme;
  2299.  
  2300.     assert(epa != vm_page_fictitious_addr);
  2301.  
  2302.     Vac_Physflush(epa, PAGE_SIZE);
  2303.     va = (vm_offset_t)(phys_map_vaddr1 + (cpu_number() * NBPG));
  2304.     i = pmes_per_vm_page;
  2305.     /*
  2306.      *    No need to fill up the cache with a page full
  2307.      *    of zeros.
  2308.      */
  2309.     pme = epa_to_pme(epa) | PG_V | PG_KW | PG_NC;
  2310.     do {
  2311.         setpgmap(va, pme);
  2312.         page_zero((int *)va);    
  2313.         inc_pme(pme);
  2314.         va += NBPG;
  2315.     } while (--i > 0);
  2316. }
  2317.  
  2318. /*
  2319.  *    pmap_copy_page copies the specified (machine independent)
  2320.  *    page by mapping the page into virtual memory and using
  2321.  *    bcopy to copy the page, one machine dependent page at a
  2322.  *    time.
  2323.  */
  2324. pmap_copy_page(src, dst)
  2325.     vm_offset_t    src, dst;
  2326. {
  2327.     register int        dstpme, srcpme, i;
  2328.     register vm_offset_t    dstva, srcva;
  2329.  
  2330.     assert(src != vm_page_fictitious_addr);
  2331.     assert(dst != vm_page_fictitious_addr);
  2332.  
  2333.     Vac_Physflush(src, PAGE_SIZE);
  2334.     srcpme = epa_to_pme(src) | PG_V | PG_KR | PG_NC;
  2335.     srcva = (vm_offset_t)(phys_map_vaddr1 + (cpu_number() * NBPG));
  2336.     Vac_Physflush(dst, PAGE_SIZE);
  2337.     dstpme = epa_to_pme(dst) | PG_V | PG_KW | PG_NC;
  2338.     dstva = (vm_offset_t)(phys_map_vaddr2 + (cpu_number() * NBPG));
  2339.  
  2340.     i = pmes_per_vm_page;
  2341.     do {
  2342.         setpgmap(srcva, srcpme);
  2343.         setpgmap(dstva, dstpme);
  2344.         bcopy((int *)srcva, (int *)dstva, NBPG);
  2345.         inc_pme(srcpme);
  2346.         inc_pme(dstpme);
  2347.         srcva += NBPG;
  2348.         dstva += NBPG;
  2349.     } while (--i > 0);
  2350. }
  2351.  
  2352.  
  2353. /*
  2354.  *    copy_to_phys
  2355.  *
  2356.  *    Copy virtual memory to physical memory by mapping the physical
  2357.  *    memory into virtual memory and then doing a virtual to virtual
  2358.  *    copy with bcopy.
  2359.  *    NB: assumes that both source and destination are aligned
  2360.  *    on page boundaries.
  2361.  */
  2362. copy_to_phys(srcva, dstpa, bytecount)
  2363.     register vm_offset_t    srcva;
  2364.     register vm_offset_t    dstpa;
  2365.     register int        bytecount;
  2366. {
  2367.     register vm_offset_t    dstva;
  2368.     register int        copy_size, offset;
  2369.  
  2370.     assert(dstpa != vm_page_fictitious_addr);
  2371.  
  2372.     Vac_Physflush(dstpa, bytecount);
  2373.     dstva = (vm_offset_t)(phys_map_vaddr1 + (cpu_number() * NBPG));
  2374.     copy_size = NBPG;
  2375.     offset = dstpa - sun_trunc_page(dstpa);
  2376.     dstpa -= offset;
  2377.  
  2378.     while (bytecount > 0){
  2379.         copy_size = NBPG - offset;
  2380.         if (copy_size > bytecount)
  2381.         copy_size = bytecount;
  2382.         setpgmap(dstva, epa_to_pme(dstpa) | PG_V | PG_KW);
  2383.         dstva += offset;
  2384.         bcopy(srcva, dstva, copy_size);
  2385.         Cache_Flush_Page(KCONTEXT, dstva);
  2386.         srcva += copy_size;
  2387.         dstpa += NBPG;
  2388.         bytecount -= copy_size;
  2389.         offset = 0;
  2390.     }
  2391. }
  2392.  
  2393. /*
  2394.  *    copy_from_phys
  2395.  *
  2396.  *    Copy physical memory to virtual memory by mapping the physical
  2397.  *    memory into virtual memory and then doing a virtual to virtual
  2398.  *    copy with bcopy.
  2399.  *    NB: assumes that both source and destination are aligned
  2400.  *    on page boundaries.
  2401.  */
  2402. copy_from_phys(srcpa, dstva, bytecount)
  2403.     register vm_offset_t    srcpa;
  2404.     register vm_offset_t    dstva;
  2405.     register int        bytecount;
  2406. {
  2407.     register vm_offset_t    srcva;
  2408.     register int        copy_size, offset;
  2409.  
  2410.     assert(srcpa != vm_page_fictitious_addr);
  2411.  
  2412.     Vac_Physflush(srcpa, bytecount);
  2413.     srcva = (vm_offset_t)(phys_map_vaddr1 + (cpu_number() * NBPG));
  2414.     copy_size = NBPG;
  2415.     offset = srcpa - sun_trunc_page(srcpa);
  2416.     srcpa -= offset;
  2417.     while (bytecount > 0){
  2418.         copy_size = NBPG - offset;
  2419.         setpgmap(srcva, epa_to_pme(srcpa) | PG_V | PG_KR);
  2420.         srcva += offset;
  2421.         if (copy_size > bytecount)
  2422.             copy_size = bytecount;
  2423.         bcopy(srcva, dstva, copy_size);
  2424.         Cache_Flush_Page(KCONTEXT, (caddr_t)srcva);
  2425.         dstva += copy_size;
  2426.         srcpa += NBPG;
  2427.         bytecount -= copy_size;
  2428.         offset = 0;
  2429.     }
  2430. }
  2431.  
  2432. /*
  2433.  *    pmap_page_protect:
  2434.  *
  2435.  *    Lower the permission for all mappings to a given page.
  2436.  */
  2437. void    pmap_page_protect(epa, prot)
  2438.     vm_offset_t    epa;
  2439.     vm_prot_t    prot;
  2440. {
  2441.     assert(epa != vm_page_fictitious_addr);
  2442.  
  2443.     switch (prot) {
  2444.         case VM_PROT_READ:
  2445.         case VM_PROT_READ|VM_PROT_EXECUTE:
  2446.             pmap_copy_on_write(epa);
  2447.             break;
  2448.         case VM_PROT_ALL:
  2449.             break;
  2450.         default:
  2451.             pmap_remove_all(epa);
  2452.             break;
  2453.     }
  2454. }
  2455.  
  2456. vm_offset_t    pmap_phys_address(x)
  2457.     int        x;
  2458. {
  2459.     
  2460.     return (pme_to_epa(x) | EPA_NC);
  2461. }
  2462.  
  2463. /*
  2464.  *    getmemc
  2465.  *    Get 1 byte from physical memory.
  2466.  */
  2467. unsigned char getmemc(epa)
  2468.     vm_offset_t    epa;
  2469. {
  2470.     unsigned char    byte;
  2471.     caddr_t        va;
  2472.  
  2473.     Vac_Physflush(epa, PAGE_SIZE);    /* Ouch! */
  2474.     va = (caddr_t)(phys_map_vaddr1 + (cpu_number() * NBPG));
  2475.     setpgmap(va, epa_to_pme(epa) | PG_V | PG_KR | PG_NC);
  2476.     byte = *(unsigned char *)(va + (epa & (NBPG - 1)));
  2477.     return(byte);
  2478. }
  2479.  
  2480. /*
  2481.  *    putmemc
  2482.  *    Put 1 byte into physical memory.
  2483.  */
  2484. void putmemc(epa, byte)
  2485.     vm_offset_t    epa;
  2486.     unsigned char    byte;
  2487. {
  2488.     caddr_t        va;
  2489.  
  2490.     Vac_Physflush(epa, PAGE_SIZE);    /* Ouch! */
  2491.     va = (caddr_t)(phys_map_vaddr1 + (cpu_number() * NBPG));
  2492.     setpgmap(va, epa_to_pme(epa) | PG_V | PG_KW | PG_NC);
  2493.     va += epa & (NBPG - 1);
  2494.     *(unsigned char *)va = byte;
  2495. }
  2496.  
  2497. #if    SUN_VAC
  2498. /*
  2499.  *    Flush specified number of bytes (rounded up to a page) from virtual
  2500.  *    address cache starting at given physical address
  2501.  */
  2502. vac_physflush(epa, bytecount)
  2503.     register vm_offset_t    epa;
  2504.     register int        bytecount;
  2505. {
  2506.     register pv_entry_t    pv_h;
  2507.     long            pme;
  2508.     register vm_offset_t    va;
  2509.     register pmap_t        pmap;
  2510.     int             pai;
  2511.     int            i;
  2512.  
  2513.     epa &= ~EPA_NC;
  2514.     if (!vac || !managed_epa(epa))
  2515.         return;
  2516.  
  2517.     epa = trunc_page(epa);
  2518.     while (bytecount > 0){
  2519.         /*
  2520.          *    Run down the PV list, flushing all of the virtual pages
  2521.          *    that map to this physical page
  2522.          */
  2523.         pai = pa_index(epa);
  2524.         LOCK_PVH(pai);
  2525.         for (pv_h = pai_to_pvh(pai); pv_h != PV_ENTRY_NULL
  2526.              && pv_h->pmap != PMAP_NULL; pv_h = pv_h->next) {
  2527.         pmap = pv_h->pmap;
  2528.         va = pv_h->va;
  2529.         if (pmap->context == CONTEXT_NULL)
  2530.             context_allocate(pmap);
  2531.         i = pmes_per_vm_page;
  2532.         do {
  2533.             pme = getpagemap(pmap->context->num, va);
  2534.             if ((pme & PG_V) == 0)
  2535.             panic("vac_physflush: pme in list but not in map");
  2536.             Cache_Flush_Page(pmap->context->num, va);
  2537.         } while (--i > 0);
  2538.         }
  2539.         UNLOCK_PVH(pai);
  2540.         bytecount -= PAGE_SIZE;
  2541.         epa += PAGE_SIZE;
  2542.     }
  2543. }
  2544. #endif    SUN_VAC
  2545.  
  2546. pmap_map_page(vaddr, pfn, size)
  2547.     vm_offset_t        vaddr;
  2548.     vm_offset_t        pfn;
  2549.     u_int            size;
  2550. {
  2551.     vm_offset_t        epa = pme_to_epa(pfn) | EPA_NC;
  2552.     
  2553.     pmap_map(vaddr, epa, epa + size, VM_PROT_READ|VM_PROT_WRITE);
  2554. }
  2555.  
  2556. /*
  2557.  *    Set the protection on the specified range of this pmap as requested.
  2558.  *    Like pmap_protect, but kernel only, use sun protections and deal with
  2559.  *    PG_NC nocache
  2560.  */
  2561. void    pme_protect(s, e, prot)
  2562.     vm_offset_t    s, e;
  2563.     int        prot;
  2564. {
  2565.     register vm_offset_t    l, c;
  2566.     u_int        pme;
  2567.  
  2568.     while (s < e) {
  2569.         l = round_pmeg(s + 1);
  2570.         if (l > e)
  2571.         l = e;
  2572.         if (pmeg_valid(kernel_pmap, s)) {
  2573.         Cache_Flush_Range(KCONTEXT, s, l, c);
  2574.         for (c = s; c < l; c += NBPG) {
  2575.             pme = changepgmap(c, ~(PG_PROT|PG_NC), prot);
  2576.             if ( ! (pme & PG_V))
  2577.                 setpgmap(c, 0);
  2578.         }
  2579.         }
  2580.     s = l;
  2581.     }
  2582. }
  2583.  
  2584. /*
  2585.  *    Set the pme on the specified range of this map to zero.
  2586.  *    And create pmeg if requested and SEGINV
  2587.  */
  2588. void    pme_zero(s, e, reserved)
  2589.     vm_offset_t    s, e;
  2590. {
  2591.     register vm_offset_t    l, c;
  2592.     register pmeg_t        pmegp;
  2593.  
  2594.  
  2595.     while (s < e) {
  2596.         l = round_pmeg(s + 1);
  2597.         if (l > e)
  2598.         l = e;
  2599.         if (pmegp=get_pmeg(kernel_pmap, s)) {
  2600.         Cache_Flush_Range(KCONTEXT, s, l, c);
  2601.         } else if ((pmegp=pmeg_alloc(kernel_pmap, s)) == PMEG_NULL) {
  2602.             panic("pme_zero: no pmegs");
  2603.         } else if (reserved) {
  2604.             pmegp->pmap = PMAP_NULL;    /* can't recycle pmeg */
  2605.             pmegp->use_count = 4*NPAGSEG;
  2606.         }
  2607.  
  2608.         for (c = s; c < l; c += NBPG)
  2609.         setpgmap(c, 0);
  2610.         s = l;
  2611.     }
  2612. }
  2613.  
  2614.  
  2615. /*
  2616.  *    To save rewriting/modifying old sun code, define:
  2617.  */
  2618.  
  2619. getkpgmap(va)
  2620.     vm_offset_t va;
  2621. {
  2622.     if (va <  VM_MIN_KERNEL_ADDRESS ||
  2623.         va >= VM_MAX_KERNEL_ADDRESS)
  2624.         panic("getkpgmap");
  2625.     return (getpgmap(va));
  2626. }
  2627.  
  2628. vac_pageflush(va)
  2629.     vm_offset_t va;
  2630. {
  2631.     Cache_Flush_Page(CURRENTCONTEXT, va);
  2632. }
  2633.  
  2634. #if    CHECK
  2635. use_check(pmegp)
  2636.     pmeg_t        pmegp;
  2637. {
  2638.     vm_offset_t    v;
  2639.     int        pme;
  2640.     int        count = 0;
  2641.     int        i;
  2642.  
  2643.     if (pmegp->pmap == PMAP_NULL)
  2644.         return;
  2645.     if (pmegp->pmap->context == CONTEXT_NULL)
  2646.         context_allocate(pmegp->pmap);
  2647.     for (i = 0, v = pmegp->va; i < NPAGSEG; i++, v += NBPG) {
  2648.         pme = getpagemap(pmegp->pmap->context->num, v);
  2649.         if (pme & PG_V)
  2650.             count++;
  2651.     }
  2652.  
  2653.     if (pmegp->use_count != count) {
  2654.         printf("v = %x, pmeg %x[#%x] use_count = %x, pme_count = %x\n",
  2655.             pmegp->va, pmegp, pmegp - pmeg_array, pmegp->use_count, count);
  2656.         break_here();
  2657.     }
  2658. }
  2659.  
  2660. break_here()
  2661. {
  2662. }
  2663.  
  2664. print_context_queue(q, name)
  2665.     queue_entry_t        q;
  2666.     char *            name;
  2667. {
  2668.     queue_entry_t        e;
  2669.     int            cnt = NCONTEXT;
  2670.  
  2671.     if (queue_empty(q))
  2672.         printf("QUEUE: %s EMTPY\n", name);
  2673.     else {
  2674.         printf("QUEUE: %s ", name);
  2675.         e = queue_first(q);
  2676.         while ( (! queue_end(q, e)) && cnt--) {
  2677.             printf("%x ", ((context_t)e)->num);
  2678.                e = queue_next(e);
  2679.         }
  2680.         printf("\n");
  2681.     }
  2682. }
  2683.  
  2684. context_enq_ck(q, name, context)
  2685.     queue_entry_t        q;
  2686.     char *            name;
  2687.     context_t        context;
  2688. {
  2689.     queue_entry_t        e;
  2690.     int            cnt = NCONTEXT;
  2691.  
  2692.     if (queue_empty(q))
  2693.         printf("QUEUE SCAN: %s EMTPY\n", name);
  2694.     else {
  2695.         e = queue_first(q);
  2696.         while ( (! queue_end(q, e)) && cnt--) {
  2697.             if ( ((context_t)q) == context ) {
  2698.                 printf("%s: entry %x[%x] exists.\n",
  2699.                     name, context, context-context_array);
  2700.                 print_context_queue(q, name);
  2701.                 Debugger("Pmap");
  2702.             }
  2703.                e = queue_next(e);
  2704.         }
  2705.         if (cnt <= 0) {
  2706.             printf("QUEUE SCAN: %s Knotted\n", name);
  2707.             print_context_queue(q, name);
  2708.             Debugger("Pmap");
  2709.         }
  2710.     }
  2711. }
  2712.  
  2713. print_pmeg_queue(q, name)
  2714.     queue_entry_t        q;
  2715.     char *            name;
  2716. {
  2717.     queue_entry_t        e;
  2718.     int            cnt = NPMEG;
  2719.  
  2720.     if (queue_empty(q))
  2721.         printf("QUEUE SCAN: %s EMTPY\n", name);
  2722.     else {
  2723.         printf("QUEUE SCAN: %s ", name);
  2724.         e = queue_first(q);
  2725.         while ( (! queue_end(q, e)) && cnt--) {
  2726.             printf("%x ", pmeg_to_seg(((pmeg_t)e)));
  2727.                e = queue_next(e);
  2728.         }
  2729.         printf("\n");
  2730.     }
  2731. }
  2732.  
  2733. pmeg_enq_ck(q, name, pmegp)
  2734.     queue_entry_t        q;
  2735.     char *            name;
  2736.     pmeg_t            pmegp;
  2737. {
  2738.     queue_entry_t        e;
  2739.     int            cnt = NPMEG;
  2740.  
  2741.     if (queue_empty(q))
  2742.         printf("QUEUE SCAN: %s EMTPY\n", name);
  2743.     else {
  2744.         e = queue_first(q);
  2745.         while ( (! queue_end(q, e)) && cnt--) {
  2746.             if ( ((pmeg_t)e) == pmegp ) {
  2747.                 printf("%s: entry %x[%x] exists.\n",
  2748.                     name, pmegp, pmegp-pmeg_array);
  2749.                 print_pmeg_queue(q, name);
  2750.                 Debugger("Pmap");
  2751.             }
  2752.                e = queue_next(e);
  2753.         }
  2754.         if (cnt <= 0) {
  2755.             printf("QUEUE SCAN: %s Knotted\n", name);
  2756.             print_pmeg_queue(q, name);
  2757.             Debugger("Pmap");
  2758.         }
  2759.     }
  2760. }
  2761.  
  2762. pmeg_remq_ck(q, name, pmegp)
  2763.     queue_entry_t        q;
  2764.     char *            name;
  2765.     pmeg_t            pmegp;
  2766. {
  2767.     queue_entry_t        e;
  2768.     int            cnt = NPMEG;
  2769.  
  2770.     if (queue_empty(q))
  2771.         printf("QUEUE SCAN: %s EMTPY\n", name);
  2772.     else {
  2773.         e = queue_first(q);
  2774.         while ( (! queue_end(q, e)) && cnt--) {
  2775.             if ( ((pmeg_t)e) == pmegp ) {
  2776.                 return 1;
  2777.             }
  2778.                e = queue_next(e);
  2779.         }
  2780.         if (cnt <= 0) {
  2781.             printf("QUEUE SCAN: %s Knotted\n", name);
  2782.             print_pmeg_queue(q, name);
  2783.             Debugger("Pmap");
  2784.         }
  2785.         printf("%s: entry %x[%x] missing.\n",
  2786.             name, pmegp, pmegp-pmeg_array);
  2787.         print_pmeg_queue(q, name);
  2788.         print_pmeg_queue(&pmeg_free_queue, "pmeg_free_queue");
  2789.         Debugger("Pmap");
  2790.     }
  2791.     return 0;
  2792. }
  2793. #endif    CHECK
  2794.  
  2795. #if    PARANOIA
  2796. #include <vm/vm_page.h>
  2797. #include <vm/vm_object.h>
  2798. static ppg_cksum(), ppg_all0();
  2799. static int ppg_save_index = 0;
  2800.  
  2801. int ppg_index = 0;
  2802. int ppg_on = 0;
  2803.  
  2804. struct ppg_stat
  2805.        {
  2806.     vm_offset_t    va;
  2807.     vm_offset_t    pa;
  2808.     int        cksum;
  2809.     int        attr;
  2810.     int        pme;
  2811.        }         ppg_stat[101];
  2812.  
  2813. ppg_out(va, pa)
  2814. {
  2815.     register int            i;
  2816.     register struct ppg_stat    *ppgp;
  2817.  
  2818.     if (!current_thread() || !vm_page_array || !ppg_on)
  2819.         return;
  2820.  
  2821.     for (i = 0; i < ppg_index; i++) {
  2822.         if (ppg_stat[i].va == va)
  2823.             ppg_save_index = i;
  2824.             break;
  2825.     }
  2826.     ppgp = &ppg_stat[i];
  2827.     ppgp->va = va;
  2828.     ppgp->pa = pa;
  2829.     ppgp->cksum = ppg_cksum((int *)va);
  2830.     ppgp->pme = getpagemap(-1, va);
  2831.  
  2832. }
  2833.  
  2834. ppg_attr(va, epa)
  2835. {
  2836.     register int    i = ppg_save_index;
  2837.  
  2838.     if (!current_thread() || !vm_page_array || !ppg_on)
  2839.         return;
  2840.  
  2841.     if (va != ppg_stat[i].va) {
  2842.         printf("ppg_stat = %x\n", &ppg_stat[i]);
  2843.         panic("ppg_attr");
  2844.     }
  2845.  
  2846.     ppg_stat[i].attr = phys_attributes[pa_index(epa)];
  2847.  
  2848.     if (ppg_index < 100)
  2849.         ppg_index++;
  2850. }
  2851.  
  2852. ppg_in(va, pa)
  2853. {
  2854.     register int            i;
  2855.     register int            sum;
  2856.     register struct ppg_stat    *ppgp;
  2857.  
  2858.     if (!current_thread() || !vm_page_array || !ppg_on || !ppg_index)
  2859.         return;
  2860.  
  2861.     sum = ppg_cksum((int*)va);
  2862.  
  2863.     for (i = 0; i < ppg_index; i++)
  2864.         if (ppg_stat[i].va == va && ppg_stat[i].cksum != sum) {
  2865.             ppgp = &ppg_stat[i];
  2866.             printf("ppg_in %x: va %x, opa %x, pa %x, owd %x wd %x\n",
  2867.                 &ppg_stat[i], va, ppgp->pa, pa, ppgp->cksum, sum);
  2868.             printf("ppg_in: zero = %x\n", ppg_all0((int*)va));
  2869.             printf("attributes = %x, pme = %x\n",
  2870.                 ppgp->attr, ppgp->pme);
  2871.             Debugger("Pmap");
  2872.             return;
  2873.         }
  2874. }
  2875.  
  2876. static ppg_cksum(vp)
  2877.     register int    *vp;
  2878. {
  2879.     register int    i;
  2880.     register int    sum;
  2881.  
  2882.     for (i = 0, sum = 0; i < 2048; i++)
  2883.         sum += *vp++;
  2884.     return sum;
  2885. }
  2886.  
  2887. static ppg_all0(vp)
  2888.     register int    *vp;
  2889. {
  2890.     register int    i;
  2891.  
  2892.     for (i = 0; i < 2048; i++)
  2893.         if (*vp++)
  2894.             return 0;
  2895.     return 1;
  2896. }
  2897. #endif    PARANOIA
  2898.