Annotation of kernel/machdep/i386/pmap.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:  * Copyright (c) 1992 NeXT Computer, Inc.
                     27:  *
                     28:  * Intel386 Family:    Hardware page mapping.
                     29:  *
                     30:  * HISTORY
                     31:  *
                     32:  * 9 April 1992 ? at NeXT
                     33:  *     Created.
                     34:  */
                     35:  
                     36: #import <cpus.h>
                     37: 
                     38: #import <mach/mach_types.h>
                     39: 
                     40: #import <vm/vm_kern.h>
                     41: #import <vm/vm_page.h>
                     42: 
                     43: #import <machdep/i386/pmap_private.h>
                     44: #import <machdep/i386/pmap_inline.h>
                     45: #import <machdep/i386/cpu_inline.h>
                     46: 
                     47: /*
                     48:  * Setup structures to map from mach vm_prot_t
                     49:  * to machine protections.
                     50:  */
                     51: unsigned int                   user_prot_codes[8];
                     52: unsigned int                   kernel_prot_codes[8];
                     53: #define kernel_pmap_prot(x)    (kernel_prot_codes[(x)])
                     54: 
                     55: static
                     56: void
                     57: pte_prot_init(
                     58:     void
                     59: )
                     60: {
                     61:     unsigned int       *kp, *up;
                     62:     int                        prot;
                     63: 
                     64:     kp = kernel_prot_codes;
                     65:     up = user_prot_codes;
                     66:     for (prot = 0; prot < 8; prot++) {
                     67:        switch ((vm_prot_t)prot) {
                     68:        case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
                     69:            *kp++ = 0;
                     70:            *up++ = 0;
                     71:            break;
                     72:        case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
                     73:        case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
                     74:        case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
                     75:            *kp++ = PT_PROT_KR;
                     76:            *up++ = PT_PROT_UR;
                     77:            break;
                     78:        case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
                     79:        case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
                     80:        case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
                     81:        case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
                     82:            *kp++ = PT_PROT_KRW;
                     83:            *up++ = PT_PROT_URW;
                     84:            break;
                     85:        }
                     86:     }
                     87: }
                     88: 
                     89: /*
                     90:  * Given a map and a machine independent protection code,
                     91:  * set the protection code in the given pte
                     92:  */
                     93: static inline
                     94: void
                     95: pte_prot(
                     96:     pmap_t             pmap,
                     97:     vm_prot_t          prot,
                     98:     int                        valid,          /* valid bit for pte */
                     99:     pt_entry_t *       pte             /* IN/OUT */
                    100: )
                    101: {
                    102:     if (pmap == kernel_pmap)
                    103:        pte->prot = kernel_prot_codes[prot];
                    104:     else
                    105:        pte->prot = user_prot_codes[prot];
                    106: 
                    107:     pte->valid = valid;
                    108: }
                    109: 
                    110: /*
                    111:  * Return a ptr to the page
                    112:  * table entry at the indicated
                    113:  * offset in the pmap.  Return
                    114:  * PT_ENTRY_NULL if the page table
                    115:  * does not exist.
                    116:  */
                    117: inline
                    118: pt_entry_t *
                    119: pmap_pt_entry(
                    120:     pmap_t             pmap,
                    121:     vm_offset_t                va
                    122: )
                    123: {
                    124:     pd_entry_t *       pde;
                    125:     
                    126:     pde = pd_to_pd_entry(pmap->root, va);
                    127:     
                    128:     if (!pde->valid)
                    129:        return (PT_ENTRY_NULL);
                    130:        
                    131:     return (pd_entry_to_pt_entry(pde, va));
                    132: }
                    133: 
                    134: /*
                    135:  * Return a ptr to the page
                    136:  * directory entry at the indicated
                    137:  * offset in the pmap.
                    138:  */
                    139: inline
                    140: pd_entry_t *
                    141: pmap_pd_entry(
                    142:     pmap_t             pmap,
                    143:     vm_offset_t                va
                    144: )
                    145: {
                    146:     return (pd_to_pd_entry(pmap->root, va));
                    147: }
                    148: 
                    149: /*
                    150:  * Return the physical address
                    151:  * corresponding to the indicated
                    152:  * offset in the pmap.  Only used
                    153:  * internally since no locking is
                    154:  * done.
                    155:  */
                    156: static inline
                    157: unsigned int
                    158: pmap_phys(
                    159:     pmap_t             pmap,
                    160:     vm_offset_t                va
                    161: )
                    162: {
                    163:     pt_entry_t         *pte;
                    164:     
                    165:     pte = pmap_pt_entry(pmap, va);
                    166:     if (pte == PT_ENTRY_NULL || !pte->valid)
                    167:        return (0);
                    168:            
                    169:     return (pfn_to_phys(pte->pfn) + page_offset(va));
                    170: }
                    171: 
                    172: static inline
                    173: void
                    174: pmap_update_tlbs(
                    175:     pmap_t             pmap,
                    176:     vm_offset_t                start,
                    177:     vm_offset_t                end
                    178: )
                    179: {
                    180:     if (pmap == kernel_pmap || pmap->cpus_using) {
                    181:        tlb_stat.total++;
                    182:        if (end - start > PAGE_SIZE)
                    183:            flush_tlb();
                    184:        else {
                    185:            for (; start < end; start += I386_PGBYTES)
                    186:                invlpg(start, pmap == kernel_pmap);
                    187:          
                    188:            tlb_stat.single++;
                    189:        }
                    190:     }
                    191: }
                    192: 
                    193: /*
                    194:  * Allocate a new page table
                    195:  * in the kernel pmap at the
                    196:  * given offset when one does
                    197:  * not already exist.
                    198:  */
                    199: static
                    200: void
                    201: pmap_kernel_pt_alloc(
                    202:     vm_offset_t                addr
                    203: )
                    204: {
                    205:     pd_entry_t         template, *pde;
                    206:     vm_offset_t                pt;
                    207:     unsigned int       phys;
                    208:     int                        i;
                    209:     
                    210:     pde = pmap_pd_entry(kernel_pmap, trunc_section(addr));
                    211:     if (pde->valid)
                    212:        panic("pmap_kernel_pt_alloc");
                    213:        
                    214:     if (!pmap_initialized) {
                    215:        pt = alloc_pages(PAGE_SIZE);
                    216:        if (!pt)
                    217:            panic("pmap_kernel_pt_alloc 2");
                    218: 
                    219:        bzero(pt, PAGE_SIZE);
                    220: 
                    221:        phys = pt - VM_MIN_KERNEL_ADDRESS;      
                    222:     }
                    223:     else {
                    224:        if (kmem_alloc_wired(kernel_map, &pt, PAGE_SIZE) != KERN_SUCCESS)
                    225:            panic("pmap_kernel_pt_alloc 3");
                    226:            
                    227:        phys = pmap_phys(kernel_pmap, pt);
                    228:     }
                    229:     
                    230:     template = (pd_entry_t) { 0 };
                    231:     template.valid = 1;
                    232:     template.prot = PT_PROT_KRW;
                    233:     template.pfn = phys_to_pfn(phys);
                    234:     
                    235:     for (i = ptes_per_vm_page; i-- > 0; pde++) {
                    236:        *pde = template;
                    237:        template.pfn++;
                    238:     }
                    239: }
                    240: 
                    241: /*
                    242:  * Map memory at initialization.  The physical addresses being
                    243:  * mapped are not managed and are never unmapped.
                    244:  */
                    245: vm_offset_t
                    246: pmap_map(
                    247:     vm_offset_t                virt,
                    248:     vm_offset_t                start,
                    249:     vm_offset_t                end,
                    250:     vm_prot_t          prot
                    251: )
                    252: {
                    253:     pt_entry_t         template, *pte;
                    254:     
                    255:     template = (pt_entry_t) { 0 };
                    256: 
                    257:     if (prot != VM_PROT_NONE) {
                    258:        template.valid = 1;
                    259:        template.prot =  kernel_pmap_prot(prot);
                    260:        template.pfn = phys_to_pfn(start);
                    261:     }
                    262: 
                    263:     while (start < end) {
                    264:        pte = pmap_pt_entry(kernel_pmap, virt);
                    265:        if (pte == PT_ENTRY_NULL) {
                    266:            pmap_kernel_pt_alloc(virt);
                    267:            pte = pmap_pt_entry(kernel_pmap, virt);
                    268:        }
                    269: 
                    270:        /*
                    271:         * Is this necessary ??
                    272:         */     
                    273:        if (    start >= (640 * 1024) &&
                    274:                start < (1024 * 1024))
                    275:            template.cachewrt = 1;
                    276:        else
                    277:            template.cachewrt = 0;
                    278:        
                    279:        *pte = template;
                    280:        if (prot != VM_PROT_NONE)
                    281:            template.pfn++;
                    282: 
                    283:        virt += I386_PGBYTES;
                    284:        start += I386_PGBYTES;
                    285:     }
                    286: 
                    287:     flush_tlb();
                    288: 
                    289:     return (virt);
                    290: }
                    291: 
                    292: static
                    293: void
                    294: pmap_enable_pg(
                    295:     vm_offset_t                kernel_pd
                    296: )
                    297: {
                    298:     pd_entry_t         *kpde, *end_kpde;
                    299:     pd_entry_t         *pde;
                    300:     cr0_t              _cr0 = cr0();
                    301: 
                    302:     /*
                    303:      * Double map the kernel memory
                    304:      * into the low end of the kernel
                    305:      * pmap linear space.  This is
                    306:      * necessary in order to enable
                    307:      * paging.
                    308:      */
                    309:     pde = (pd_entry_t *)kernel_pd;
                    310: 
                    311:     kpde =
                    312:        pmap_pd_entry(kernel_pmap,
                    313:                        VM_MIN_KERNEL_ADDRESS);
                    314:     end_kpde =
                    315:        pmap_pd_entry(kernel_pmap,
                    316:                        VM_MAX_KERNEL_ADDRESS);
                    317:                        
                    318:     while (kpde < end_kpde)
                    319:        *pde++ = *kpde++;
                    320: 
                    321:     /*
                    322:      * Use the kernel pmap
                    323:      * as our initial translation
                    324:      * tree.
                    325:      */ 
                    326:     kernel_pmap->cr3 =
                    327:            pmap_phys(kernel_pmap, kernel_pd);
                    328:     
                    329:     set_cr3(kernel_pmap->cr3);
                    330: 
                    331:     /*
                    332:      * Now, enable paging by
                    333:      * turning on the PG bit
                    334:      * in CR0.  Also turn on
                    335:      * the WP bit to allow
                    336:      * the write protecting of
                    337:      * memory with repect to
                    338:      * the kernel.
                    339:      */ 
                    340:     _cr0.pg = _cr0.wp = TRUE;
                    341:     set_cr0(_cr0);
                    342: }
                    343: 
                    344: /*
                    345:  */
                    346: void
                    347: pmap_bootstrap(
                    348:     mem_region_t       mem_region,
                    349:     int                        num_regions,
                    350:     vm_offset_t *      virt_avail,     /* OUT */
                    351:     vm_offset_t *      virt_end        /* OUT */
                    352: )
                    353: {
                    354:     vm_offset_t                va;
                    355:     unsigned int       phys_end = mem_region[0].last_phys_addr;
                    356:     vm_offset_t                kernel_pd;
                    357:     
                    358:     /*
                    359:      * Setup section_size variable.
                    360:      */
                    361:     section_size = SECTION_SIZE;
                    362:        
                    363:     /*
                    364:      * Set ptes_per_vm_page for general use.
                    365:      */
                    366:     ptes_per_vm_page = PAGE_SIZE / I386_PGBYTES;
                    367: 
                    368:     /*
                    369:      * Initialize pte protection arrays.
                    370:      */
                    371:     pte_prot_init();
                    372: 
                    373:     /*
                    374:      * The kernel's pmap is statically allocated so we don't
                    375:      * have to use pmap_create, which does not work
                    376:      * correctly at this part of the boot sequence.
                    377:      */
                    378:     kernel_pmap = &kernel_pmap_store;
                    379: 
                    380:     simple_lock_init(&kernel_pmap->lock);
                    381: 
                    382:     /*
                    383:      * Allocate a page directory for the
                    384:      * kernel pmap.
                    385:      */
                    386:     (vm_offset_t)kernel_pmap->root =
                    387:            kernel_pd = alloc_cnvmem(I386_PGBYTES, I386_PGBYTES);
                    388: 
                    389:     bzero((vm_offset_t)kernel_pmap->root, I386_PGBYTES);
                    390: 
                    391:     kernel_pmap->ref_count = 1;
                    392: 
                    393:     kernel_pmap->root +=
                    394:        (KERNEL_LINEAR_BASE - VM_MIN_KERNEL_ADDRESS) / I386_SECTBYTES;
                    395:     
                    396:     /*
                    397:      * Map all physical memory V == P.
                    398:      */
                    399:     va = pmap_map(VM_MIN_KERNEL_ADDRESS,
                    400:                  0,
                    401:                  phys_end,
                    402:                  VM_PROT_READ | VM_PROT_WRITE);
                    403: 
                    404:     /*
                    405:      * Allocate additional kernel page tables
                    406:      * needed for allocating kernel virtual memory later.
                    407:      */
                    408:     *virt_avail = va;
                    409:      va = pmap_map(va,
                    410:                   0,
                    411:                   64*1024*1024 +       /* base size */
                    412:                   zone_map_sizer() +   /* zone allocator */
                    413:                   buffer_map_sizer(),  /* buffer cache */
                    414:                   VM_PROT_NONE);
                    415:                   
                    416:     *virt_end = va;
                    417: 
                    418:     /*
                    419:      * Finish initialization
                    420:      * of the kernel pmap, and
                    421:      * then enable paging.
                    422:      */
                    423:     pmap_enable_pg(kernel_pd);
                    424: }
                    425: 
                    426: /*
                    427:  * Initialize the pmap module.
                    428:  * Called by vm_init, to initialize any structures that the pmap
                    429:  * system needs to map virtual memory.
                    430:  */
                    431: void
                    432: pmap_init(
                    433:     mem_region_t       mem_region,
                    434:     int                        num_regions
                    435: )
                    436: {
                    437:     unsigned int       phys_start, phys_end;
                    438:     int                        npages;
                    439:     vm_size_t          s;
                    440: 
                    441:     phys_start = mem_region[0].first_phys_addr;
                    442:     phys_end   = mem_region[0].last_phys_addr;
                    443: 
                    444:     npages     = mem_region[0].num_pages;
                    445: 
                    446:     /*
                    447:      * Allocate memory for the page descriptor
                    448:      * table.
                    449:      */
                    450:     s = sizeof(struct pg_desc) * npages;
                    451:     (void) kmem_alloc_wired(kernel_map, (vm_offset_t *)&pg_desc_tbl, s);
                    452:     pg_first_phys = phys_start;
                    453: 
                    454:     /*
                    455:      * Create the zone of physical maps,
                    456:      * and of the physical-to-virtual entries.
                    457:      */
                    458:     s = sizeof (struct pmap);
                    459:     pmap_zone = zinit(s, 400*s, 0, FALSE, "pmap");             /* XXX */
                    460: 
                    461:     s = sizeof (struct pv_entry);
                    462:     pv_entry_zone = zinit(s, 10000*s, 0, FALSE, "pv_entry");   /* XXX */
                    463:     
                    464:     /*
                    465:      * Create the zone of page
                    466:      * extensions.
                    467:      */
                    468:     s = sizeof (struct pg_exten);
                    469:     pg_exten_zone = zinit(s, npages*s, 0, FALSE, "pg_exten");
                    470: 
                    471:     /*
                    472:      * Initialize the queues of active and
                    473:      * free page tables and free page directories.
                    474:      */        
                    475:     queue_init(&pt_active_queue);
                    476:     queue_init(&pt_free_queue);
                    477:     queue_init(&pd_free_queue);
                    478: 
                    479:     /*
                    480:      * Only now, when all of the data structures are allocated,
                    481:      * can we set vm_first_phys and vm_last_phys.  If we set them
                    482:      * too soon, the kmem_alloc above will try to use these
                    483:      * data structures and blow up.
                    484:      */
                    485: 
                    486:     vm_first_phys      = phys_start;
                    487:     vm_last_phys       = phys_end;
                    488: 
                    489:     pmap_initialized = TRUE;
                    490: }
                    491: 
                    492: static
                    493: pg_exten_t *
                    494: pg_exten_alloc(
                    495:     vm_offset_t                page
                    496: )
                    497: {
                    498:     pg_exten_t         *pe;
                    499:     pg_desc_t          *pd;
                    500:         
                    501:     (vm_offset_t)pe = zalloc(pg_exten_zone);
                    502:     
                    503:     pe->phys = pmap_phys(kernel_pmap, page);
                    504:     
                    505:     pd = pg_desc(pe->phys);
                    506: 
                    507:     pd->pg_exten = pe; pe->pg_desc = pd;
                    508:     
                    509:     pe->alloc_count = pe->wired_count = pe->unrefd_age = pe->alloc_bmap = 0;
                    510:     
                    511:     return (pe);
                    512: }
                    513: 
                    514: static
                    515: void
                    516: pg_exten_free(
                    517:     pg_exten_t         *pe
                    518: )
                    519: {
                    520:     pe->pg_desc->pg_exten = PG_EXTEN_NULL;
                    521:     
                    522:     zfree(pg_exten_zone, (vm_offset_t)pe);
                    523: }
                    524: 
                    525: static
                    526: void
                    527: pmap_alloc_pd(
                    528:     pmap_t             pmap
                    529: )
                    530: {
                    531:     pg_exten_t         *pe;
                    532:     int                        i;
                    533:    
                    534:     if (pe = pd_free_obtain()) {
                    535:        if (++pe->alloc_count == ptes_per_vm_page)
                    536:            pd_free_remove(pe);
                    537: 
                    538:        i = ffs(~pe->alloc_bmap) - 1;
                    539:        pe->alloc_bmap |= (1 << i);
                    540: 
                    541:        (vm_offset_t)pmap->root = pe->pg_desc->pv_list.va + (I386_PGBYTES * i);
                    542:     }
                    543:     else {
                    544:        if (kmem_alloc_wired(kernel_map,
                    545:                        (vm_offset_t *)&pmap->root, PAGE_SIZE) != KERN_SUCCESS)
                    546:            panic("pmap_alloc_pd");
                    547: 
                    548:        pd_alloc_count++;
                    549:        
                    550:        pe = pg_exten_alloc((vm_offset_t)pmap->root);
                    551: 
                    552:        if (++pe->alloc_count < ptes_per_vm_page)
                    553:            pd_free_add(pe);
                    554: 
                    555:        pe->alloc_bmap |= 1;
                    556:     }
                    557: }
                    558: 
                    559: static
                    560: void
                    561: pmap_free_pd(
                    562:     pmap_t             pmap
                    563: )
                    564: {
                    565:     pg_exten_t         *pe;
                    566:     pg_desc_t          *pd;
                    567:     int                        i;
                    568:     
                    569:     pd = pg_desc(pmap_phys(kernel_pmap, (vm_offset_t)pmap->root));
                    570:     
                    571:     pe = pd->pg_exten;
                    572: 
                    573:     if (pe->alloc_count-- == ptes_per_vm_page)
                    574:        pd_free_add(pe);
                    575: 
                    576:     i = ((vm_offset_t)pmap->root - pd->pv_list.va) / I386_PGBYTES;
                    577: 
                    578:     pe->alloc_bmap &= ~(1 << i);
                    579: }
                    580: 
                    581: /*
                    582:  * Allocate and setup the page directory
                    583:  * for a new pmap.  The pd_entries that
                    584:  * correspond to the kernel address space
                    585:  * are initialized by copying them from
                    586:  * the kernel pmap.  This works correctly
                    587:  * since we never expand the kernel pmap.
                    588:  */
                    589: static
                    590: void
                    591: pmap_create_pd(
                    592:     pmap_t             pmap
                    593: )
                    594: {
                    595:     pd_entry_t         *pde;
                    596:     pd_entry_t         *kpde, *end_kpde;
                    597:     
                    598:     pmap_alloc_pd(pmap);
                    599:     
                    600:     if (pmap->root == PD_ENTRY_NULL)
                    601:        panic("pmap_create_page_directory");
                    602:     
                    603:     if (i386_trunc_page(pmap->root) != (vm_offset_t)pmap->root)
                    604:        panic("pmap_create_page_directory 1");
                    605:     
                    606:     pmap->cr3 = pmap_phys(kernel_pmap, (vm_offset_t)pmap->root);
                    607:        
                    608:     kpde =
                    609:        pmap_pd_entry(kernel_pmap,
                    610:                        VM_MIN_KERNEL_ADDRESS);
                    611:     end_kpde =
                    612:        pmap_pd_entry(kernel_pmap,
                    613:                        VM_MAX_KERNEL_ADDRESS);
                    614:                    
                    615:     pde = pmap_pd_entry(pmap, KERNEL_LINEAR_BASE);
                    616:     
                    617:     while (kpde < end_kpde)
                    618:        *pde++ = *kpde++;
                    619: }
                    620: 
                    621: /*
                    622:  * Create and return a physical map.
                    623:  *
                    624:  * If the size specified for the map
                    625:  * is zero, the map is an actual physical
                    626:  * map, and may be referenced by the
                    627:  * hardware.
                    628:  *
                    629:  * If the size specified is non-zero,
                    630:  * the map will be used in software only, and
                    631:  * is bounded by that size.
                    632:  */
                    633: pmap_t
                    634: pmap_create(
                    635:     vm_size_t          size
                    636: )
                    637: {
                    638:     pmap_t             pmap;
                    639: 
                    640:     /*
                    641:      * A software use-only map doesn't even need a pmap.
                    642:      */
                    643:     if (size != 0)
                    644:        return (PMAP_NULL);
                    645: 
                    646:     /*
                    647:      * Allocate a pmap struct from the pmap_zone.
                    648:      */
                    649:     pmap = (pmap_t) zalloc(pmap_zone);
                    650:     if (pmap == PMAP_NULL)
                    651:        panic("pmap_create pmap");
                    652: 
                    653:     bzero((vm_offset_t)pmap, sizeof (struct pmap));
                    654: 
                    655:     /*
                    656:      * Create the page directory.
                    657:      */
                    658:     pmap_create_pd(pmap);
                    659: 
                    660:     pmap->ref_count = 1;
                    661: 
                    662:     simple_lock_init(&pmap->lock);
                    663:        
                    664:     return (pmap);
                    665: }
                    666: 
                    667: /*
                    668:  * Retire the given physical map from service.
                    669:  * Should only be called if the map contains
                    670:  * no valid mappings.
                    671:  */
                    672: void
                    673: pmap_destroy(
                    674:     pmap_t             pmap
                    675: )
                    676: {
                    677:     int                        c, s;
                    678: 
                    679:     if (pmap == PMAP_NULL)
                    680:        return;
                    681: 
                    682:     SPLVM(s);
                    683:     simple_lock(&pmap->lock);
                    684: 
                    685:     c = --pmap->ref_count;
                    686: 
                    687:     simple_unlock(&pmap->lock);
                    688:     SPLX(s);
                    689: 
                    690:     if (c != 0)
                    691:        return;
                    692: 
                    693:     pmap_free_pd(pmap);
                    694: 
                    695:     zfree(pmap_zone, (vm_offset_t)pmap);
                    696: }
                    697: 
                    698: /*
                    699:  *     Add a reference to the specified pmap.
                    700:  */
                    701: 
                    702: void
                    703: pmap_reference(
                    704:     pmap_t             pmap
                    705: )
                    706: {
                    707:     int                        s;
                    708: 
                    709:     if (pmap != PMAP_NULL) {
                    710:        SPLVM(s);
                    711:        simple_lock(&pmap->lock);
                    712: 
                    713:        pmap->ref_count++;
                    714: 
                    715:        simple_unlock(&pmap->lock);
                    716:        SPLX(s);
                    717:     }
                    718: }
                    719: 
                    720: /*
                    721:  * Remove a range of mappings from
                    722:  * a pmap.  The indicated range must
                    723:  * lie completely within one section,
                    724:  * i.e. the ptes must be within one
                    725:  * page table.
                    726:  */
                    727: static
                    728: void
                    729: pmap_remove_range(
                    730:     pmap_t             pmap,
                    731:     vm_offset_t                start,
                    732:     vm_offset_t                end,
                    733:     boolean_t          free_table
                    734: )
                    735: {
                    736:     pt_entry_t         *pte, *epte;
                    737:     pg_desc_t          *pd;
                    738:     pv_entry_t         pv_h;
                    739:     pv_entry_t         cur, prev;
                    740:     unsigned int       pa;
                    741:     vm_offset_t                va = start;
                    742:     int                        i, num_removed = 0, num_unwired = 0;
                    743:     
                    744:     if ((pte = pmap_pt_entry(pmap, start)) == PT_ENTRY_NULL)
                    745:        return;
                    746:        
                    747:     epte = pmap_pt_entry(pmap, end);
                    748:     if (trunc_page(pte) != trunc_page(epte))
                    749:        epte = (pt_entry_t *)round_page(pte + ptes_per_vm_page);
                    750:     
                    751:     for (; pte < epte; va += PAGE_SIZE) {
                    752:        if (!pte->valid) {
                    753:            pte += ptes_per_vm_page;
                    754:            continue;
                    755:        }
                    756:            
                    757:        num_removed++;
                    758:        if (pte->wired)
                    759:            num_unwired++;
                    760:            
                    761:        pa = pfn_to_phys(pte->pfn);
                    762:        if (!managed_page(pa)) {
                    763:            for (i = ptes_per_vm_page; i-- > 0; pte++)
                    764:                *pte = (pt_entry_t) { 0 };
                    765:            continue;
                    766:        }
                    767:            
                    768:        pd = pg_desc(pa);
                    769:        LOCK_PVH(pd);
                    770:        
                    771:        /*
                    772:         * Collect the referenced & dirty bits
                    773:         * and clear the mapping.
                    774:         */
                    775:        for (i = ptes_per_vm_page; i-- > 0; pte++) {
                    776:            if (pte->dirty) {
                    777:                vm_page_t       m = PHYS_TO_VM_PAGE(pa);
                    778:                
                    779:                vm_page_set_modified(m);
                    780:                pd->page_attrib |= PG_DIRTY;
                    781:            }
                    782:            
                    783:            if (pte->refer)
                    784:                pd->page_attrib |= PG_REFER;
                    785:                
                    786:            *pte = (pt_entry_t) { 0 };
                    787:        }
                    788: 
                    789:        /*
                    790:         * Remove the mapping from the pvlist for
                    791:         * this physical page.
                    792:         */
                    793:        pv_h = pg_desc_pvh(pd);
                    794:        if (pv_h->pmap == PMAP_NULL)
                    795:            panic("pmap_remove_range");
                    796: 
                    797:        if (pv_h->va == va && pv_h->pmap == pmap) {
                    798:            /*
                    799:             * Header is the pv_entry.  Copy the next one
                    800:             * to header and free the next one (we can't
                    801:             * free the header)
                    802:             */
                    803:            cur = pv_h->next;
                    804:            if (cur != PV_ENTRY_NULL) {
                    805:                *pv_h = *cur;
                    806:                zfree(pv_entry_zone, (vm_offset_t) cur);
                    807:            }
                    808:            else
                    809:                pv_h->pmap = PMAP_NULL;
                    810:        }
                    811:        else {
                    812:            prev = pv_h;
                    813:            while ((cur = prev->next) != PV_ENTRY_NULL) {
                    814:                if (cur->va == va && cur->pmap == pmap)
                    815:                    break;
                    816:                prev = cur;
                    817:            }
                    818:            if (cur == PV_ENTRY_NULL)
                    819:                panic("pmap_remove_range 2");
                    820: 
                    821:            prev->next = cur->next;
                    822:            zfree(pv_entry_zone, (vm_offset_t) cur);
                    823:        }
                    824:        
                    825:        UNLOCK_PVH(pd);
                    826:     }
                    827: 
                    828:     /*
                    829:      * Free the mappings from the page table.
                    830:      */        
                    831:     pmap_deallocate_mappings(
                    832:                            pmap, start,
                    833:                            num_removed, num_unwired, free_table);
                    834: }
                    835: 
                    836: /*
                    837:  * Remove the given range of addresses
                    838:  * from the specified pmap.
                    839:  *
                    840:  * It is assumed that the start and end are properly
                    841:  * rounded to the page size.
                    842:  */
                    843: void
                    844: pmap_remove(
                    845:     pmap_t             pmap,
                    846:     vm_offset_t                start,
                    847:     vm_offset_t                end
                    848: )
                    849: {
                    850:     vm_offset_t                sect_end;
                    851:     int                        s;
                    852: 
                    853:     if (pmap == PMAP_NULL)
                    854:        return;
                    855: 
                    856:     PMAP_READ_LOCK(pmap, s);
                    857: 
                    858:     /*
                    859:      * Invalidate the translation buffer first
                    860:      */
                    861:     PMAP_UPDATE_TLBS(pmap, start, end);
                    862:     
                    863:     while (start < end) {
                    864:        sect_end = round_section(start + PAGE_SIZE);
                    865:        if (sect_end > end)
                    866:            sect_end = end;
                    867: 
                    868:        pmap_remove_range(pmap, start, sect_end, TRUE);
                    869:        start = sect_end;
                    870:     }
                    871: 
                    872:     PMAP_READ_UNLOCK(pmap, s);
                    873: }
                    874: 
                    875: /*
                    876:  * Remove all references to 
                    877:  * the indicated page from
                    878:  * all pmaps.
                    879:  */
                    880: void
                    881: pmap_remove_all(
                    882:     unsigned int       pa
                    883: )
                    884: {
                    885:     pt_entry_t         *pte;
                    886:     pv_entry_t         pv_h, cur;
                    887:     pg_desc_t          *pd;
                    888:     vm_offset_t                va;
                    889:     pmap_t             pmap;
                    890:     int                        s, i;
                    891:     
                    892:     if (!managed_page(pa))
                    893:        return;
                    894: 
                    895:     /*
                    896:      * Lock the pmap system first, since we will be changing
                    897:      * several pmaps.
                    898:      */
                    899:     PMAP_WRITE_LOCK(s);
                    900:     
                    901:     /*
                    902:      * Walk down PV list, removing all mappings.
                    903:      * We have to do the same work as in pmap_remove_range
                    904:      * since that routine locks the pv_head.  We don't have
                    905:      * to lock the pv_head, since we have the entire pmap system.
                    906:      */
                    907:     pd = pg_desc(pa);
                    908:     pv_h = pg_desc_pvh(pd);
                    909:     
                    910:     while ((pmap = pv_h->pmap) != PMAP_NULL) {
                    911:        va = pv_h->va;
                    912: 
                    913:        simple_lock(&pmap->lock);
                    914: 
                    915:        pte = pmap_pt_entry(pmap, va);
                    916:        if (pte == PT_ENTRY_NULL || !pte->valid)
                    917:            panic("pmap_remove_all");
                    918:            
                    919:        if (pfn_to_phys(pte->pfn) != pa)
                    920:            panic("pmap_remove_all 2");
                    921:            
                    922:        if (pte->wired)
                    923:            panic("pmap_remove_all 3");
                    924:        
                    925:        /*
                    926:         * Tell CPU using pmap to invalidate its TLB
                    927:         */
                    928:        PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
                    929: 
                    930:        if ((cur = pv_h->next) != PV_ENTRY_NULL) {
                    931:            *pv_h = *cur;
                    932:            zfree(pv_entry_zone, (vm_offset_t) cur);
                    933:        }
                    934:        else
                    935:            pv_h->pmap = PMAP_NULL;     
                    936:        
                    937:        /*
                    938:         * Collect the referenced & dirty bits
                    939:         * and clear the mapping.
                    940:         */
                    941:        for (i = ptes_per_vm_page; i-- > 0; pte++) {
                    942:            if (pte->dirty) {
                    943:                vm_page_t       m = PHYS_TO_VM_PAGE(pa);
                    944:                
                    945:                vm_page_set_modified(m);
                    946:                pd->page_attrib |= PG_DIRTY;
                    947:            }
                    948:            
                    949:            if (pte->refer)
                    950:                pd->page_attrib |= PG_REFER;
                    951:                
                    952:            *pte = (pt_entry_t) { 0 };
                    953:        }
                    954:        
                    955:        pmap_deallocate_mappings(pmap, va, 1, 0, TRUE);
                    956:        
                    957:        simple_unlock(&pmap->lock);
                    958:     }
                    959:     
                    960:     PMAP_WRITE_UNLOCK(s);
                    961: }
                    962: 
                    963: /*
                    964:  * Remove write access to the
                    965:  * indicated page from all pmaps.
                    966:  */
                    967: void
                    968: pmap_copy_on_write(
                    969:     unsigned int       pa
                    970: )
                    971: {
                    972:     pt_entry_t         *pte;
                    973:     pv_entry_t         pv_e;
                    974:     int                        i, s;
                    975: 
                    976:     if (!managed_page(pa))
                    977:        return;
                    978:        
                    979:     /*
                    980:      * Lock the entire pmap system, since we may be changing
                    981:      * several maps.
                    982:      */
                    983:     PMAP_WRITE_LOCK(s);
                    984:     
                    985:     pv_e = pg_desc_pvh(pg_desc(pa));
                    986:     if (pv_e->pmap == PMAP_NULL) {
                    987:        PMAP_WRITE_UNLOCK(s);
                    988:        return;
                    989:     }    
                    990: 
                    991:     /*
                    992:      * Run down the list of mappings to this physical page,
                    993:      * disabling write privileges on each one.
                    994:      */
                    995:     while (pv_e != PV_ENTRY_NULL) {
                    996:        pmap_t          pmap;
                    997:        vm_offset_t     va;
                    998: 
                    999:        pmap = pv_e->pmap;
                   1000:        va = pv_e->va;
                   1001: 
                   1002:        simple_lock(&pmap->lock);
                   1003:        
                   1004:        pte = pmap_pt_entry(pmap, va);
                   1005:        
                   1006:        if (pte == PT_ENTRY_NULL || !pte->valid)
                   1007:            panic("pmap_copy_on_write");
                   1008: 
                   1009:        /*
                   1010:         * Ask cpus using pmap to invalidate their TLBs
                   1011:         */
                   1012:        PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
                   1013:        
                   1014:        if (pte->prot == PT_PROT_URW || pte->prot == PT_PROT_KRW)
                   1015:            for (i = ptes_per_vm_page; i-- > 0; pte++)
                   1016:                pte_prot(pmap, VM_PROT_READ, pte->valid, pte);
                   1017:            
                   1018:        simple_unlock(&pmap->lock);
                   1019:        
                   1020:        pv_e = pv_e->next;
                   1021:     }
                   1022:     
                   1023:     PMAP_WRITE_UNLOCK(s);
                   1024: }
                   1025: 
                   1026: /*
                   1027:  * Change the page protection
                   1028:  * on a range of addresses in
                   1029:  * the indicated pmap.  If protect
                   1030:  * is being changed to VM_PROT_NONE,
                   1031:  * remove the mappings.
                   1032:  */
                   1033: void
                   1034: pmap_protect(
                   1035:     pmap_t             pmap,
                   1036:     vm_offset_t                start,
                   1037:     vm_offset_t                end,
                   1038:     vm_prot_t          prot
                   1039: )
                   1040: {
                   1041:     pt_entry_t         *pte, *epte;
                   1042:     vm_offset_t                sect_end;
                   1043:     int                        i, s;
                   1044:     
                   1045:     if (pmap == PMAP_NULL)
                   1046:        return;
                   1047:        
                   1048:     if (prot == VM_PROT_NONE) {
                   1049:        pmap_remove(pmap, start, end);
                   1050:        return;
                   1051:     }
                   1052:     
                   1053:     SPLVM(s);
                   1054:     simple_lock(&pmap->lock);
                   1055: 
                   1056:     /*
                   1057:      * Invalidate the translation buffer first
                   1058:      */
                   1059:     PMAP_UPDATE_TLBS(pmap, start, end);    
                   1060:     
                   1061:     while (start < end) {
                   1062:        sect_end = round_section(start + PAGE_SIZE);
                   1063:        if (sect_end > end)
                   1064:            sect_end = end;
                   1065:            
                   1066:        pte = pmap_pt_entry(pmap, start);
                   1067:        if (pte != PT_ENTRY_NULL) {
                   1068:            epte = pmap_pt_entry(pmap, sect_end);
                   1069:            if (trunc_page(pte) != trunc_page(epte))
                   1070:                epte = (pt_entry_t *)round_page(pte + ptes_per_vm_page);
                   1071:                
                   1072:            while (pte < epte) {
                   1073:                if (!pte->valid) {
                   1074:                    pte += ptes_per_vm_page;
                   1075:                    continue;
                   1076:                }
                   1077:                
                   1078:                for (i = ptes_per_vm_page; i-- > 0; pte++)
                   1079:                    pte_prot(pmap, prot, pte->valid, pte);
                   1080:            }
                   1081:        }
                   1082: 
                   1083:        start = sect_end;
                   1084:     }
                   1085:     
                   1086:     simple_unlock(&pmap->lock);
                   1087:     SPLX(s);
                   1088: }
                   1089: 
                   1090: /*
                   1091:  * Insert the given physical page (p) at
                   1092:  * the specified virtual address (v) in the
                   1093:  * target physical map with the protection requested.
                   1094:  *
                   1095:  * If specified, the page will be wired down, meaning
                   1096:  * that the related pte can not be reclaimed.
                   1097:  *
                   1098:  * NB:  This is the only routine which MAY NOT lazy-evaluate
                   1099:  * or lose information.  That is, this routine must actually
                   1100:  * insert this page into the given map NOW.
                   1101:  */
                   1102: void inline
                   1103: pmap_enter_cache_spec(
                   1104:     pmap_t             pmap,
                   1105:     vm_offset_t                va,
                   1106:     vm_offset_t                pa,
                   1107:     vm_prot_t          prot,
                   1108:     boolean_t          wired,
                   1109:     cache_spec_t       caching
                   1110: )
                   1111: {
                   1112:     pt_entry_t         *pte;
                   1113:     pv_entry_t         pv_h;
                   1114:     pg_desc_t          *pd;
                   1115:     int                        i, s;
                   1116:     pv_entry_t         pv_e;
                   1117:     pt_entry_t         template;
                   1118:     vm_offset_t                old_pa;
                   1119:     
                   1120:     if (pmap == PMAP_NULL)
                   1121:        return;
                   1122:        
                   1123:     if (prot == VM_PROT_NONE) {
                   1124:        pmap_remove(pmap, va, va + PAGE_SIZE);
                   1125:        return;
                   1126:     }
                   1127: 
                   1128:     /*
                   1129:      * Must allocate a new pvlist entry while we're unlocked;
                   1130:      * zalloc may cause pageout (which will lock the pmap system).
                   1131:      * If we determine we need a pvlist entry, we will unlock
                   1132:      * and allocate one.  Then we will retry, throwing away
                   1133:      * the allocated entry later (if we no longer need it).
                   1134:      */
                   1135:     pv_e = PV_ENTRY_NULL;
                   1136:     template = (pt_entry_t) { 0 };
                   1137: 
                   1138: Retry:
                   1139:     PMAP_READ_LOCK(pmap, s);
                   1140: 
                   1141:     /*
                   1142:      * Expand pmap to include this pte.  Assume that
                   1143:      * pmap is always expanded to include enough
                   1144:      * pages to map one VM page.
                   1145:      */
                   1146:     while ((pte = pmap_pt_entry(pmap, va)) == PT_ENTRY_NULL) {
                   1147:        /*
                   1148:         * Must unlock to expand the pmap.
                   1149:         */
                   1150:        PMAP_READ_UNLOCK(pmap, s);
                   1151: 
                   1152:        pmap_expand(pmap, va);
                   1153: 
                   1154:        PMAP_READ_LOCK(pmap, s);
                   1155:     }
                   1156: 
                   1157:     /*
                   1158:      * Special case if the physical page is already mapped
                   1159:      * at this address.
                   1160:      */
                   1161:     old_pa = pfn_to_phys(pte->pfn);
                   1162:     if (pte->valid && old_pa == pa) {
                   1163:        /*
                   1164:         * May be changing its wired attribute or protection
                   1165:         */
                   1166:        if (wired && !pte->wired)
                   1167:            pmap_wire_mapping(pmap, va);
                   1168:        else
                   1169:        if (!wired && pte->wired)
                   1170:            pmap_unwire_mapping(pmap, va);
                   1171: 
                   1172:        pte_prot(pmap, prot, 1, &template);
                   1173:        template.pfn = phys_to_pfn(pa);
                   1174:        if (wired)
                   1175:            template.wired = 1;
                   1176:            
                   1177:        if (caching == cache_disable)
                   1178:            template.cachedis = 1;
                   1179:        else
                   1180:        if (caching == cache_writethrough)
                   1181:            template.cachewrt = 1;
                   1182: 
                   1183:        PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
                   1184:        
                   1185:        for (i = ptes_per_vm_page; i-- > 0; pte++) {
                   1186:            if (pte->dirty)
                   1187:                template.dirty = 1;
                   1188:            *pte = template;
                   1189:            template.pfn++;
                   1190:        }
                   1191:     }
                   1192:     else {
                   1193: 
                   1194:        /*
                   1195:         * Remove old mapping from the PV list if necessary.
                   1196:         */
                   1197:        if (pte->valid) {
                   1198:            /*
                   1199:             * Invalidate the translation buffer,
                   1200:             * then remove the mapping.
                   1201:             */
                   1202:            PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
                   1203:            
                   1204:            pmap_remove_range(pmap, va, va + PAGE_SIZE, FALSE);
                   1205:        }
                   1206:        
                   1207:        if (managed_page(pa)) {
                   1208: 
                   1209:            /*
                   1210:             * Enter the mapping in the PV list for this
                   1211:             * physical page.
                   1212:             */
                   1213:            pd = pg_desc(pa);
                   1214:            LOCK_PVH(pd);
                   1215:            pv_h = pg_desc_pvh(pd);
                   1216: 
                   1217:            if (pv_h->pmap == PMAP_NULL) {
                   1218: 
                   1219:                /*
                   1220:                 * No mappings yet
                   1221:                 */
                   1222:                pv_h->va = va;
                   1223:                pv_h->pmap = pmap;
                   1224:                pv_h->next = PV_ENTRY_NULL;
                   1225:            }
                   1226:            else {
                   1227:                    
                   1228:                /*
                   1229:                 * Add new pv_entry after header.
                   1230:                 */
                   1231:                if (pv_e == PV_ENTRY_NULL) {
                   1232:                    UNLOCK_PVH(pd);
                   1233:                    PMAP_READ_UNLOCK(pmap, s);
                   1234:                    pv_e = (pv_entry_t) zalloc(pv_entry_zone);
                   1235:                    goto Retry;
                   1236:                }
                   1237:                pv_e->va = va;
                   1238:                pv_e->pmap = pmap;
                   1239:                pv_e->next = pv_h->next;
                   1240:                pv_h->next = pv_e;
                   1241:                /*
                   1242:                 * Remember that we used the pvlist entry.
                   1243:                 */
                   1244:                pv_e = PV_ENTRY_NULL;
                   1245:            }
                   1246:            
                   1247:            UNLOCK_PVH(pd);
                   1248:        }
                   1249:            
                   1250:        pmap_allocate_mapping(pmap, va, wired);
                   1251: 
                   1252:        /*
                   1253:         * Build a template to speed up entering -
                   1254:         * only the pfn changes.
                   1255:         */
                   1256:        pte_prot(pmap, prot, 1, &template);
                   1257:        template.pfn = phys_to_pfn(pa);
                   1258:        if (wired)
                   1259:            template.wired = 1;
                   1260:            
                   1261:        if (caching == cache_disable)
                   1262:            template.cachedis = 1;
                   1263:        else
                   1264:        if (caching == cache_writethrough)
                   1265:            template.cachewrt = 1;
                   1266:        
                   1267:        for (i = ptes_per_vm_page; i-- > 0; pte++) {
                   1268:            *pte = template;
                   1269:            template.pfn++;
                   1270:        }
                   1271:     }
                   1272: 
                   1273:     PMAP_READ_UNLOCK(pmap, s);
                   1274: 
                   1275:     if (pv_e != PV_ENTRY_NULL)
                   1276:        zfree(pv_entry_zone, (vm_offset_t) pv_e);
                   1277: }
                   1278: 
                   1279: void
                   1280: pmap_enter(
                   1281:     pmap_t             pmap,
                   1282:     vm_offset_t                va,
                   1283:     vm_offset_t                pa,
                   1284:     vm_prot_t          prot,
                   1285:     boolean_t          wired
                   1286: )
                   1287: {
                   1288:     pmap_enter_cache_spec(
                   1289:                        pmap,
                   1290:                        va,
                   1291:                        pa,
                   1292:                        prot,
                   1293:                        wired,
                   1294:                        cache_default);
                   1295: }
                   1296: 
                   1297: void
                   1298: pmap_enter_shared_range(
                   1299:     pmap_t             pmap,
                   1300:     vm_offset_t                va,
                   1301:     vm_size_t          size,
                   1302:     vm_offset_t                kern
                   1303: )
                   1304: {
                   1305:     vm_offset_t                end = round_page(va + size);
                   1306:     
                   1307:     while (va < end) {
                   1308:        pmap_enter(
                   1309:                    pmap,
                   1310:                    va,
                   1311:                    pmap_resident_extract(kernel_pmap, kern),
                   1312:                    VM_PROT_READ|VM_PROT_WRITE,
                   1313:                    TRUE);
                   1314:                    
                   1315:        va += PAGE_SIZE; kern += PAGE_SIZE;
                   1316:     }
                   1317: }
                   1318: 
                   1319: /*
                   1320:  * Change the wiring attribute for a
                   1321:  * pmap/virtual-address        pair.
                   1322:  *
                   1323:  * The mapping must already exist in the pmap.
                   1324:  */
                   1325: void
                   1326: pmap_change_wiring(
                   1327:     pmap_t             pmap,
                   1328:     vm_offset_t                va,
                   1329:     boolean_t          wired
                   1330: )
                   1331: {
                   1332:     pt_entry_t         *pte;
                   1333:     int                        i, s;
                   1334:     
                   1335:     /*
                   1336:      * We must grab the pmap system lock because we may
                   1337:      * change a pte_page queue.
                   1338:      */
                   1339:     PMAP_READ_LOCK(pmap, s);
                   1340:     
                   1341:     if ((pte = pmap_pt_entry(pmap, va)) == PT_ENTRY_NULL)
                   1342:        panic("pmap_change_wiring");
                   1343: 
                   1344:     if (wired && !pte->wired) {
                   1345:        /*
                   1346:         * wiring down mapping
                   1347:         */
                   1348:        pmap_wire_mapping(pmap, va);
                   1349:     }
                   1350:     else
                   1351:     if (!wired && pte->wired) {
                   1352:        /*
                   1353:         * unwiring mapping
                   1354:         */
                   1355:        pmap_unwire_mapping(pmap, va);
                   1356:     }
                   1357:     
                   1358:     for (i = ptes_per_vm_page; i-- > 0; pte++)
                   1359:        pte->wired = wired;
                   1360: 
                   1361:     PMAP_READ_UNLOCK(map, s);
                   1362: }
                   1363: 
                   1364: vm_offset_t
                   1365: pmap_extract(
                   1366:     pmap_t             pmap,
                   1367:     vm_offset_t                va
                   1368: )
                   1369: {
                   1370:     vm_offset_t                pa;
                   1371:     int                        s;
                   1372:     
                   1373:     SPLVM(s);
                   1374:     simple_lock(&pmap->lock);
                   1375:     
                   1376:     pa = pmap_phys(pmap, va);
                   1377:     
                   1378:     simple_unlock(&pmap->lock);
                   1379:     SPLX(s);
                   1380:     
                   1381:     return (pa);
                   1382: }
                   1383: 
                   1384: vm_offset_t
                   1385: pmap_resident_extract(
                   1386:     pmap_t             pmap,
                   1387:     vm_offset_t                va
                   1388: )
                   1389: {
                   1390:     return ((vm_offset_t) pmap_phys(pmap, va));
                   1391: }
                   1392: 
                   1393: /*
                   1394:  * Expand a pmap to be able to map the
                   1395:  * specified virtual address by allocating
                   1396:  * a single page table either from the list 
                   1397:  * of free page tables or directly from kernel
                   1398:  * memory.
                   1399:  */
                   1400: static
                   1401: void
                   1402: pmap_expand(
                   1403:     pmap_t             pmap,
                   1404:     vm_offset_t                va
                   1405: )
                   1406: {
                   1407:     pd_entry_t         template, *pde;
                   1408:     pg_exten_t         *pe;
                   1409:     vm_offset_t                pt;
                   1410:     int                        i, s;
                   1411: 
                   1412:     if (pmap == kernel_pmap)
                   1413:        panic("pmap_expand");
                   1414:            
                   1415:     if (pe = pt_free_obtain())
                   1416:        pt = pe->pg_desc->pv_list.va;
                   1417:     else {
                   1418:        if (kmem_alloc_wired(kernel_map, &pt, PAGE_SIZE) != KERN_SUCCESS)
                   1419:            return;
                   1420: 
                   1421:        pt_alloc_count++;
                   1422:        
                   1423:        pe = pg_exten_alloc(pt);
                   1424:     }
                   1425: 
                   1426:     PMAP_READ_LOCK(pmap, s);   
                   1427: 
                   1428:     /*
                   1429:      * See if someone else expanded us first.
                   1430:      */
                   1431:     if (pmap_pt_entry(pmap, va) != PT_ENTRY_NULL) {
                   1432:        PMAP_READ_UNLOCK(pmap, s);
                   1433:        
                   1434:        pg_exten_free(pe);
                   1435: 
                   1436:        kmem_free(kernel_map, pt, PAGE_SIZE);
                   1437:        
                   1438:        pt_alloc_count--;
                   1439: 
                   1440:        return;
                   1441:     }
                   1442: 
                   1443:     /*
                   1444:      * What virtual memory does this
                   1445:      * page table map ?
                   1446:      */
                   1447:     pe->offset = trunc_section(va);
                   1448:     pe->pmap = pmap;
                   1449: 
                   1450:     /*
                   1451:      * Clear the reference aging
                   1452:      * tick count.
                   1453:      */
                   1454:     pe->unrefd_age = 0;
                   1455: 
                   1456:     /*
                   1457:      * Add this page table
                   1458:      * to the active queue.
                   1459:      */        
                   1460:     pt_active_add(pe);
                   1461: 
                   1462:     /*
                   1463:      * Setup entry template.
                   1464:      */
                   1465:     template = (pd_entry_t) { 0 };
                   1466:     template.valid = 1;
                   1467:     template.prot = PT_PROT_URW;
                   1468:     template.pfn = phys_to_pfn(pe->phys);
                   1469: 
                   1470:     /*
                   1471:      * Set the page directory entries for this page table
                   1472:      */
                   1473:     pde = pmap_pd_entry(pmap, pe->offset);
                   1474:     for (i = ptes_per_vm_page; i-- > 0; pde++) {
                   1475:        *pde = template;
                   1476:        template.pfn++;
                   1477:     }
                   1478:     
                   1479:     PMAP_READ_UNLOCK(pmap, s);
                   1480: }
                   1481: 
                   1482: /*
                   1483:  * Allocate one additional mapping
                   1484:  * in a page table.  Note: pmap is
                   1485:  * already locked.
                   1486:  */
                   1487: static
                   1488: void
                   1489: pmap_allocate_mapping(
                   1490:     pmap_t             pmap,
                   1491:     vm_offset_t                va,
                   1492:     boolean_t          wired
                   1493: )
                   1494: {
                   1495:     pd_entry_t         *pde;
                   1496:     pg_exten_t         *pe;
                   1497:     
                   1498:     pmap->stats.resident_count++;
                   1499:     if (wired)
                   1500:        pmap->stats.wired_count++;
                   1501:     
                   1502:     if (pmap == kernel_pmap)
                   1503:        return;
                   1504:        
                   1505:     pde = pmap_pd_entry(pmap, trunc_section(va));
                   1506:     if (pde->valid) {
                   1507:        pe = pg_desc(pfn_to_phys(pde->pfn))->pg_exten;
                   1508:        pe->alloc_count++;
                   1509:        if (wired)
                   1510:            pe->wired_count++;
                   1511:     }
                   1512: }
                   1513: 
                   1514: /*
                   1515:  * Deallocate one or more mappings
                   1516:  * in a page table.  The page table
                   1517:  * is freed if no mappings remain.
                   1518:  * Note: pmap is already locked.
                   1519:  */
                   1520: static
                   1521: void
                   1522: pmap_deallocate_mappings(
                   1523:     pmap_t             pmap,
                   1524:     vm_offset_t                va,
                   1525:     int                        count,
                   1526:     int                        unwire_count,
                   1527:     boolean_t          free_table
                   1528: )
                   1529: {
                   1530:     pd_entry_t         *pde;
                   1531:     pg_exten_t         *pe;
                   1532:     int                        i;
                   1533:     
                   1534:     pmap->stats.wired_count -= unwire_count;
                   1535:     pmap->stats.resident_count -= count;
                   1536: 
                   1537:     if (pmap == kernel_pmap)
                   1538:        return;
                   1539:        
                   1540:     pde = pmap_pd_entry(pmap, trunc_section(va));
                   1541:     if (pde->valid) {  
                   1542:        pe = pg_desc(pfn_to_phys(pde->pfn))->pg_exten;
                   1543:        if (pe->wired_count < unwire_count)
                   1544:            panic("pmap_deallocate_mappings unwire");
                   1545:        pe->wired_count -= unwire_count;
                   1546:        if (pe->alloc_count < count)
                   1547:            panic("pmap_deallocate_mappings");
                   1548:        pe->alloc_count -= count;
                   1549: 
                   1550:        if (free_table && pe->alloc_count == 0) {
                   1551:            for (i = ptes_per_vm_page; i-- > 0; pde++)
                   1552:                pde->valid = 0;
                   1553:                
                   1554:            pt_active_remove(pe);
                   1555:            
                   1556:            pt_free_add(pe);
                   1557:        }
                   1558:     }
                   1559: }
                   1560: 
                   1561: static
                   1562: void
                   1563: pmap_wire_mapping(
                   1564:     pmap_t             pmap,
                   1565:     vm_offset_t                va
                   1566: )
                   1567: {
                   1568:     pd_entry_t         *pde;
                   1569:     pg_exten_t         *pe;
                   1570:     
                   1571:     pmap->stats.wired_count++;
                   1572:     
                   1573:     if (pmap == kernel_pmap)
                   1574:        return;
                   1575:        
                   1576:     pde = pmap_pd_entry(pmap, trunc_section(va));
                   1577:     if (pde->valid) {
                   1578:        pe = pg_desc(pfn_to_phys(pde->pfn))->pg_exten;
                   1579:        pe->wired_count++;
                   1580:     }
                   1581: }
                   1582: 
                   1583: static
                   1584: void
                   1585: pmap_unwire_mapping(
                   1586:     pmap_t             pmap,
                   1587:     vm_offset_t                va
                   1588: )
                   1589: {
                   1590:     pd_entry_t         *pde;
                   1591:     pg_exten_t         *pe;
                   1592:     
                   1593:     pmap->stats.wired_count--;
                   1594:     
                   1595:     if (pmap == kernel_pmap)
                   1596:        return;
                   1597:        
                   1598:     pde = pmap_pd_entry(pmap, trunc_section(va));
                   1599:     if (pde->valid) {
                   1600:        pe = pg_desc(pfn_to_phys(pde->pfn))->pg_exten;
                   1601:        pe->wired_count--;
                   1602:     }
                   1603: }
                   1604: 
                   1605: /*
                   1606:  * Copy the range specified by src_addr/len
                   1607:  * from the source map to the range dst_addr/len
                   1608:  * in the destination map.
                   1609:  *
                   1610:  * This routine is only advisory and need not do anything.
                   1611:  */
                   1612: void
                   1613: pmap_copy(
                   1614:     pmap_t             dst_pmap,
                   1615:     pmap_t             src_pmap,
                   1616:     vm_offset_t                dst_addr,
                   1617:     vm_size_t          len,
                   1618:     vm_offset_t                src_addr
                   1619: )
                   1620: {
                   1621:     /* OPTIONAL */
                   1622: }
                   1623: 
                   1624: /*
                   1625:  * Require that all active physical maps contain no
                   1626:  * incorrect entries NOW.  [This update includes
                   1627:  * forcing updates of any address map caching.]
                   1628:  *
                   1629:  * Generally used to insure that a thread about
                   1630:  * to run will see a semantically correct world.
                   1631:  */
                   1632: void
                   1633: pmap_update(
                   1634:     void
                   1635: )
                   1636: {
                   1637:     pg_exten_t         *pe, *npe;
                   1638:     vm_offset_t                page;
                   1639:     pd_entry_t         *pde;
                   1640:     int                        tick_delta;
                   1641:     static unsigned int        last_tick;
                   1642: 
                   1643:     if (!last_tick)
                   1644:        last_tick = sched_tick; /* initialization */
                   1645: 
                   1646:     tick_delta = sched_tick - last_tick;
                   1647: 
                   1648:     if (tick_delta > 1) {
                   1649:        /*
                   1650:         * Free all of the pages in
                   1651:         * the free page table list.
                   1652:         */     
                   1653:        while (pe = pt_free_obtain()) {
                   1654:            page = pe->pg_desc->pv_list.va;
                   1655:     
                   1656:            pg_exten_free(pe);
                   1657:     
                   1658:            kmem_free(kernel_map, page, PAGE_SIZE);
                   1659:            pt_alloc_count--;
                   1660:        }
                   1661: 
                   1662:        /*
                   1663:         * Run through the page directory
                   1664:         * free list, freeing any that are
                   1665:         * not in use.
                   1666:         */
                   1667:        (queue_entry_t)pe = queue_first(&pd_free_queue);
                   1668:        while (!queue_end(&pd_free_queue, (queue_entry_t)pe)) {
                   1669:            if (pe->alloc_count == 0) {
                   1670:                remqueue(&pd_free_queue, (queue_entry_t)pe);
                   1671:                
                   1672:                pd_free_count--;
                   1673:                
                   1674:                page = pe->pg_desc->pv_list.va;
                   1675:                
                   1676:                pg_exten_free(pe);
                   1677:                
                   1678:                kmem_free(kernel_map, page, PAGE_SIZE);
                   1679:                pd_alloc_count--;
                   1680:                
                   1681:                (queue_entry_t)pe = queue_first(&pd_free_queue);
                   1682:            }
                   1683:            else
                   1684:                (queue_entry_t)pe = queue_next((queue_entry_t)pe);
                   1685:        }
                   1686:     }
                   1687: 
                   1688:     /*
                   1689:      * Age the active page tables.  Remove
                   1690:      * all of the mappings from the tables
                   1691:      * which have not been used for address
                   1692:      * translation recently (excluding those
                   1693:      * with wired mappings).  Removing all of
                   1694:      * a table's mappings causes the table to
                   1695:      * be removed from the pmap and added to
                   1696:      * the free page table list.
                   1697:      */
                   1698:     {
                   1699:        static int      pt_aging_k[] = { 8, 12, 16, 24, 32 },
                   1700:                        pt_aging_n = sizeof pt_aging_k / sizeof pt_aging_k[0];
                   1701:        int             tick_age;
                   1702:        
                   1703:        tick_age = ((tick_age = tick_delta >> 3) > (pt_aging_n - 1)) ?
                   1704:                                                pt_aging_k[pt_aging_n - 1] :
                   1705:                                                pt_aging_k[tick_age];       
                   1706: 
                   1707:        (queue_entry_t)pe = queue_first(&pt_active_queue);
                   1708:        while (!queue_end(&pt_active_queue, (queue_entry_t)pe)) {
                   1709:            pde = pmap_pd_entry(pe->pmap, pe->offset);
                   1710:            if (pe->wired_count == 0 && pde->valid) {
                   1711:                (queue_entry_t)npe = queue_next((queue_entry_t)pe);
                   1712:     
                   1713:                if (tick_delta > 0 && !pde->refer) {
                   1714:                    int         old_age = pe->unrefd_age;
                   1715:     
                   1716:                    pe->unrefd_age += tick_delta;
                   1717:                    if (old_age > pe->unrefd_age || pe->unrefd_age > tick_age)
                   1718:                        pmap_remove(
                   1719:                                pe->pmap,
                   1720:                                pe->offset,
                   1721:                                pe->offset + section_size);
                   1722:                }
                   1723:                else if (pde->refer) {
                   1724:                    pde->refer = FALSE;
                   1725:                    pe->unrefd_age = 0;
                   1726:                }
                   1727:                    
                   1728:                pe = npe;
                   1729:            }
                   1730:            else {
                   1731:                pe->unrefd_age = 0;
                   1732:                (queue_entry_t)pe = queue_next((queue_entry_t)pe);
                   1733:            }
                   1734:        }
                   1735:     }
                   1736: 
                   1737:     last_tick += tick_delta;
                   1738: }
                   1739: 
                   1740: /*
                   1741:  * Garbage collects the physical map system for
                   1742:  * pages which are no longer used.
                   1743:  * Success need not be guaranteed -- that is, there
                   1744:  * may well be pages which are not referenced, but
                   1745:  * others may be collected.
                   1746:  *
                   1747:  * Called by the pageout daemon when pages are scarce.
                   1748:  */
                   1749: void
                   1750: pmap_collect(
                   1751:     pmap_t             pmap
                   1752: )
                   1753: {
                   1754:     /* OPTIONAL */
                   1755: }
                   1756: 
                   1757: /*
                   1758:  * Bind the given pmap to the given
                   1759:  * processor.
                   1760:  */
                   1761: void
                   1762: pmap_activate(
                   1763:     pmap_t             pmap,
                   1764:     thread_t           thread,
                   1765:     int                        cpu
                   1766: )
                   1767: {
                   1768:     PMAP_ACTIVATE(pmap, thread, cpu);
                   1769: }
                   1770: 
                   1771: 
                   1772: /*
                   1773:  * Indicates that the given physical map is no longer
                   1774:  * in use on the specified processor.
                   1775:  */
                   1776: void
                   1777: pmap_deactivate(
                   1778:     pmap_t             pmap,
                   1779:     thread_t           thread,
                   1780:     int                        cpu
                   1781: )
                   1782: {
                   1783:     PMAP_DEACTIVATE(pmap, thread, cpu);
                   1784: }
                   1785: 
                   1786: /*
                   1787:  * Return the pmap handle for the kernel.
                   1788:  */
                   1789: pmap_t
                   1790: pmap_kernel(
                   1791:     void
                   1792: )
                   1793: {
                   1794:     return (kernel_pmap);
                   1795: }
                   1796: 
                   1797: /*
                   1798:  * pmap_zero_page zeros the specified (machine independent)
                   1799:  * page.
                   1800:  */
                   1801: void
                   1802: pmap_zero_page(
                   1803:     vm_offset_t                pa
                   1804: )
                   1805: {
                   1806:     page_set(pmap_phys_to_kern(pa), 0, PAGE_SIZE);
                   1807: }
                   1808: 
                   1809: /*
                   1810:  * pmap_copy_page copies the specified (machine independent)
                   1811:  * pages.
                   1812:  */
                   1813: void
                   1814: pmap_copy_page(
                   1815:     vm_offset_t                src,
                   1816:     vm_offset_t                dst
                   1817: )
                   1818: {
                   1819:     page_copy(pmap_phys_to_kern(dst), pmap_phys_to_kern(src), PAGE_SIZE);
                   1820: }
                   1821: 
                   1822: void
                   1823: copy_to_phys(
                   1824:     vm_offset_t                src,
                   1825:     vm_offset_t                dst,
                   1826:     vm_size_t          count
                   1827: )
                   1828: {
                   1829:     bcopy(src, pmap_phys_to_kern(dst), count);
                   1830: }
                   1831: 
                   1832: void
                   1833: copy_from_phys(
                   1834:     vm_offset_t                src,
                   1835:     vm_offset_t                dst,
                   1836:     vm_size_t          count
                   1837: )
                   1838: {
                   1839:     bcopy(pmap_phys_to_kern(src), dst, count);
                   1840: }
                   1841: 
                   1842: /*
                   1843:  * Make the specified pages (by pmap, offset)
                   1844:  * pageable (or not) as requested.
                   1845:  *
                   1846:  * A page which is not pageable may not take
                   1847:  * a fault; therefore, its page table entry
                   1848:  * must remain valid for the duration.
                   1849:  *
                   1850:  * This routine is merely advisory; pmap_enter
                   1851:  * will specify that these pages are to be wired
                   1852:  * down (or not) as appropriate.
                   1853:  */
                   1854: pmap_pageable(
                   1855:     pmap_t             pmap,
                   1856:     vm_offset_t                start,
                   1857:     vm_offset_t                end,
                   1858:     boolean_t          pageable
                   1859: )
                   1860: {
                   1861:     /* OPTIONAL */
                   1862: }
                   1863: 
                   1864: kern_return_t
                   1865: pmap_attribute(
                   1866:     pmap_t                     pmap,
                   1867:     vm_offset_t                        address,
                   1868:     vm_size_t                  size,
                   1869:     vm_machine_attribute_t     attribute,
                   1870:     vm_machine_attribute_val_t *value
                   1871: )
                   1872: {
                   1873:        kern_return_t ret;
                   1874: 
                   1875:        if (attribute != MATTR_CACHE)
                   1876:                return KERN_INVALID_ARGUMENT;
                   1877: 
                   1878:        /*
                   1879:        ** We can't get the caching attribute for more than one page
                   1880:        ** at a time
                   1881:        */
                   1882:        if ((*value == MATTR_VAL_GET) &&
                   1883:            (trunc_page(address) != trunc_page(address+size-1)))
                   1884:                return KERN_INVALID_ARGUMENT;
                   1885: 
                   1886:        if (pmap == PMAP_NULL)
                   1887:                return KERN_SUCCESS;
                   1888: 
                   1889:        ret = KERN_SUCCESS;
                   1890: 
                   1891:         simple_lock(&pmap->lock);
                   1892: 
                   1893:        switch (*value) {
                   1894:        case MATTR_VAL_CACHE_FLUSH:     /* flush from all caches */
                   1895:        case MATTR_VAL_DCACHE_FLUSH:    /* flush from data cache(s) */
                   1896:        case MATTR_VAL_ICACHE_FLUSH:    /* flush from instr cache(s) */
                   1897:                break;
                   1898: 
                   1899:        case MATTR_VAL_GET:             /* return current value */
                   1900:        case MATTR_VAL_OFF:             /* turn attribute off */
                   1901:        case MATTR_VAL_ON:              /* turn attribute on */
                   1902:        default:
                   1903:                ret = KERN_INVALID_ARGUMENT;
                   1904:                break;
                   1905:        }
                   1906:        simple_unlock(&pmap->lock);
                   1907: 
                   1908:        return ret;
                   1909: 
                   1910: }
                   1911: 
                   1912: /*
                   1913:  * Clear the modify bits on the specified physical page.
                   1914:  */
                   1915: void
                   1916: pmap_clear_modify(
                   1917:     vm_offset_t                pa
                   1918: )
                   1919: {
                   1920:     if (managed_page(pa))
                   1921:        pmap_clear_page_attrib(pa, PG_DIRTY);
                   1922: }
                   1923: 
                   1924: /*
                   1925:  * Return whether or not the specified physical page is modified
                   1926:  * by any pmaps.
                   1927:  */
                   1928: boolean_t
                   1929: pmap_is_modified(
                   1930:     vm_offset_t                pa
                   1931: )
                   1932: {
                   1933:     if (managed_page(pa))
                   1934:        return (pmap_check_page_attrib(pa, PG_DIRTY));
                   1935:     else
                   1936:        return (FALSE);
                   1937: }
                   1938: 
                   1939: /*
                   1940:  * Clear the reference bit on the specified physical page.
                   1941:  */
                   1942: void
                   1943: pmap_clear_reference(
                   1944:     vm_offset_t                pa
                   1945: )
                   1946: {
                   1947:     if (managed_page(pa))
                   1948:        pmap_clear_page_attrib(pa, PG_REFER);
                   1949: }
                   1950: 
                   1951: /*
                   1952:  * Return whether or not the specified physical page is referenced
                   1953:  * by any physical maps.
                   1954:  */
                   1955: boolean_t
                   1956: pmap_is_referenced(
                   1957:     vm_offset_t                pa
                   1958: )
                   1959: {
                   1960:     if (managed_page(pa))
                   1961:        return (pmap_check_page_attrib(pa, PG_REFER));
                   1962:     else
                   1963:        return (FALSE);
                   1964: }
                   1965: 
                   1966: /*
                   1967:  * Clear the specified page attributes both in the
                   1968:  * pmap_page_attributes table and the address translation
                   1969:  * tables.  Note that we DO have to flush the entries from
                   1970:  * the TLB since the processor uses the bits in the TLB to
                   1971:  * determine whether it has to write the bits out to memory.
                   1972:  */
                   1973: static
                   1974: void
                   1975: pmap_clear_page_attrib(
                   1976:     vm_offset_t                        pa,
                   1977:     int                                attrib
                   1978: )
                   1979: {
                   1980:     pt_entry_t                 *pte;
                   1981:     pv_entry_t                 pv_h;
                   1982:     pmap_t                     pmap;
                   1983:     vm_offset_t                        va;
                   1984:     pg_desc_t                  *pd;
                   1985:     int                                i, s;
                   1986: 
                   1987:     pd = pg_desc(pa);
                   1988: 
                   1989:     PMAP_WRITE_LOCK(s);
                   1990: 
                   1991:     pd->page_attrib &= ~attrib;
                   1992: 
                   1993:     pv_h = pg_desc_pvh(pd);
                   1994: 
                   1995:     while ((pmap = pv_h->pmap) != PMAP_NULL) {
                   1996:        va = pv_h->va;
                   1997: 
                   1998:        simple_lock(&pmap->lock);
                   1999: 
                   2000:        PMAP_UPDATE_TLBS(pmap, va, va + PAGE_SIZE);
                   2001: 
                   2002:        pte = pmap_pt_entry(pmap, va);
                   2003:        if (pte != PT_ENTRY_NULL) {
                   2004:            for (i = ptes_per_vm_page; i-- > 0; pte++) {
                   2005:                if (attrib & PG_DIRTY)
                   2006:                    pte->dirty = 0;
                   2007:                if (attrib & PG_REFER)
                   2008:                    pte->refer = 0;
                   2009:            }
                   2010:        }
                   2011: 
                   2012:        simple_unlock(&pmap->lock);
                   2013: 
                   2014:        if ((pv_h = pv_h->next) == PV_ENTRY_NULL)
                   2015:            break;
                   2016:     }
                   2017: 
                   2018:     PMAP_WRITE_UNLOCK(s);
                   2019: }
                   2020: 
                   2021: /*
                   2022:  * Check for the specified attributes for the
                   2023:  * physical page.  if all bits are true in
                   2024:  * the pmap_page_attributes table, we can trust
                   2025:  * it.  otherwise, we must check the address
                   2026:  * translation tables ourselves.  Note that we
                   2027:  * DO NOT have to flush the entry from the TLB
                   2028:  * before looking at the address translation
                   2029:  * table since the TLB is write-through for the bits.
                   2030:  */
                   2031: static
                   2032: boolean_t
                   2033: pmap_check_page_attrib(
                   2034:     vm_offset_t                        pa,
                   2035:     int                                attrib
                   2036: )
                   2037: {
                   2038:     pt_entry_t                 *pte;
                   2039:     pv_entry_t                 pv_h;
                   2040:     pmap_t                     pmap;
                   2041:     vm_offset_t                        va;
                   2042:     pg_desc_t                  *pd;
                   2043:     int                                i, s;
                   2044: 
                   2045:     pd = pg_desc(pa);
                   2046: 
                   2047:     if ((pd->page_attrib & attrib) == attrib)
                   2048:        return (TRUE);
                   2049: 
                   2050:     pv_h = pg_desc_pvh(pd);
                   2051: 
                   2052:     PMAP_WRITE_LOCK(s);
                   2053: 
                   2054:     while ((pmap = pv_h->pmap) != PMAP_NULL) {
                   2055:        va = pv_h->va;
                   2056: 
                   2057:        simple_lock(&pmap->lock);
                   2058: 
                   2059:        pte = pmap_pt_entry(pmap, va);
                   2060:        if (pte != PT_ENTRY_NULL) {
                   2061:            for (i = ptes_per_vm_page; i-- > 0; pte++) {
                   2062:                if (pte->dirty)
                   2063:                    pd->page_attrib |= PG_DIRTY;
                   2064:                if (pte->refer)
                   2065:                    pd->page_attrib |= PG_REFER;
                   2066:            }
                   2067: 
                   2068:            if ((pd->page_attrib & attrib) == attrib) {
                   2069:                simple_unlock(&pmap->lock);
                   2070: 
                   2071:                PMAP_WRITE_UNLOCK(s);
                   2072: 
                   2073:                return (TRUE);
                   2074:            }
                   2075:        }
                   2076: 
                   2077:        simple_unlock(&pmap->lock);
                   2078: 
                   2079:        if ((pv_h = pv_h->next) == PV_ENTRY_NULL)
                   2080:            break;
                   2081:     }
                   2082: 
                   2083:     PMAP_WRITE_UNLOCK(s);
                   2084: 
                   2085:     return (FALSE);
                   2086: }
                   2087: 
                   2088: /*
                   2089:  * Dummy routine to satisfy external reference.
                   2090:  */
                   2091: void
                   2092: pmap_update_interrupt(
                   2093:     void
                   2094: )
                   2095: {
                   2096:     /* should never be called. */
                   2097:     panic("pmap_update_interrupt");
                   2098: }
                   2099: 
                   2100: /*
                   2101:  * Lower the permission for all mappings to a given page.
                   2102:  */
                   2103: void
                   2104: pmap_page_protect(
                   2105:     vm_offset_t                        pa,
                   2106:     vm_prot_t                  prot
                   2107: )
                   2108: {
                   2109:     switch (prot) {
                   2110:        case VM_PROT_READ:
                   2111:        case VM_PROT_READ|VM_PROT_EXECUTE:
                   2112:            pmap_copy_on_write(pa);
                   2113:            break;
                   2114: 
                   2115:        case VM_PROT_ALL:
                   2116:            break;
                   2117: 
                   2118:        default:
                   2119:            pmap_remove_all(pa);
                   2120:            break;
                   2121:     }
                   2122: }

unix.superglobalmegacorp.com

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