Annotation of Net2/vm/vm_map.c, revision 1.1.1.2

1.1       root        1: /* 
                      2:  * Copyright (c) 1991 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * The Mach Operating System project at Carnegie-Mellon University.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  *     @(#)vm_map.c    7.3 (Berkeley) 4/21/91
                     37:  *
                     38:  *
                     39:  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
                     40:  * All rights reserved.
                     41:  *
                     42:  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
                     43:  * 
                     44:  * Permission to use, copy, modify and distribute this software and
                     45:  * its documentation is hereby granted, provided that both the copyright
                     46:  * notice and this permission notice appear in all copies of the
                     47:  * software, derivative works or modified versions, and any portions
                     48:  * thereof, and that both notices appear in supporting documentation.
                     49:  * 
                     50:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
                     51:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
                     52:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     53:  * 
                     54:  * Carnegie Mellon requests users of this software to return to
                     55:  *
                     56:  *  Software Distribution Coordinator  or  [email protected]
                     57:  *  School of Computer Science
                     58:  *  Carnegie Mellon University
                     59:  *  Pittsburgh PA 15213-3890
                     60:  *
                     61:  * any improvements or extensions that they make and grant Carnegie the
                     62:  * rights to redistribute these changes.
                     63:  */
                     64: 
                     65: /*
                     66:  *     Virtual memory mapping module.
                     67:  */
                     68: 
                     69: #include "param.h"
                     70: #include "malloc.h"
                     71: #include "vm.h"
                     72: #include "vm_page.h"
                     73: #include "vm_object.h"
                     74: 
                     75: /*
                     76:  *     Virtual memory maps provide for the mapping, protection,
                     77:  *     and sharing of virtual memory objects.  In addition,
                     78:  *     this module provides for an efficient virtual copy of
                     79:  *     memory from one map to another.
                     80:  *
                     81:  *     Synchronization is required prior to most operations.
                     82:  *
                     83:  *     Maps consist of an ordered doubly-linked list of simple
                     84:  *     entries; a single hint is used to speed up lookups.
                     85:  *
                     86:  *     In order to properly represent the sharing of virtual
                     87:  *     memory regions among maps, the map structure is bi-level.
                     88:  *     Top-level ("address") maps refer to regions of sharable
                     89:  *     virtual memory.  These regions are implemented as
                     90:  *     ("sharing") maps, which then refer to the actual virtual
                     91:  *     memory objects.  When two address maps "share" memory,
                     92:  *     their top-level maps both have references to the same
                     93:  *     sharing map.  When memory is virtual-copied from one
                     94:  *     address map to another, the references in the sharing
                     95:  *     maps are actually copied -- no copying occurs at the
                     96:  *     virtual memory object level.
                     97:  *
                     98:  *     Since portions of maps are specified by start/end addreses,
                     99:  *     which may not align with existing map entries, all
                    100:  *     routines merely "clip" entries to these start/end values.
                    101:  *     [That is, an entry is split into two, bordering at a
                    102:  *     start or end value.]  Note that these clippings may not
                    103:  *     always be necessary (as the two resulting entries are then
                    104:  *     not changed); however, the clipping is done for convenience.
                    105:  *     No attempt is currently made to "glue back together" two
                    106:  *     abutting entries.
                    107:  *
                    108:  *     As mentioned above, virtual copy operations are performed
                    109:  *     by copying VM object references from one sharing map to
                    110:  *     another, and then marking both regions as copy-on-write.
                    111:  *     It is important to note that only one writeable reference
                    112:  *     to a VM object region exists in any map -- this means that
                    113:  *     shadow object creation can be delayed until a write operation
                    114:  *     occurs.
                    115:  */
                    116: 
                    117: /*
                    118:  *     vm_map_startup:
                    119:  *
                    120:  *     Initialize the vm_map module.  Must be called before
                    121:  *     any other vm_map routines.
                    122:  *
                    123:  *     Map and entry structures are allocated from the general
                    124:  *     purpose memory pool with some exceptions:
                    125:  *
                    126:  *     - The kernel map and kmem submap are allocated statically.
                    127:  *     - Kernel map entries are allocated out of a static pool.
                    128:  *
                    129:  *     These restrictions are necessary since malloc() uses the
                    130:  *     maps and requires map entries.
                    131:  */
                    132: 
                    133: vm_offset_t    kentry_data;
                    134: vm_size_t      kentry_data_size;
                    135: vm_map_entry_t kentry_free;
                    136: vm_map_t       kmap_free;
                    137: 
                    138: void vm_map_startup()
                    139: {
                    140:        register int i;
                    141:        register vm_map_entry_t mep;
                    142:        vm_map_t mp;
                    143: 
                    144:        /*
                    145:         * Static map structures for allocation before initialization of
                    146:         * kernel map or kmem map.  vm_map_create knows how to deal with them.
                    147:         */
                    148:        kmap_free = mp = (vm_map_t) kentry_data;
                    149:        i = MAX_KMAP;
                    150:        while (--i > 0) {
                    151:                mp->header.next = (vm_map_entry_t) (mp + 1);
                    152:                mp++;
                    153:        }
                    154:        mp++->header.next = NULL;
                    155: 
                    156:        /*
                    157:         * Form a free list of statically allocated kernel map entries
                    158:         * with the rest.
                    159:         */
                    160:        kentry_free = mep = (vm_map_entry_t) mp;
                    161:        i = (kentry_data_size - MAX_KMAP * sizeof *mp) / sizeof *mep;
                    162:        while (--i > 0) {
                    163:                mep->next = mep + 1;
                    164:                mep++;
                    165:        }
                    166:        mep->next = NULL;
                    167: }
                    168: 
                    169: /*
                    170:  * Allocate a vmspace structure, including a vm_map and pmap,
                    171:  * and initialize those structures.  The refcnt is set to 1.
                    172:  * The remaining fields must be initialized by the caller.
                    173:  */
                    174: struct vmspace *
                    175: vmspace_alloc(min, max, pageable)
                    176:        vm_offset_t min, max;
                    177:        int pageable;
                    178: {
                    179:        register struct vmspace *vm;
                    180: 
                    181:        MALLOC(vm, struct vmspace *, sizeof(struct vmspace), M_VMMAP, M_WAITOK);
                    182:        bzero(vm, (caddr_t) &vm->vm_startcopy - (caddr_t) vm);
                    183:        vm_map_init(&vm->vm_map, min, max, pageable);
                    184:        pmap_pinit(&vm->vm_pmap);
                    185:        vm->vm_map.pmap = &vm->vm_pmap;         /* XXX */
                    186:        vm->vm_refcnt = 1;
                    187:        return (vm);
                    188: }
                    189: 
                    190: void
                    191: vmspace_free(vm)
                    192:        register struct vmspace *vm;
                    193: {
                    194: 
                    195:        if (--vm->vm_refcnt == 0) {
                    196:                /*
                    197:                 * Lock the map, to wait out all other references to it.
                    198:                 * Delete all of the mappings and pages they hold,
                    199:                 * then call the pmap module to reclaim anything left.
                    200:                 */
                    201:                vm_map_lock(&vm->vm_map);
                    202:                (void) vm_map_delete(&vm->vm_map, vm->vm_map.min_offset,
                    203:                    vm->vm_map.max_offset);
                    204:                pmap_release(&vm->vm_pmap);
                    205:                FREE(vm, M_VMMAP);
                    206:        }
                    207: }
                    208: 
                    209: /*
                    210:  *     vm_map_create:
                    211:  *
                    212:  *     Creates and returns a new empty VM map with
                    213:  *     the given physical map structure, and having
                    214:  *     the given lower and upper address bounds.
                    215:  */
                    216: vm_map_t vm_map_create(pmap, min, max, pageable)
                    217:        pmap_t          pmap;
                    218:        vm_offset_t     min, max;
                    219:        boolean_t       pageable;
                    220: {
                    221:        register vm_map_t       result;
                    222:        extern vm_map_t         kernel_map, kmem_map;
                    223: 
                    224:        if (kmem_map == NULL) {
                    225:                result = kmap_free;
                    226:                kmap_free = (vm_map_t) result->header.next;
                    227:                if (result == NULL)
                    228:                        panic("vm_map_create: out of maps");
                    229:        } else
                    230:                MALLOC(result, vm_map_t, sizeof(struct vm_map),
                    231:                       M_VMMAP, M_WAITOK);
                    232: 
                    233:        vm_map_init(result, min, max, pageable);
                    234:        result->pmap = pmap;
                    235:        return(result);
                    236: }
                    237: 
                    238: /*
                    239:  * Initialize an existing vm_map structure
                    240:  * such as that in the vmspace structure.
                    241:  * The pmap is set elsewhere.
                    242:  */
                    243: void
                    244: vm_map_init(map, min, max, pageable)
                    245:        register struct vm_map *map;
                    246:        vm_offset_t     min, max;
                    247:        boolean_t       pageable;
                    248: {
                    249:        map->header.next = map->header.prev = &map->header;
                    250:        map->nentries = 0;
                    251:        map->size = 0;
                    252:        map->ref_count = 1;
                    253:        map->is_main_map = TRUE;
                    254:        map->min_offset = min;
                    255:        map->max_offset = max;
                    256:        map->entries_pageable = pageable;
                    257:        map->first_free = &map->header;
                    258:        map->hint = &map->header;
                    259:        map->timestamp = 0;
                    260:        lock_init(&map->lock, TRUE);
                    261:        simple_lock_init(&map->ref_lock);
                    262:        simple_lock_init(&map->hint_lock);
                    263: }
                    264: 
                    265: /*
                    266:  *     vm_map_entry_create:    [ internal use only ]
                    267:  *
                    268:  *     Allocates a VM map entry for insertion.
                    269:  *     No entry fields are filled in.  This routine is
                    270:  */
                    271: vm_map_entry_t vm_map_entry_create(map)
                    272:        vm_map_t        map;
                    273: {
                    274:        vm_map_entry_t  entry;
1.1.1.2 ! root      275:        extern vm_map_t         kernel_map, kmem_map, mb_map, buffer_map;
1.1       root      276: 
1.1.1.2 ! root      277:        if (map == kernel_map || map == kmem_map || map == mb_map
        !           278:                || map == buffer_map) {
1.1       root      279:                if (entry = kentry_free)
                    280:                        kentry_free = kentry_free->next;
                    281:        } else
                    282:                MALLOC(entry, vm_map_entry_t, sizeof(struct vm_map_entry),
                    283:                       M_VMMAPENT, M_WAITOK);
                    284:        if (entry == NULL)
                    285:                panic("vm_map_entry_create: out of map entries");
                    286: 
                    287:        return(entry);
                    288: }
                    289: 
                    290: /*
                    291:  *     vm_map_entry_dispose:   [ internal use only ]
                    292:  *
                    293:  *     Inverse of vm_map_entry_create.
                    294:  */
                    295: void vm_map_entry_dispose(map, entry)
                    296:        vm_map_t        map;
                    297:        vm_map_entry_t  entry;
                    298: {
1.1.1.2 ! root      299:        extern vm_map_t         kernel_map, kmem_map, mb_map, buffer_map;
1.1       root      300: 
1.1.1.2 ! root      301:        if (map == kernel_map || map == kmem_map || map == mb_map
        !           302:                || map == buffer_map) {
1.1       root      303:                entry->next = kentry_free;
                    304:                kentry_free = entry;
                    305:        } else
                    306:                FREE(entry, M_VMMAPENT);
                    307: }
                    308: 
                    309: /*
                    310:  *     vm_map_entry_{un,}link:
                    311:  *
                    312:  *     Insert/remove entries from maps.
                    313:  */
                    314: #define        vm_map_entry_link(map, after_where, entry) \
                    315:                { \
                    316:                (map)->nentries++; \
                    317:                (entry)->prev = (after_where); \
                    318:                (entry)->next = (after_where)->next; \
                    319:                (entry)->prev->next = (entry); \
                    320:                (entry)->next->prev = (entry); \
                    321:                }
                    322: #define        vm_map_entry_unlink(map, entry) \
                    323:                { \
                    324:                (map)->nentries--; \
                    325:                (entry)->next->prev = (entry)->prev; \
                    326:                (entry)->prev->next = (entry)->next; \
                    327:                }
                    328: 
                    329: /*
                    330:  *     vm_map_reference:
                    331:  *
                    332:  *     Creates another valid reference to the given map.
                    333:  *
                    334:  */
                    335: void vm_map_reference(map)
                    336:        register vm_map_t       map;
                    337: {
                    338:        if (map == NULL)
                    339:                return;
                    340: 
                    341:        simple_lock(&map->ref_lock);
                    342:        map->ref_count++;
                    343:        simple_unlock(&map->ref_lock);
                    344: }
                    345: 
                    346: /*
                    347:  *     vm_map_deallocate:
                    348:  *
                    349:  *     Removes a reference from the specified map,
                    350:  *     destroying it if no references remain.
                    351:  *     The map should not be locked.
                    352:  */
                    353: void vm_map_deallocate(map)
                    354:        register vm_map_t       map;
                    355: {
                    356:        register int            c;
                    357: 
                    358:        if (map == NULL)
                    359:                return;
                    360: 
                    361:        simple_lock(&map->ref_lock);
                    362:        c = --map->ref_count;
                    363:        simple_unlock(&map->ref_lock);
                    364: 
                    365:        if (c > 0) {
                    366:                return;
                    367:        }
                    368: 
                    369:        /*
                    370:         *      Lock the map, to wait out all other references
                    371:         *      to it.
                    372:         */
                    373: 
                    374:        vm_map_lock(map);
                    375: 
                    376:        (void) vm_map_delete(map, map->min_offset, map->max_offset);
                    377: 
                    378:        pmap_destroy(map->pmap);
                    379: 
                    380:        FREE(map, M_VMMAP);
                    381: }
                    382: 
                    383: /*
                    384:  *     vm_map_insert:  [ internal use only ]
                    385:  *
                    386:  *     Inserts the given whole VM object into the target
                    387:  *     map at the specified address range.  The object's
                    388:  *     size should match that of the address range.
                    389:  *
                    390:  *     Requires that the map be locked, and leaves it so.
                    391:  */
                    392: vm_map_insert(map, object, offset, start, end)
                    393:        vm_map_t        map;
                    394:        vm_object_t     object;
                    395:        vm_offset_t     offset;
                    396:        vm_offset_t     start;
                    397:        vm_offset_t     end;
                    398: {
                    399:        register vm_map_entry_t         new_entry;
                    400:        register vm_map_entry_t         prev_entry;
                    401:        vm_map_entry_t                  temp_entry;
                    402: 
                    403:        /*
                    404:         *      Check that the start and end points are not bogus.
                    405:         */
                    406: 
                    407:        if ((start < map->min_offset) || (end > map->max_offset) ||
                    408:                        (start >= end))
                    409:                return(KERN_INVALID_ADDRESS);
                    410: 
                    411:        /*
                    412:         *      Find the entry prior to the proposed
                    413:         *      starting address; if it's part of an
                    414:         *      existing entry, this range is bogus.
                    415:         */
                    416: 
                    417:        if (vm_map_lookup_entry(map, start, &temp_entry))
                    418:                return(KERN_NO_SPACE);
                    419: 
                    420:        prev_entry = temp_entry;
                    421: 
                    422:        /*
                    423:         *      Assert that the next entry doesn't overlap the
                    424:         *      end point.
                    425:         */
                    426: 
                    427:        if ((prev_entry->next != &map->header) &&
                    428:                        (prev_entry->next->start < end))
                    429:                return(KERN_NO_SPACE);
                    430: 
                    431:        /*
                    432:         *      See if we can avoid creating a new entry by
                    433:         *      extending one of our neighbors.
                    434:         */
                    435: 
                    436:        if (object == NULL) {
                    437:                if ((prev_entry != &map->header) &&
                    438:                    (prev_entry->end == start) &&
                    439:                    (map->is_main_map) &&
                    440:                    (prev_entry->is_a_map == FALSE) &&
                    441:                    (prev_entry->is_sub_map == FALSE) &&
                    442:                    (prev_entry->inheritance == VM_INHERIT_DEFAULT) &&
                    443:                    (prev_entry->protection == VM_PROT_DEFAULT) &&
                    444:                    (prev_entry->max_protection == VM_PROT_DEFAULT) &&
                    445:                    (prev_entry->wired_count == 0)) {
                    446: 
                    447:                        if (vm_object_coalesce(prev_entry->object.vm_object,
                    448:                                        NULL,
                    449:                                        prev_entry->offset,
                    450:                                        (vm_offset_t) 0,
                    451:                                        (vm_size_t)(prev_entry->end
                    452:                                                     - prev_entry->start),
                    453:                                        (vm_size_t)(end - prev_entry->end))) {
                    454:                                /*
                    455:                                 *      Coalesced the two objects - can extend
                    456:                                 *      the previous map entry to include the
                    457:                                 *      new range.
                    458:                                 */
                    459:                                map->size += (end - prev_entry->end);
                    460:                                prev_entry->end = end;
                    461:                                return(KERN_SUCCESS);
                    462:                        }
                    463:                }
                    464:        }
                    465: 
                    466:        /*
                    467:         *      Create a new entry
                    468:         */
                    469: 
                    470:        new_entry = vm_map_entry_create(map);
                    471:        new_entry->start = start;
                    472:        new_entry->end = end;
                    473: 
                    474:        new_entry->is_a_map = FALSE;
                    475:        new_entry->is_sub_map = FALSE;
                    476:        new_entry->object.vm_object = object;
                    477:        new_entry->offset = offset;
                    478: 
                    479:        new_entry->copy_on_write = FALSE;
                    480:        new_entry->needs_copy = FALSE;
                    481: 
                    482:        if (map->is_main_map) {
                    483:                new_entry->inheritance = VM_INHERIT_DEFAULT;
                    484:                new_entry->protection = VM_PROT_DEFAULT;
                    485:                new_entry->max_protection = VM_PROT_DEFAULT;
                    486:                new_entry->wired_count = 0;
                    487:        }
                    488: 
                    489:        /*
                    490:         *      Insert the new entry into the list
                    491:         */
                    492: 
                    493:        vm_map_entry_link(map, prev_entry, new_entry);
                    494:        map->size += new_entry->end - new_entry->start;
                    495: 
                    496:        /*
                    497:         *      Update the free space hint
                    498:         */
                    499: 
                    500:        if ((map->first_free == prev_entry) && (prev_entry->end >= new_entry->start))
                    501:                map->first_free = new_entry;
                    502: 
                    503:        return(KERN_SUCCESS);
                    504: }
                    505: 
                    506: /*
                    507:  *     SAVE_HINT:
                    508:  *
                    509:  *     Saves the specified entry as the hint for
                    510:  *     future lookups.  Performs necessary interlocks.
                    511:  */
                    512: #define        SAVE_HINT(map,value) \
                    513:                simple_lock(&(map)->hint_lock); \
                    514:                (map)->hint = (value); \
                    515:                simple_unlock(&(map)->hint_lock);
                    516: 
                    517: /*
                    518:  *     vm_map_lookup_entry:    [ internal use only ]
                    519:  *
                    520:  *     Finds the map entry containing (or
                    521:  *     immediately preceding) the specified address
                    522:  *     in the given map; the entry is returned
                    523:  *     in the "entry" parameter.  The boolean
                    524:  *     result indicates whether the address is
                    525:  *     actually contained in the map.
                    526:  */
                    527: boolean_t vm_map_lookup_entry(map, address, entry)
                    528:        register vm_map_t       map;
                    529:        register vm_offset_t    address;
                    530:        vm_map_entry_t          *entry;         /* OUT */
                    531: {
                    532:        register vm_map_entry_t         cur;
                    533:        register vm_map_entry_t         last;
                    534: 
                    535:        /*
                    536:         *      Start looking either from the head of the
                    537:         *      list, or from the hint.
                    538:         */
                    539: 
                    540:        simple_lock(&map->hint_lock);
                    541:        cur = map->hint;
                    542:        simple_unlock(&map->hint_lock);
                    543: 
                    544:        if (cur == &map->header)
                    545:                cur = cur->next;
                    546: 
                    547:        if (address >= cur->start) {
                    548:                /*
                    549:                 *      Go from hint to end of list.
                    550:                 *
                    551:                 *      But first, make a quick check to see if
                    552:                 *      we are already looking at the entry we
                    553:                 *      want (which is usually the case).
                    554:                 *      Note also that we don't need to save the hint
                    555:                 *      here... it is the same hint (unless we are
                    556:                 *      at the header, in which case the hint didn't
                    557:                 *      buy us anything anyway).
                    558:                 */
                    559:                last = &map->header;
                    560:                if ((cur != last) && (cur->end > address)) {
                    561:                        *entry = cur;
                    562:                        return(TRUE);
                    563:                }
                    564:        }
                    565:        else {
                    566:                /*
                    567:                 *      Go from start to hint, *inclusively*
                    568:                 */
                    569:                last = cur->next;
                    570:                cur = map->header.next;
                    571:        }
                    572: 
                    573:        /*
                    574:         *      Search linearly
                    575:         */
                    576: 
                    577:        while (cur != last) {
                    578:                if (cur->end > address) {
                    579:                        if (address >= cur->start) {
                    580:                                /*
                    581:                                 *      Save this lookup for future
                    582:                                 *      hints, and return
                    583:                                 */
                    584: 
                    585:                                *entry = cur;
                    586:                                SAVE_HINT(map, cur);
                    587:                                return(TRUE);
                    588:                        }
                    589:                        break;
                    590:                }
                    591:                cur = cur->next;
                    592:        }
                    593:        *entry = cur->prev;
                    594:        SAVE_HINT(map, *entry);
                    595:        return(FALSE);
                    596: }
                    597: 
                    598: /*
                    599:  *     vm_map_find finds an unallocated region in the target address
                    600:  *     map with the given length.  The search is defined to be
                    601:  *     first-fit from the specified address; the region found is
                    602:  *     returned in the same parameter.
                    603:  *
                    604:  */
                    605: vm_map_find(map, object, offset, addr, length, find_space)
                    606:        vm_map_t        map;
                    607:        vm_object_t     object;
                    608:        vm_offset_t     offset;
                    609:        vm_offset_t     *addr;          /* IN/OUT */
                    610:        vm_size_t       length;
                    611:        boolean_t       find_space;
                    612: {
                    613:        register vm_map_entry_t entry;
                    614:        register vm_offset_t    start;
                    615:        register vm_offset_t    end;
                    616:        int                     result;
                    617: 
                    618:        start = *addr;
                    619: 
                    620:        vm_map_lock(map);
                    621: 
                    622:        if (find_space) {
                    623:                /*
                    624:                 *      Calculate the first possible address.
                    625:                 */
                    626: 
                    627:                if (start < map->min_offset)
                    628:                        start = map->min_offset;
                    629:                if (start > map->max_offset) {
                    630:                        vm_map_unlock(map);
                    631:                        return (KERN_NO_SPACE);
                    632:                }
                    633: 
                    634:                /*
                    635:                 *      Look for the first possible address;
                    636:                 *      if there's already something at this
                    637:                 *      address, we have to start after it.
                    638:                 */
                    639: 
                    640:                if (start == map->min_offset) {
                    641:                        if ((entry = map->first_free) != &map->header)
                    642:                                start = entry->end;
                    643:                } else {
                    644:                        vm_map_entry_t  tmp_entry;
                    645:                        if (vm_map_lookup_entry(map, start, &tmp_entry))
                    646:                                start = tmp_entry->end;
                    647:                        entry = tmp_entry;
                    648:                }
                    649: 
                    650:                /*
                    651:                 *      In any case, the "entry" always precedes
                    652:                 *      the proposed new region throughout the
                    653:                 *      loop:
                    654:                 */
                    655: 
                    656:                while (TRUE) {
                    657:                        register vm_map_entry_t next;
                    658: 
                    659:                        /*
                    660:                         *      Find the end of the proposed new region.
                    661:                         *      Be sure we didn't go beyond the end, or
                    662:                         *      wrap around the address.
                    663:                         */
                    664: 
                    665:                        end = start + length;
                    666: 
                    667:                        if ((end > map->max_offset) || (end < start)) {
                    668:                                vm_map_unlock(map);
                    669:                                return (KERN_NO_SPACE);
                    670:                        }
                    671: 
                    672:                        /*
                    673:                         *      If there are no more entries, we must win.
                    674:                         */
                    675: 
                    676:                        next = entry->next;
                    677:                        if (next == &map->header)
                    678:                                break;
                    679: 
                    680:                        /*
                    681:                         *      If there is another entry, it must be
                    682:                         *      after the end of the potential new region.
                    683:                         */
                    684: 
                    685:                        if (next->start >= end)
                    686:                                break;
                    687: 
                    688:                        /*
                    689:                         *      Didn't fit -- move to the next entry.
                    690:                         */
                    691: 
                    692:                        entry = next;
                    693:                        start = entry->end;
                    694:                }
                    695:                *addr = start;
                    696:                
                    697:                SAVE_HINT(map, entry);
                    698:        }
                    699: 
                    700:        result = vm_map_insert(map, object, offset, start, start + length);
                    701: 
                    702:        vm_map_unlock(map);
                    703:        return(result);
                    704: }
                    705: 
                    706: /*
                    707:  *     vm_map_simplify_entry:  [ internal use only ]
                    708:  *
                    709:  *     Simplify the given map entry by:
                    710:  *             removing extra sharing maps
                    711:  *             [XXX maybe later] merging with a neighbor
                    712:  */
                    713: void vm_map_simplify_entry(map, entry)
                    714:        vm_map_t        map;
                    715:        vm_map_entry_t  entry;
                    716: {
                    717: #ifdef lint
                    718:        map++;
                    719: #endif lint
                    720: 
                    721:        /*
                    722:         *      If this entry corresponds to a sharing map, then
                    723:         *      see if we can remove the level of indirection.
                    724:         *      If it's not a sharing map, then it points to
                    725:         *      a VM object, so see if we can merge with either
                    726:         *      of our neighbors.
                    727:         */
                    728: 
                    729:        if (entry->is_sub_map)
                    730:                return;
                    731:        if (entry->is_a_map) {
                    732: #if    0
                    733:                vm_map_t        my_share_map;
                    734:                int             count;
                    735: 
                    736:                my_share_map = entry->object.share_map; 
                    737:                simple_lock(&my_share_map->ref_lock);
                    738:                count = my_share_map->ref_count;
                    739:                simple_unlock(&my_share_map->ref_lock);
                    740:                
                    741:                if (count == 1) {
                    742:                        /* Can move the region from
                    743:                         * entry->start to entry->end (+ entry->offset)
                    744:                         * in my_share_map into place of entry.
                    745:                         * Later.
                    746:                         */
                    747:                }
                    748: #endif 0
                    749:        }
                    750:        else {
                    751:                /*
                    752:                 *      Try to merge with our neighbors.
                    753:                 *
                    754:                 *      Conditions for merge are:
                    755:                 *
                    756:                 *      1.  entries are adjacent.
                    757:                 *      2.  both entries point to objects
                    758:                 *          with null pagers.
                    759:                 *
                    760:                 *      If a merge is possible, we replace the two
                    761:                 *      entries with a single entry, then merge
                    762:                 *      the two objects into a single object.
                    763:                 *
                    764:                 *      Now, all that is left to do is write the
                    765:                 *      code!
                    766:                 */
                    767:        }
                    768: }
                    769: 
                    770: /*
                    771:  *     vm_map_clip_start:      [ internal use only ]
                    772:  *
                    773:  *     Asserts that the given entry begins at or after
                    774:  *     the specified address; if necessary,
                    775:  *     it splits the entry into two.
                    776:  */
                    777: #define vm_map_clip_start(map, entry, startaddr) \
                    778: { \
                    779:        if (startaddr > entry->start) \
                    780:                _vm_map_clip_start(map, entry, startaddr); \
                    781: }
                    782: 
                    783: /*
                    784:  *     This routine is called only when it is known that
                    785:  *     the entry must be split.
                    786:  */
                    787: void _vm_map_clip_start(map, entry, start)
                    788:        register vm_map_t       map;
                    789:        register vm_map_entry_t entry;
                    790:        register vm_offset_t    start;
                    791: {
                    792:        register vm_map_entry_t new_entry;
                    793: 
                    794:        /*
                    795:         *      See if we can simplify this entry first
                    796:         */
                    797:                 
                    798:        vm_map_simplify_entry(map, entry);
                    799: 
                    800:        /*
                    801:         *      Split off the front portion --
                    802:         *      note that we must insert the new
                    803:         *      entry BEFORE this one, so that
                    804:         *      this entry has the specified starting
                    805:         *      address.
                    806:         */
                    807: 
                    808:        new_entry = vm_map_entry_create(map);
                    809:        *new_entry = *entry;
                    810: 
                    811:        new_entry->end = start;
                    812:        entry->offset += (start - entry->start);
                    813:        entry->start = start;
                    814: 
                    815:        vm_map_entry_link(map, entry->prev, new_entry);
                    816: 
                    817:        if (entry->is_a_map || entry->is_sub_map)
                    818:                vm_map_reference(new_entry->object.share_map);
                    819:        else
                    820:                vm_object_reference(new_entry->object.vm_object);
                    821: }
                    822: 
                    823: /*
                    824:  *     vm_map_clip_end:        [ internal use only ]
                    825:  *
                    826:  *     Asserts that the given entry ends at or before
                    827:  *     the specified address; if necessary,
                    828:  *     it splits the entry into two.
                    829:  */
                    830: 
                    831: void _vm_map_clip_end();
                    832: #define vm_map_clip_end(map, entry, endaddr) \
                    833: { \
                    834:        if (endaddr < entry->end) \
                    835:                _vm_map_clip_end(map, entry, endaddr); \
                    836: }
                    837: 
                    838: /*
                    839:  *     This routine is called only when it is known that
                    840:  *     the entry must be split.
                    841:  */
                    842: void _vm_map_clip_end(map, entry, end)
                    843:        register vm_map_t       map;
                    844:        register vm_map_entry_t entry;
                    845:        register vm_offset_t    end;
                    846: {
                    847:        register vm_map_entry_t new_entry;
                    848: 
                    849:        /*
                    850:         *      Create a new entry and insert it
                    851:         *      AFTER the specified entry
                    852:         */
                    853: 
                    854:        new_entry = vm_map_entry_create(map);
                    855:        *new_entry = *entry;
                    856: 
                    857:        new_entry->start = entry->end = end;
                    858:        new_entry->offset += (end - entry->start);
                    859: 
                    860:        vm_map_entry_link(map, entry, new_entry);
                    861: 
                    862:        if (entry->is_a_map || entry->is_sub_map)
                    863:                vm_map_reference(new_entry->object.share_map);
                    864:        else
                    865:                vm_object_reference(new_entry->object.vm_object);
                    866: }
                    867: 
                    868: /*
                    869:  *     VM_MAP_RANGE_CHECK:     [ internal use only ]
                    870:  *
                    871:  *     Asserts that the starting and ending region
                    872:  *     addresses fall within the valid range of the map.
                    873:  */
                    874: #define        VM_MAP_RANGE_CHECK(map, start, end)             \
                    875:                {                                       \
                    876:                if (start < vm_map_min(map))            \
                    877:                        start = vm_map_min(map);        \
                    878:                if (end > vm_map_max(map))              \
                    879:                        end = vm_map_max(map);          \
                    880:                if (start > end)                        \
                    881:                        start = end;                    \
                    882:                }
                    883: 
                    884: /*
                    885:  *     vm_map_submap:          [ kernel use only ]
                    886:  *
                    887:  *     Mark the given range as handled by a subordinate map.
                    888:  *
                    889:  *     This range must have been created with vm_map_find,
                    890:  *     and no other operations may have been performed on this
                    891:  *     range prior to calling vm_map_submap.
                    892:  *
                    893:  *     Only a limited number of operations can be performed
                    894:  *     within this rage after calling vm_map_submap:
                    895:  *             vm_fault
                    896:  *     [Don't try vm_map_copy!]
                    897:  *
                    898:  *     To remove a submapping, one must first remove the
                    899:  *     range from the superior map, and then destroy the
                    900:  *     submap (if desired).  [Better yet, don't try it.]
                    901:  */
                    902: vm_map_submap(map, start, end, submap)
                    903:        register vm_map_t       map;
                    904:        register vm_offset_t    start;
                    905:        register vm_offset_t    end;
                    906:        vm_map_t                submap;
                    907: {
                    908:        vm_map_entry_t          entry;
                    909:        register int            result = KERN_INVALID_ARGUMENT;
                    910: 
                    911:        vm_map_lock(map);
                    912: 
                    913:        VM_MAP_RANGE_CHECK(map, start, end);
                    914: 
                    915:        if (vm_map_lookup_entry(map, start, &entry)) {
                    916:                vm_map_clip_start(map, entry, start);
                    917:        }
                    918:         else
                    919:                entry = entry->next;
                    920: 
                    921:        vm_map_clip_end(map, entry, end);
                    922: 
                    923:        if ((entry->start == start) && (entry->end == end) &&
                    924:            (!entry->is_a_map) &&
                    925:            (entry->object.vm_object == NULL) &&
                    926:            (!entry->copy_on_write)) {
                    927:                entry->is_a_map = FALSE;
                    928:                entry->is_sub_map = TRUE;
                    929:                vm_map_reference(entry->object.sub_map = submap);
                    930:                result = KERN_SUCCESS;
                    931:        }
                    932:        vm_map_unlock(map);
                    933: 
                    934:        return(result);
                    935: }
                    936: 
                    937: /*
                    938:  *     vm_map_protect:
                    939:  *
                    940:  *     Sets the protection of the specified address
                    941:  *     region in the target map.  If "set_max" is
                    942:  *     specified, the maximum protection is to be set;
                    943:  *     otherwise, only the current protection is affected.
                    944:  */
                    945: vm_map_protect(map, start, end, new_prot, set_max)
                    946:        register vm_map_t       map;
                    947:        register vm_offset_t    start;
                    948:        register vm_offset_t    end;
                    949:        register vm_prot_t      new_prot;
                    950:        register boolean_t      set_max;
                    951: {
                    952:        register vm_map_entry_t         current;
                    953:        vm_map_entry_t                  entry;
                    954: 
                    955:        vm_map_lock(map);
                    956: 
                    957:        VM_MAP_RANGE_CHECK(map, start, end);
                    958: 
                    959:        if (vm_map_lookup_entry(map, start, &entry)) {
                    960:                vm_map_clip_start(map, entry, start);
                    961:        }
                    962:         else
                    963:                entry = entry->next;
                    964: 
                    965:        /*
                    966:         *      Make a first pass to check for protection
                    967:         *      violations.
                    968:         */
                    969: 
                    970:        current = entry;
                    971:        while ((current != &map->header) && (current->start < end)) {
                    972:                if (current->is_sub_map)
                    973:                        return(KERN_INVALID_ARGUMENT);
                    974:                if ((new_prot & current->max_protection) != new_prot) {
                    975:                        vm_map_unlock(map);
                    976:                        return(KERN_PROTECTION_FAILURE);
                    977:                }
                    978: 
                    979:                current = current->next;
                    980:        }
                    981: 
                    982:        /*
                    983:         *      Go back and fix up protections.
                    984:         *      [Note that clipping is not necessary the second time.]
                    985:         */
                    986: 
                    987:        current = entry;
                    988: 
                    989:        while ((current != &map->header) && (current->start < end)) {
                    990:                vm_prot_t       old_prot;
                    991: 
                    992:                vm_map_clip_end(map, current, end);
                    993: 
                    994:                old_prot = current->protection;
                    995:                if (set_max)
                    996:                        current->protection =
                    997:                                (current->max_protection = new_prot) &
                    998:                                        old_prot;
                    999:                else
                   1000:                        current->protection = new_prot;
                   1001: 
                   1002:                /*
                   1003:                 *      Update physical map if necessary.
                   1004:                 *      Worry about copy-on-write here -- CHECK THIS XXX
                   1005:                 */
                   1006: 
                   1007:                if (current->protection != old_prot) {
                   1008: 
                   1009: #define MASK(entry)    ((entry)->copy_on_write ? ~VM_PROT_WRITE : \
                   1010:                                                        VM_PROT_ALL)
                   1011: #define        max(a,b)        ((a) > (b) ? (a) : (b))
                   1012: 
                   1013:                        if (current->is_a_map) {
                   1014:                                vm_map_entry_t  share_entry;
                   1015:                                vm_offset_t     share_end;
                   1016: 
                   1017:                                vm_map_lock(current->object.share_map);
                   1018:                                (void) vm_map_lookup_entry(
                   1019:                                                current->object.share_map,
                   1020:                                                current->offset,
                   1021:                                                &share_entry);
                   1022:                                share_end = current->offset +
                   1023:                                        (current->end - current->start);
                   1024:                                while ((share_entry !=
                   1025:                                        &current->object.share_map->header) &&
                   1026:                                        (share_entry->start < share_end)) {
                   1027: 
                   1028:                                        pmap_protect(map->pmap,
                   1029:                                                (max(share_entry->start,
                   1030:                                                        current->offset) -
                   1031:                                                        current->offset +
                   1032:                                                        current->start),
                   1033:                                                min(share_entry->end,
                   1034:                                                        share_end) -
                   1035:                                                current->offset +
                   1036:                                                current->start,
                   1037:                                                current->protection &
                   1038:                                                        MASK(share_entry));
                   1039: 
                   1040:                                        share_entry = share_entry->next;
                   1041:                                }
                   1042:                                vm_map_unlock(current->object.share_map);
                   1043:                        }
                   1044:                        else
                   1045:                                pmap_protect(map->pmap, current->start,
                   1046:                                        current->end,
                   1047:                                        current->protection & MASK(entry));
                   1048: #undef max
                   1049: #undef MASK
                   1050:                }
                   1051:                current = current->next;
                   1052:        }
                   1053: 
                   1054:        vm_map_unlock(map);
                   1055:        return(KERN_SUCCESS);
                   1056: }
                   1057: 
                   1058: /*
                   1059:  *     vm_map_inherit:
                   1060:  *
                   1061:  *     Sets the inheritance of the specified address
                   1062:  *     range in the target map.  Inheritance
                   1063:  *     affects how the map will be shared with
                   1064:  *     child maps at the time of vm_map_fork.
                   1065:  */
                   1066: vm_map_inherit(map, start, end, new_inheritance)
                   1067:        register vm_map_t       map;
                   1068:        register vm_offset_t    start;
                   1069:        register vm_offset_t    end;
                   1070:        register vm_inherit_t   new_inheritance;
                   1071: {
                   1072:        register vm_map_entry_t entry;
                   1073:        vm_map_entry_t  temp_entry;
                   1074: 
                   1075:        switch (new_inheritance) {
                   1076:        case VM_INHERIT_NONE:
                   1077:        case VM_INHERIT_COPY:
                   1078:        case VM_INHERIT_SHARE:
                   1079:                break;
                   1080:        default:
                   1081:                return(KERN_INVALID_ARGUMENT);
                   1082:        }
                   1083: 
                   1084:        vm_map_lock(map);
                   1085: 
                   1086:        VM_MAP_RANGE_CHECK(map, start, end);
                   1087: 
                   1088:        if (vm_map_lookup_entry(map, start, &temp_entry)) {
                   1089:                entry = temp_entry;
                   1090:                vm_map_clip_start(map, entry, start);
                   1091:        }
                   1092:        else
                   1093:                entry = temp_entry->next;
                   1094: 
                   1095:        while ((entry != &map->header) && (entry->start < end)) {
                   1096:                vm_map_clip_end(map, entry, end);
                   1097: 
                   1098:                entry->inheritance = new_inheritance;
                   1099: 
                   1100:                entry = entry->next;
                   1101:        }
                   1102: 
                   1103:        vm_map_unlock(map);
                   1104:        return(KERN_SUCCESS);
                   1105: }
                   1106: 
                   1107: /*
                   1108:  *     vm_map_pageable:
                   1109:  *
                   1110:  *     Sets the pageability of the specified address
                   1111:  *     range in the target map.  Regions specified
                   1112:  *     as not pageable require locked-down physical
                   1113:  *     memory and physical page maps.
                   1114:  *
                   1115:  *     The map must not be locked, but a reference
                   1116:  *     must remain to the map throughout the call.
                   1117:  */
                   1118: vm_map_pageable(map, start, end, new_pageable)
                   1119:        register vm_map_t       map;
                   1120:        register vm_offset_t    start;
                   1121:        register vm_offset_t    end;
                   1122:        register boolean_t      new_pageable;
                   1123: {
                   1124:        register vm_map_entry_t entry;
                   1125:        vm_map_entry_t          temp_entry;
                   1126: 
                   1127:        vm_map_lock(map);
                   1128: 
                   1129:        VM_MAP_RANGE_CHECK(map, start, end);
                   1130: 
                   1131:        /*
                   1132:         *      Only one pageability change may take place at one
                   1133:         *      time, since vm_fault assumes it will be called
                   1134:         *      only once for each wiring/unwiring.  Therefore, we
                   1135:         *      have to make sure we're actually changing the pageability
                   1136:         *      for the entire region.  We do so before making any changes.
                   1137:         */
                   1138: 
                   1139:        if (vm_map_lookup_entry(map, start, &temp_entry)) {
                   1140:                entry = temp_entry;
                   1141:                vm_map_clip_start(map, entry, start);
                   1142:        }
                   1143:        else
                   1144:                entry = temp_entry->next;
                   1145:        temp_entry = entry;
                   1146: 
                   1147:        /*
                   1148:         *      Actions are rather different for wiring and unwiring,
                   1149:         *      so we have two separate cases.
                   1150:         */
                   1151: 
                   1152:        if (new_pageable) {
                   1153: 
                   1154:                /*
                   1155:                 *      Unwiring.  First ensure that the range to be
                   1156:                 *      unwired is really wired down.
                   1157:                 */
                   1158:                while ((entry != &map->header) && (entry->start < end)) {
                   1159: 
                   1160:                    if (entry->wired_count == 0) {
                   1161:                        vm_map_unlock(map);
                   1162:                        return(KERN_INVALID_ARGUMENT);
                   1163:                    }
                   1164:                    entry = entry->next;
                   1165:                }
                   1166: 
                   1167:                /*
                   1168:                 *      Now decrement the wiring count for each region.
                   1169:                 *      If a region becomes completely unwired,
                   1170:                 *      unwire its physical pages and mappings.
                   1171:                 */
                   1172:                lock_set_recursive(&map->lock);
                   1173: 
                   1174:                entry = temp_entry;
                   1175:                while ((entry != &map->header) && (entry->start < end)) {
                   1176:                    vm_map_clip_end(map, entry, end);
                   1177: 
                   1178:                    entry->wired_count--;
                   1179:                    if (entry->wired_count == 0)
                   1180:                        vm_fault_unwire(map, entry->start, entry->end);
                   1181: 
                   1182:                    entry = entry->next;
                   1183:                }
                   1184:                lock_clear_recursive(&map->lock);
                   1185:        }
                   1186: 
                   1187:        else {
                   1188:                /*
                   1189:                 *      Wiring.  We must do this in two passes:
                   1190:                 *
                   1191:                 *      1.  Holding the write lock, we increment the
                   1192:                 *          wiring count.  For any area that is not already
                   1193:                 *          wired, we create any shadow objects that need
                   1194:                 *          to be created.
                   1195:                 *
                   1196:                 *      2.  We downgrade to a read lock, and call
                   1197:                 *          vm_fault_wire to fault in the pages for any
                   1198:                 *          newly wired area (wired_count is 1).
                   1199:                 *
                   1200:                 *      Downgrading to a read lock for vm_fault_wire avoids
                   1201:                 *      a possible deadlock with another thread that may have
                   1202:                 *      faulted on one of the pages to be wired (it would mark
                   1203:                 *      the page busy, blocking us, then in turn block on the
                   1204:                 *      map lock that we hold).  Because of problems in the
                   1205:                 *      recursive lock package, we cannot upgrade to a write
                   1206:                 *      lock in vm_map_lookup.  Thus, any actions that require
                   1207:                 *      the write lock must be done beforehand.  Because we
                   1208:                 *      keep the read lock on the map, the copy-on-write status
                   1209:                 *      of the entries we modify here cannot change.
                   1210:                 */
                   1211: 
                   1212:                /*
                   1213:                 *      Pass 1.
                   1214:                 */
                   1215:                entry = temp_entry;
                   1216:                while ((entry != &map->header) && (entry->start < end)) {
                   1217:                    vm_map_clip_end(map, entry, end);
                   1218: 
                   1219:                    entry->wired_count++;
                   1220:                    if (entry->wired_count == 1) {
                   1221: 
                   1222:                        /*
                   1223:                         *      Perform actions of vm_map_lookup that need
                   1224:                         *      the write lock on the map: create a shadow
                   1225:                         *      object for a copy-on-write region, or an
                   1226:                         *      object for a zero-fill region.
                   1227:                         *
                   1228:                         *      We don't have to do this for entries that
                   1229:                         *      point to sharing maps, because we won't hold
                   1230:                         *      the lock on the sharing map.
                   1231:                         */
                   1232:                        if (!entry->is_a_map) {
                   1233:                            if (entry->needs_copy &&
                   1234:                                ((entry->protection & VM_PROT_WRITE) != 0)) {
                   1235: 
                   1236:                                vm_object_shadow(&entry->object.vm_object,
                   1237:                                                &entry->offset,
                   1238:                                                (vm_size_t)(entry->end
                   1239:                                                        - entry->start));
                   1240:                                entry->needs_copy = FALSE;
                   1241:                            }
                   1242:                            else if (entry->object.vm_object == NULL) {
                   1243:                                entry->object.vm_object =
                   1244:                                    vm_object_allocate((vm_size_t)(entry->end
                   1245:                                                        - entry->start));
                   1246:                                entry->offset = (vm_offset_t)0;
                   1247:                            }
                   1248:                        }
                   1249:                    }
                   1250: 
                   1251:                    entry = entry->next;
                   1252:                }
                   1253: 
                   1254:                /*
                   1255:                 *      Pass 2.
                   1256:                 */
                   1257: 
                   1258:                /*
                   1259:                 * HACK HACK HACK HACK
                   1260:                 *
                   1261:                 * If we are wiring in the kernel map or a submap of it,
                   1262:                 * unlock the map to avoid deadlocks.  We trust that the
                   1263:                 * kernel threads are well-behaved, and therefore will
                   1264:                 * not do anything destructive to this region of the map
                   1265:                 * while we have it unlocked.  We cannot trust user threads
                   1266:                 * to do the same.
                   1267:                 *
                   1268:                 * HACK HACK HACK HACK
                   1269:                 */
                   1270:                if (vm_map_pmap(map) == kernel_pmap) {
                   1271:                    vm_map_unlock(map);         /* trust me ... */
                   1272:                }
                   1273:                else {
                   1274:                    lock_set_recursive(&map->lock);
                   1275:                    lock_write_to_read(&map->lock);
                   1276:                }
                   1277: 
                   1278:                entry = temp_entry;
                   1279:                while (entry != &map->header && entry->start < end) {
                   1280:                    if (entry->wired_count == 1) {
                   1281:                        vm_fault_wire(map, entry->start, entry->end);
                   1282:                    }
                   1283:                    entry = entry->next;
                   1284:                }
                   1285: 
                   1286:                if (vm_map_pmap(map) == kernel_pmap) {
                   1287:                    vm_map_lock(map);
                   1288:                }
                   1289:                else {
                   1290:                    lock_clear_recursive(&map->lock);
                   1291:                }
                   1292:        }
                   1293: 
                   1294:        vm_map_unlock(map);
                   1295: 
                   1296:        return(KERN_SUCCESS);
                   1297: }
                   1298: 
                   1299: /*
                   1300:  *     vm_map_entry_unwire:    [ internal use only ]
                   1301:  *
                   1302:  *     Make the region specified by this entry pageable.
                   1303:  *
                   1304:  *     The map in question should be locked.
                   1305:  *     [This is the reason for this routine's existence.]
                   1306:  */
                   1307: void vm_map_entry_unwire(map, entry)
                   1308:        vm_map_t                map;
                   1309:        register vm_map_entry_t entry;
                   1310: {
                   1311:        vm_fault_unwire(map, entry->start, entry->end);
                   1312:        entry->wired_count = 0;
                   1313: }
                   1314: 
                   1315: /*
                   1316:  *     vm_map_entry_delete:    [ internal use only ]
                   1317:  *
                   1318:  *     Deallocate the given entry from the target map.
                   1319:  */            
                   1320: void vm_map_entry_delete(map, entry)
                   1321:        register vm_map_t       map;
                   1322:        register vm_map_entry_t entry;
                   1323: {
                   1324:        if (entry->wired_count != 0)
                   1325:                vm_map_entry_unwire(map, entry);
                   1326:                
                   1327:        vm_map_entry_unlink(map, entry);
                   1328:        map->size -= entry->end - entry->start;
                   1329: 
                   1330:        if (entry->is_a_map || entry->is_sub_map)
                   1331:                vm_map_deallocate(entry->object.share_map);
                   1332:        else
                   1333:                vm_object_deallocate(entry->object.vm_object);
                   1334: 
                   1335:        vm_map_entry_dispose(map, entry);
                   1336: }
                   1337: 
                   1338: /*
                   1339:  *     vm_map_delete:  [ internal use only ]
                   1340:  *
                   1341:  *     Deallocates the given address range from the target
                   1342:  *     map.
                   1343:  *
                   1344:  *     When called with a sharing map, removes pages from
                   1345:  *     that region from all physical maps.
                   1346:  */
                   1347: vm_map_delete(map, start, end)
                   1348:        register vm_map_t       map;
                   1349:        vm_offset_t             start;
                   1350:        register vm_offset_t    end;
                   1351: {
                   1352:        register vm_map_entry_t entry;
                   1353:        vm_map_entry_t          first_entry;
                   1354: 
                   1355:        /*
                   1356:         *      Find the start of the region, and clip it
                   1357:         */
                   1358: 
                   1359:        if (!vm_map_lookup_entry(map, start, &first_entry))
                   1360:                entry = first_entry->next;
                   1361:        else {
                   1362:                entry = first_entry;
                   1363:                vm_map_clip_start(map, entry, start);
                   1364: 
                   1365:                /*
                   1366:                 *      Fix the lookup hint now, rather than each
                   1367:                 *      time though the loop.
                   1368:                 */
                   1369: 
                   1370:                SAVE_HINT(map, entry->prev);
                   1371:        }
                   1372: 
                   1373:        /*
                   1374:         *      Save the free space hint
                   1375:         */
                   1376: 
                   1377:        if (map->first_free->start >= start)
                   1378:                map->first_free = entry->prev;
                   1379: 
                   1380:        /*
                   1381:         *      Step through all entries in this region
                   1382:         */
                   1383: 
                   1384:        while ((entry != &map->header) && (entry->start < end)) {
                   1385:                vm_map_entry_t          next;
                   1386:                register vm_offset_t    s, e;
                   1387:                register vm_object_t    object;
                   1388: 
                   1389:                vm_map_clip_end(map, entry, end);
                   1390: 
                   1391:                next = entry->next;
                   1392:                s = entry->start;
                   1393:                e = entry->end;
                   1394: 
                   1395:                /*
                   1396:                 *      Unwire before removing addresses from the pmap;
                   1397:                 *      otherwise, unwiring will put the entries back in
                   1398:                 *      the pmap.
                   1399:                 */
                   1400: 
                   1401:                object = entry->object.vm_object;
                   1402:                if (entry->wired_count != 0)
                   1403:                        vm_map_entry_unwire(map, entry);
                   1404: 
                   1405:                /*
                   1406:                 *      If this is a sharing map, we must remove
                   1407:                 *      *all* references to this data, since we can't
                   1408:                 *      find all of the physical maps which are sharing
                   1409:                 *      it.
                   1410:                 */
                   1411: 
                   1412:                if (object == kernel_object || object == kmem_object)
                   1413:                        vm_object_page_remove(object, entry->offset,
                   1414:                                        entry->offset + (e - s));
                   1415:                else if (!map->is_main_map)
                   1416:                        vm_object_pmap_remove(object,
                   1417:                                         entry->offset,
                   1418:                                         entry->offset + (e - s));
                   1419:                else
                   1420:                        pmap_remove(map->pmap, s, e);
                   1421: 
                   1422:                /*
                   1423:                 *      Delete the entry (which may delete the object)
                   1424:                 *      only after removing all pmap entries pointing
                   1425:                 *      to its pages.  (Otherwise, its page frames may
                   1426:                 *      be reallocated, and any modify bits will be
                   1427:                 *      set in the wrong object!)
                   1428:                 */
                   1429: 
                   1430:                vm_map_entry_delete(map, entry);
                   1431:                entry = next;
                   1432:        }
                   1433:        return(KERN_SUCCESS);
                   1434: }
                   1435: 
                   1436: /*
                   1437:  *     vm_map_remove:
                   1438:  *
                   1439:  *     Remove the given address range from the target map.
                   1440:  *     This is the exported form of vm_map_delete.
                   1441:  */
                   1442: vm_map_remove(map, start, end)
                   1443:        register vm_map_t       map;
                   1444:        register vm_offset_t    start;
                   1445:        register vm_offset_t    end;
                   1446: {
                   1447:        register int            result;
                   1448: 
                   1449:        vm_map_lock(map);
                   1450:        VM_MAP_RANGE_CHECK(map, start, end);
                   1451:        result = vm_map_delete(map, start, end);
                   1452:        vm_map_unlock(map);
                   1453: 
                   1454:        return(result);
                   1455: }
                   1456: 
                   1457: /*
                   1458:  *     vm_map_check_protection:
                   1459:  *
                   1460:  *     Assert that the target map allows the specified
                   1461:  *     privilege on the entire address region given.
                   1462:  *     The entire region must be allocated.
                   1463:  */
                   1464: boolean_t vm_map_check_protection(map, start, end, protection)
                   1465:        register vm_map_t       map;
                   1466:        register vm_offset_t    start;
                   1467:        register vm_offset_t    end;
                   1468:        register vm_prot_t      protection;
                   1469: {
                   1470:        register vm_map_entry_t entry;
                   1471:        vm_map_entry_t          tmp_entry;
                   1472: 
                   1473:        if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   1474:                return(FALSE);
                   1475:        }
                   1476: 
                   1477:        entry = tmp_entry;
                   1478: 
                   1479:        while (start < end) {
                   1480:                if (entry == &map->header) {
                   1481:                        return(FALSE);
                   1482:                }
                   1483: 
                   1484:                /*
                   1485:                 *      No holes allowed!
                   1486:                 */
                   1487: 
                   1488:                if (start < entry->start) {
                   1489:                        return(FALSE);
                   1490:                }
                   1491: 
                   1492:                /*
                   1493:                 * Check protection associated with entry.
                   1494:                 */
                   1495: 
                   1496:                if ((entry->protection & protection) != protection) {
                   1497:                        return(FALSE);
                   1498:                }
                   1499: 
                   1500:                /* go to next entry */
                   1501: 
                   1502:                start = entry->end;
                   1503:                entry = entry->next;
                   1504:        }
                   1505:        return(TRUE);
                   1506: }
                   1507: 
                   1508: /*
                   1509:  *     vm_map_copy_entry:
                   1510:  *
                   1511:  *     Copies the contents of the source entry to the destination
                   1512:  *     entry.  The entries *must* be aligned properly.
                   1513:  */
                   1514: void vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry)
                   1515:        vm_map_t                src_map, dst_map;
                   1516:        register vm_map_entry_t src_entry, dst_entry;
                   1517: {
                   1518:        vm_object_t     temp_object;
                   1519: 
                   1520:        if (src_entry->is_sub_map || dst_entry->is_sub_map)
                   1521:                return;
                   1522: 
                   1523:        if (dst_entry->object.vm_object != NULL &&
                   1524:            !dst_entry->object.vm_object->internal)
                   1525:                printf("vm_map_copy_entry: copying over permanent data!\n");
                   1526: 
                   1527:        /*
                   1528:         *      If our destination map was wired down,
                   1529:         *      unwire it now.
                   1530:         */
                   1531: 
                   1532:        if (dst_entry->wired_count != 0)
                   1533:                vm_map_entry_unwire(dst_map, dst_entry);
                   1534: 
                   1535:        /*
                   1536:         *      If we're dealing with a sharing map, we
                   1537:         *      must remove the destination pages from
                   1538:         *      all maps (since we cannot know which maps
                   1539:         *      this sharing map belongs in).
                   1540:         */
                   1541: 
                   1542:        if (dst_map->is_main_map)
                   1543:                pmap_remove(dst_map->pmap, dst_entry->start, dst_entry->end);
                   1544:        else
                   1545:                vm_object_pmap_remove(dst_entry->object.vm_object,
                   1546:                        dst_entry->offset,
                   1547:                        dst_entry->offset +
                   1548:                                (dst_entry->end - dst_entry->start));
                   1549: 
                   1550:        if (src_entry->wired_count == 0) {
                   1551: 
                   1552:                boolean_t       src_needs_copy;
                   1553: 
                   1554:                /*
                   1555:                 *      If the source entry is marked needs_copy,
                   1556:                 *      it is already write-protected.
                   1557:                 */
                   1558:                if (!src_entry->needs_copy) {
                   1559: 
                   1560:                        boolean_t       su;
                   1561: 
                   1562:                        /*
                   1563:                         *      If the source entry has only one mapping,
                   1564:                         *      we can just protect the virtual address
                   1565:                         *      range.
                   1566:                         */
                   1567:                        if (!(su = src_map->is_main_map)) {
                   1568:                                simple_lock(&src_map->ref_lock);
                   1569:                                su = (src_map->ref_count == 1);
                   1570:                                simple_unlock(&src_map->ref_lock);
                   1571:                        }
                   1572: 
                   1573:                        if (su) {
                   1574:                                pmap_protect(src_map->pmap,
                   1575:                                        src_entry->start,
                   1576:                                        src_entry->end,
                   1577:                                        src_entry->protection & ~VM_PROT_WRITE);
                   1578:                        }
                   1579:                        else {
                   1580:                                vm_object_pmap_copy(src_entry->object.vm_object,
                   1581:                                        src_entry->offset,
                   1582:                                        src_entry->offset + (src_entry->end
                   1583:                                                            -src_entry->start));
                   1584:                        }
                   1585:                }
                   1586: 
                   1587:                /*
                   1588:                 *      Make a copy of the object.
                   1589:                 */
                   1590:                temp_object = dst_entry->object.vm_object;
                   1591:                vm_object_copy(src_entry->object.vm_object,
                   1592:                                src_entry->offset,
                   1593:                                (vm_size_t)(src_entry->end -
                   1594:                                            src_entry->start),
                   1595:                                &dst_entry->object.vm_object,
                   1596:                                &dst_entry->offset,
                   1597:                                &src_needs_copy);
                   1598:                /*
                   1599:                 *      If we didn't get a copy-object now, mark the
                   1600:                 *      source map entry so that a shadow will be created
                   1601:                 *      to hold its changed pages.
                   1602:                 */
                   1603:                if (src_needs_copy)
                   1604:                        src_entry->needs_copy = TRUE;
                   1605: 
                   1606:                /*
                   1607:                 *      The destination always needs to have a shadow
                   1608:                 *      created.
                   1609:                 */
                   1610:                dst_entry->needs_copy = TRUE;
                   1611: 
                   1612:                /*
                   1613:                 *      Mark the entries copy-on-write, so that write-enabling
                   1614:                 *      the entry won't make copy-on-write pages writable.
                   1615:                 */
                   1616:                src_entry->copy_on_write = TRUE;
                   1617:                dst_entry->copy_on_write = TRUE;
                   1618:                /*
                   1619:                 *      Get rid of the old object.
                   1620:                 */
                   1621:                vm_object_deallocate(temp_object);
                   1622: 
                   1623:                pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->start,
                   1624:                        dst_entry->end - dst_entry->start, src_entry->start);
                   1625:        }
                   1626:        else {
                   1627:                /*
                   1628:                 *      Of course, wired down pages can't be set copy-on-write.
                   1629:                 *      Cause wired pages to be copied into the new
                   1630:                 *      map by simulating faults (the new pages are
                   1631:                 *      pageable)
                   1632:                 */
                   1633:                vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry);
                   1634:        }
                   1635: }
                   1636: 
                   1637: /*
                   1638:  *     vm_map_copy:
                   1639:  *
                   1640:  *     Perform a virtual memory copy from the source
                   1641:  *     address map/range to the destination map/range.
                   1642:  *
                   1643:  *     If src_destroy or dst_alloc is requested,
                   1644:  *     the source and destination regions should be
                   1645:  *     disjoint, not only in the top-level map, but
                   1646:  *     in the sharing maps as well.  [The best way
                   1647:  *     to guarantee this is to use a new intermediate
                   1648:  *     map to make copies.  This also reduces map
                   1649:  *     fragmentation.]
                   1650:  */
                   1651: vm_map_copy(dst_map, src_map,
                   1652:                          dst_addr, len, src_addr,
                   1653:                          dst_alloc, src_destroy)
                   1654:        vm_map_t        dst_map;
                   1655:        vm_map_t        src_map;
                   1656:        vm_offset_t     dst_addr;
                   1657:        vm_size_t       len;
                   1658:        vm_offset_t     src_addr;
                   1659:        boolean_t       dst_alloc;
                   1660:        boolean_t       src_destroy;
                   1661: {
                   1662:        register
                   1663:        vm_map_entry_t  src_entry;
                   1664:        register
                   1665:        vm_map_entry_t  dst_entry;
                   1666:        vm_map_entry_t  tmp_entry;
                   1667:        vm_offset_t     src_start;
                   1668:        vm_offset_t     src_end;
                   1669:        vm_offset_t     dst_start;
                   1670:        vm_offset_t     dst_end;
                   1671:        vm_offset_t     src_clip;
                   1672:        vm_offset_t     dst_clip;
                   1673:        int             result;
                   1674:        boolean_t       old_src_destroy;
                   1675: 
                   1676:        /*
                   1677:         *      XXX While we figure out why src_destroy screws up,
                   1678:         *      we'll do it by explicitly vm_map_delete'ing at the end.
                   1679:         */
                   1680: 
                   1681:        old_src_destroy = src_destroy;
                   1682:        src_destroy = FALSE;
                   1683: 
                   1684:        /*
                   1685:         *      Compute start and end of region in both maps
                   1686:         */
                   1687: 
                   1688:        src_start = src_addr;
                   1689:        src_end = src_start + len;
                   1690:        dst_start = dst_addr;
                   1691:        dst_end = dst_start + len;
                   1692: 
                   1693:        /*
                   1694:         *      Check that the region can exist in both source
                   1695:         *      and destination.
                   1696:         */
                   1697: 
                   1698:        if ((dst_end < dst_start) || (src_end < src_start))
                   1699:                return(KERN_NO_SPACE);
                   1700: 
                   1701:        /*
                   1702:         *      Lock the maps in question -- we avoid deadlock
                   1703:         *      by ordering lock acquisition by map value
                   1704:         */
                   1705: 
                   1706:        if (src_map == dst_map) {
                   1707:                vm_map_lock(src_map);
                   1708:        }
                   1709:        else if ((int) src_map < (int) dst_map) {
                   1710:                vm_map_lock(src_map);
                   1711:                vm_map_lock(dst_map);
                   1712:        } else {
                   1713:                vm_map_lock(dst_map);
                   1714:                vm_map_lock(src_map);
                   1715:        }
                   1716: 
                   1717:        result = KERN_SUCCESS;
                   1718: 
                   1719:        /*
                   1720:         *      Check protections... source must be completely readable and
                   1721:         *      destination must be completely writable.  [Note that if we're
                   1722:         *      allocating the destination region, we don't have to worry
                   1723:         *      about protection, but instead about whether the region
                   1724:         *      exists.]
                   1725:         */
                   1726: 
                   1727:        if (src_map->is_main_map && dst_map->is_main_map) {
                   1728:                if (!vm_map_check_protection(src_map, src_start, src_end,
                   1729:                                        VM_PROT_READ)) {
                   1730:                        result = KERN_PROTECTION_FAILURE;
                   1731:                        goto Return;
                   1732:                }
                   1733: 
                   1734:                if (dst_alloc) {
                   1735:                        /* XXX Consider making this a vm_map_find instead */
                   1736:                        if ((result = vm_map_insert(dst_map, NULL,
                   1737:                                        (vm_offset_t) 0, dst_start, dst_end)) != KERN_SUCCESS)
                   1738:                                goto Return;
                   1739:                }
                   1740:                else if (!vm_map_check_protection(dst_map, dst_start, dst_end,
                   1741:                                        VM_PROT_WRITE)) {
                   1742:                        result = KERN_PROTECTION_FAILURE;
                   1743:                        goto Return;
                   1744:                }
                   1745:        }
                   1746: 
                   1747:        /*
                   1748:         *      Find the start entries and clip.
                   1749:         *
                   1750:         *      Note that checking protection asserts that the
                   1751:         *      lookup cannot fail.
                   1752:         *
                   1753:         *      Also note that we wait to do the second lookup
                   1754:         *      until we have done the first clip, as the clip
                   1755:         *      may affect which entry we get!
                   1756:         */
                   1757: 
                   1758:        (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
                   1759:        src_entry = tmp_entry;
                   1760:        vm_map_clip_start(src_map, src_entry, src_start);
                   1761: 
                   1762:        (void) vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry);
                   1763:        dst_entry = tmp_entry;
                   1764:        vm_map_clip_start(dst_map, dst_entry, dst_start);
                   1765: 
                   1766:        /*
                   1767:         *      If both source and destination entries are the same,
                   1768:         *      retry the first lookup, as it may have changed.
                   1769:         */
                   1770: 
                   1771:        if (src_entry == dst_entry) {
                   1772:                (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
                   1773:                src_entry = tmp_entry;
                   1774:        }
                   1775: 
                   1776:        /*
                   1777:         *      If source and destination entries are still the same,
                   1778:         *      a null copy is being performed.
                   1779:         */
                   1780: 
                   1781:        if (src_entry == dst_entry)
                   1782:                goto Return;
                   1783: 
                   1784:        /*
                   1785:         *      Go through entries until we get to the end of the
                   1786:         *      region.
                   1787:         */
                   1788: 
                   1789:        while (src_start < src_end) {
                   1790:                /*
                   1791:                 *      Clip the entries to the endpoint of the entire region.
                   1792:                 */
                   1793: 
                   1794:                vm_map_clip_end(src_map, src_entry, src_end);
                   1795:                vm_map_clip_end(dst_map, dst_entry, dst_end);
                   1796: 
                   1797:                /*
                   1798:                 *      Clip each entry to the endpoint of the other entry.
                   1799:                 */
                   1800: 
                   1801:                src_clip = src_entry->start + (dst_entry->end - dst_entry->start);
                   1802:                vm_map_clip_end(src_map, src_entry, src_clip);
                   1803: 
                   1804:                dst_clip = dst_entry->start + (src_entry->end - src_entry->start);
                   1805:                vm_map_clip_end(dst_map, dst_entry, dst_clip);
                   1806: 
                   1807:                /*
                   1808:                 *      Both entries now match in size and relative endpoints.
                   1809:                 *
                   1810:                 *      If both entries refer to a VM object, we can
                   1811:                 *      deal with them now.
                   1812:                 */
                   1813: 
                   1814:                if (!src_entry->is_a_map && !dst_entry->is_a_map) {
                   1815:                        vm_map_copy_entry(src_map, dst_map, src_entry,
                   1816:                                                dst_entry);
                   1817:                }
                   1818:                else {
                   1819:                        register vm_map_t       new_dst_map;
                   1820:                        vm_offset_t             new_dst_start;
                   1821:                        vm_size_t               new_size;
                   1822:                        vm_map_t                new_src_map;
                   1823:                        vm_offset_t             new_src_start;
                   1824: 
                   1825:                        /*
                   1826:                         *      We have to follow at least one sharing map.
                   1827:                         */
                   1828: 
                   1829:                        new_size = (dst_entry->end - dst_entry->start);
                   1830: 
                   1831:                        if (src_entry->is_a_map) {
                   1832:                                new_src_map = src_entry->object.share_map;
                   1833:                                new_src_start = src_entry->offset;
                   1834:                        }
                   1835:                        else {
                   1836:                                new_src_map = src_map;
                   1837:                                new_src_start = src_entry->start;
                   1838:                                lock_set_recursive(&src_map->lock);
                   1839:                        }
                   1840: 
                   1841:                        if (dst_entry->is_a_map) {
                   1842:                                vm_offset_t     new_dst_end;
                   1843: 
                   1844:                                new_dst_map = dst_entry->object.share_map;
                   1845:                                new_dst_start = dst_entry->offset;
                   1846: 
                   1847:                                /*
                   1848:                                 *      Since the destination sharing entries
                   1849:                                 *      will be merely deallocated, we can
                   1850:                                 *      do that now, and replace the region
                   1851:                                 *      with a null object.  [This prevents
                   1852:                                 *      splitting the source map to match
                   1853:                                 *      the form of the destination map.]
                   1854:                                 *      Note that we can only do so if the
                   1855:                                 *      source and destination do not overlap.
                   1856:                                 */
                   1857: 
                   1858:                                new_dst_end = new_dst_start + new_size;
                   1859: 
                   1860:                                if (new_dst_map != new_src_map) {
                   1861:                                        vm_map_lock(new_dst_map);
                   1862:                                        (void) vm_map_delete(new_dst_map,
                   1863:                                                        new_dst_start,
                   1864:                                                        new_dst_end);
                   1865:                                        (void) vm_map_insert(new_dst_map,
                   1866:                                                        NULL,
                   1867:                                                        (vm_offset_t) 0,
                   1868:                                                        new_dst_start,
                   1869:                                                        new_dst_end);
                   1870:                                        vm_map_unlock(new_dst_map);
                   1871:                                }
                   1872:                        }
                   1873:                        else {
                   1874:                                new_dst_map = dst_map;
                   1875:                                new_dst_start = dst_entry->start;
                   1876:                                lock_set_recursive(&dst_map->lock);
                   1877:                        }
                   1878: 
                   1879:                        /*
                   1880:                         *      Recursively copy the sharing map.
                   1881:                         */
                   1882: 
                   1883:                        (void) vm_map_copy(new_dst_map, new_src_map,
                   1884:                                new_dst_start, new_size, new_src_start,
                   1885:                                FALSE, FALSE);
                   1886: 
                   1887:                        if (dst_map == new_dst_map)
                   1888:                                lock_clear_recursive(&dst_map->lock);
                   1889:                        if (src_map == new_src_map)
                   1890:                                lock_clear_recursive(&src_map->lock);
                   1891:                }
                   1892: 
                   1893:                /*
                   1894:                 *      Update variables for next pass through the loop.
                   1895:                 */
                   1896: 
                   1897:                src_start = src_entry->end;
                   1898:                src_entry = src_entry->next;
                   1899:                dst_start = dst_entry->end;
                   1900:                dst_entry = dst_entry->next;
                   1901: 
                   1902:                /*
                   1903:                 *      If the source is to be destroyed, here is the
                   1904:                 *      place to do it.
                   1905:                 */
                   1906: 
                   1907:                if (src_destroy && src_map->is_main_map &&
                   1908:                                                dst_map->is_main_map)
                   1909:                        vm_map_entry_delete(src_map, src_entry->prev);
                   1910:        }
                   1911: 
                   1912:        /*
                   1913:         *      Update the physical maps as appropriate
                   1914:         */
                   1915: 
                   1916:        if (src_map->is_main_map && dst_map->is_main_map) {
                   1917:                if (src_destroy)
                   1918:                        pmap_remove(src_map->pmap, src_addr, src_addr + len);
                   1919:        }
                   1920: 
                   1921:        /*
                   1922:         *      Unlock the maps
                   1923:         */
                   1924: 
                   1925:        Return: ;
                   1926: 
                   1927:        if (old_src_destroy)
                   1928:                vm_map_delete(src_map, src_addr, src_addr + len);
                   1929: 
                   1930:        vm_map_unlock(src_map);
                   1931:        if (src_map != dst_map)
                   1932:                vm_map_unlock(dst_map);
                   1933: 
                   1934:        return(result);
                   1935: }
                   1936: 
                   1937: /*
                   1938:  * vmspace_fork:
                   1939:  * Create a new process vmspace structure and vm_map
                   1940:  * based on those of an existing process.  The new map
                   1941:  * is based on the old map, according to the inheritance
                   1942:  * values on the regions in that map.
                   1943:  *
                   1944:  * The source map must not be locked.
                   1945:  */
                   1946: struct vmspace *
                   1947: vmspace_fork(vm1)
                   1948:        register struct vmspace *vm1;
                   1949: {
                   1950:        register struct vmspace *vm2;
                   1951:        vm_map_t        old_map = &vm1->vm_map;
                   1952:        vm_map_t        new_map;
                   1953:        vm_map_entry_t  old_entry;
                   1954:        vm_map_entry_t  new_entry;
                   1955:        pmap_t          new_pmap;
                   1956: 
                   1957:        vm_map_lock(old_map);
                   1958: 
                   1959:        vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset,
                   1960:            old_map->entries_pageable);
                   1961:        bcopy(&vm1->vm_startcopy, &vm2->vm_startcopy,
                   1962:            (caddr_t) (vm1 + 1) - (caddr_t) &vm1->vm_startcopy);
                   1963:        new_pmap = &vm2->vm_pmap;               /* XXX */
                   1964:        new_map = &vm2->vm_map;                 /* XXX */
                   1965: 
                   1966:        old_entry = old_map->header.next;
                   1967: 
                   1968:        while (old_entry != &old_map->header) {
                   1969:                if (old_entry->is_sub_map)
                   1970:                        panic("vm_map_fork: encountered a submap");
                   1971: 
                   1972:                switch (old_entry->inheritance) {
                   1973:                case VM_INHERIT_NONE:
                   1974:                        break;
                   1975: 
                   1976:                case VM_INHERIT_SHARE:
                   1977:                        /*
                   1978:                         *      If we don't already have a sharing map:
                   1979:                         */
                   1980: 
                   1981:                        if (!old_entry->is_a_map) {
                   1982:                                vm_map_t        new_share_map;
                   1983:                                vm_map_entry_t  new_share_entry;
                   1984:                                
                   1985:                                /*
                   1986:                                 *      Create a new sharing map
                   1987:                                 */
                   1988:                                 
                   1989:                                new_share_map = vm_map_create(NULL,
                   1990:                                                        old_entry->start,
                   1991:                                                        old_entry->end,
                   1992:                                                        TRUE);
                   1993:                                new_share_map->is_main_map = FALSE;
                   1994: 
                   1995:                                /*
                   1996:                                 *      Create the only sharing entry from the
                   1997:                                 *      old task map entry.
                   1998:                                 */
                   1999: 
                   2000:                                new_share_entry =
                   2001:                                        vm_map_entry_create(new_share_map);
                   2002:                                *new_share_entry = *old_entry;
                   2003: 
                   2004:                                /*
                   2005:                                 *      Insert the entry into the new sharing
                   2006:                                 *      map
                   2007:                                 */
                   2008: 
                   2009:                                vm_map_entry_link(new_share_map,
                   2010:                                                new_share_map->header.prev,
                   2011:                                                new_share_entry);
                   2012: 
                   2013:                                /*
                   2014:                                 *      Fix up the task map entry to refer
                   2015:                                 *      to the sharing map now.
                   2016:                                 */
                   2017: 
                   2018:                                old_entry->is_a_map = TRUE;
                   2019:                                old_entry->object.share_map = new_share_map;
                   2020:                                old_entry->offset = old_entry->start;
                   2021:                        }
                   2022: 
                   2023:                        /*
                   2024:                         *      Clone the entry, referencing the sharing map.
                   2025:                         */
                   2026: 
                   2027:                        new_entry = vm_map_entry_create(new_map);
                   2028:                        *new_entry = *old_entry;
                   2029:                        vm_map_reference(new_entry->object.share_map);
                   2030: 
                   2031:                        /*
                   2032:                         *      Insert the entry into the new map -- we
                   2033:                         *      know we're inserting at the end of the new
                   2034:                         *      map.
                   2035:                         */
                   2036: 
                   2037:                        vm_map_entry_link(new_map, new_map->header.prev,
                   2038:                                                new_entry);
                   2039: 
                   2040:                        /*
                   2041:                         *      Update the physical map
                   2042:                         */
                   2043: 
                   2044:                        pmap_copy(new_map->pmap, old_map->pmap,
                   2045:                                new_entry->start,
                   2046:                                (old_entry->end - old_entry->start),
                   2047:                                old_entry->start);
                   2048:                        break;
                   2049: 
                   2050:                case VM_INHERIT_COPY:
                   2051:                        /*
                   2052:                         *      Clone the entry and link into the map.
                   2053:                         */
                   2054: 
                   2055:                        new_entry = vm_map_entry_create(new_map);
                   2056:                        *new_entry = *old_entry;
                   2057:                        new_entry->wired_count = 0;
                   2058:                        new_entry->object.vm_object = NULL;
                   2059:                        new_entry->is_a_map = FALSE;
                   2060:                        vm_map_entry_link(new_map, new_map->header.prev,
                   2061:                                                        new_entry);
                   2062:                        if (old_entry->is_a_map) {
                   2063:                                int     check;
                   2064: 
                   2065:                                check = vm_map_copy(new_map,
                   2066:                                                old_entry->object.share_map,
                   2067:                                                new_entry->start,
                   2068:                                                (vm_size_t)(new_entry->end -
                   2069:                                                        new_entry->start),
                   2070:                                                old_entry->offset,
                   2071:                                                FALSE, FALSE);
                   2072:                                if (check != KERN_SUCCESS)
                   2073:                                        printf("vm_map_fork: copy in share_map region failed\n");
                   2074:                        }
                   2075:                        else {
                   2076:                                vm_map_copy_entry(old_map, new_map, old_entry,
                   2077:                                                new_entry);
                   2078:                        }
                   2079:                        break;
                   2080:                }
                   2081:                old_entry = old_entry->next;
                   2082:        }
                   2083: 
                   2084:        new_map->size = old_map->size;
                   2085:        vm_map_unlock(old_map);
                   2086: 
                   2087:        return(vm2);
                   2088: }
                   2089: 
                   2090: /*
                   2091:  *     vm_map_lookup:
                   2092:  *
                   2093:  *     Finds the VM object, offset, and
                   2094:  *     protection for a given virtual address in the
                   2095:  *     specified map, assuming a page fault of the
                   2096:  *     type specified.
                   2097:  *
                   2098:  *     Leaves the map in question locked for read; return
                   2099:  *     values are guaranteed until a vm_map_lookup_done
                   2100:  *     call is performed.  Note that the map argument
                   2101:  *     is in/out; the returned map must be used in
                   2102:  *     the call to vm_map_lookup_done.
                   2103:  *
                   2104:  *     A handle (out_entry) is returned for use in
                   2105:  *     vm_map_lookup_done, to make that fast.
                   2106:  *
                   2107:  *     If a lookup is requested with "write protection"
                   2108:  *     specified, the map may be changed to perform virtual
                   2109:  *     copying operations, although the data referenced will
                   2110:  *     remain the same.
                   2111:  */
                   2112: vm_map_lookup(var_map, vaddr, fault_type, out_entry,
                   2113:                                object, offset, out_prot, wired, single_use)
                   2114:        vm_map_t                *var_map;       /* IN/OUT */
                   2115:        register vm_offset_t    vaddr;
                   2116:        register vm_prot_t      fault_type;
                   2117: 
                   2118:        vm_map_entry_t          *out_entry;     /* OUT */
                   2119:        vm_object_t             *object;        /* OUT */
                   2120:        vm_offset_t             *offset;        /* OUT */
                   2121:        vm_prot_t               *out_prot;      /* OUT */
                   2122:        boolean_t               *wired;         /* OUT */
                   2123:        boolean_t               *single_use;    /* OUT */
                   2124: {
                   2125:        vm_map_t                        share_map;
                   2126:        vm_offset_t                     share_offset;
                   2127:        register vm_map_entry_t         entry;
                   2128:        register vm_map_t               map = *var_map;
                   2129:        register vm_prot_t              prot;
                   2130:        register boolean_t              su;
                   2131: 
                   2132:        RetryLookup: ;
                   2133: 
                   2134:        /*
                   2135:         *      Lookup the faulting address.
                   2136:         */
                   2137: 
                   2138:        vm_map_lock_read(map);
                   2139: 
                   2140: #define        RETURN(why) \
                   2141:                { \
                   2142:                vm_map_unlock_read(map); \
                   2143:                return(why); \
                   2144:                }
                   2145: 
                   2146:        /*
                   2147:         *      If the map has an interesting hint, try it before calling
                   2148:         *      full blown lookup routine.
                   2149:         */
                   2150: 
                   2151:        simple_lock(&map->hint_lock);
                   2152:        entry = map->hint;
                   2153:        simple_unlock(&map->hint_lock);
                   2154: 
                   2155:        *out_entry = entry;
                   2156: 
                   2157:        if ((entry == &map->header) ||
                   2158:            (vaddr < entry->start) || (vaddr >= entry->end)) {
                   2159:                vm_map_entry_t  tmp_entry;
                   2160: 
                   2161:                /*
                   2162:                 *      Entry was either not a valid hint, or the vaddr
                   2163:                 *      was not contained in the entry, so do a full lookup.
                   2164:                 */
                   2165:                if (!vm_map_lookup_entry(map, vaddr, &tmp_entry))
                   2166:                        RETURN(KERN_INVALID_ADDRESS);
                   2167: 
                   2168:                entry = tmp_entry;
                   2169:                *out_entry = entry;
                   2170:        }
                   2171: 
                   2172:        /*
                   2173:         *      Handle submaps.
                   2174:         */
                   2175: 
                   2176:        if (entry->is_sub_map) {
                   2177:                vm_map_t        old_map = map;
                   2178: 
                   2179:                *var_map = map = entry->object.sub_map;
                   2180:                vm_map_unlock_read(old_map);
                   2181:                goto RetryLookup;
                   2182:        }
                   2183:                
                   2184:        /*
                   2185:         *      Check whether this task is allowed to have
                   2186:         *      this page.
                   2187:         */
                   2188: 
                   2189:        prot = entry->protection;
                   2190:        if ((fault_type & (prot)) != fault_type)
                   2191:                RETURN(KERN_PROTECTION_FAILURE);
                   2192: 
                   2193:        /*
                   2194:         *      If this page is not pageable, we have to get
                   2195:         *      it for all possible accesses.
                   2196:         */
                   2197: 
                   2198:        if (*wired = (entry->wired_count != 0))
                   2199:                prot = fault_type = entry->protection;
                   2200: 
                   2201:        /*
                   2202:         *      If we don't already have a VM object, track
                   2203:         *      it down.
                   2204:         */
                   2205: 
                   2206:        if (su = !entry->is_a_map) {
                   2207:                share_map = map;
                   2208:                share_offset = vaddr;
                   2209:        }
                   2210:        else {
                   2211:                vm_map_entry_t  share_entry;
                   2212: 
                   2213:                /*
                   2214:                 *      Compute the sharing map, and offset into it.
                   2215:                 */
                   2216: 
                   2217:                share_map = entry->object.share_map;
                   2218:                share_offset = (vaddr - entry->start) + entry->offset;
                   2219: 
                   2220:                /*
                   2221:                 *      Look for the backing store object and offset
                   2222:                 */
                   2223: 
                   2224:                vm_map_lock_read(share_map);
                   2225: 
                   2226:                if (!vm_map_lookup_entry(share_map, share_offset,
                   2227:                                        &share_entry)) {
                   2228:                        vm_map_unlock_read(share_map);
                   2229:                        RETURN(KERN_INVALID_ADDRESS);
                   2230:                }
                   2231:                entry = share_entry;
                   2232:        }
                   2233: 
                   2234:        /*
                   2235:         *      If the entry was copy-on-write, we either ...
                   2236:         */
                   2237: 
                   2238:        if (entry->needs_copy) {
                   2239:                /*
                   2240:                 *      If we want to write the page, we may as well
                   2241:                 *      handle that now since we've got the sharing
                   2242:                 *      map locked.
                   2243:                 *
                   2244:                 *      If we don't need to write the page, we just
                   2245:                 *      demote the permissions allowed.
                   2246:                 */
                   2247: 
                   2248:                if (fault_type & VM_PROT_WRITE) {
                   2249:                        /*
                   2250:                         *      Make a new object, and place it in the
                   2251:                         *      object chain.  Note that no new references
                   2252:                         *      have appeared -- one just moved from the
                   2253:                         *      share map to the new object.
                   2254:                         */
                   2255: 
                   2256:                        if (lock_read_to_write(&share_map->lock)) {
                   2257:                                if (share_map != map)
                   2258:                                        vm_map_unlock_read(map);
                   2259:                                goto RetryLookup;
                   2260:                        }
                   2261: 
                   2262:                        vm_object_shadow(
                   2263:                                &entry->object.vm_object,
                   2264:                                &entry->offset,
                   2265:                                (vm_size_t) (entry->end - entry->start));
                   2266:                                
                   2267:                        entry->needs_copy = FALSE;
                   2268:                        
                   2269:                        lock_write_to_read(&share_map->lock);
                   2270:                }
                   2271:                else {
                   2272:                        /*
                   2273:                         *      We're attempting to read a copy-on-write
                   2274:                         *      page -- don't allow writes.
                   2275:                         */
                   2276: 
                   2277:                        prot &= (~VM_PROT_WRITE);
                   2278:                }
                   2279:        }
                   2280: 
                   2281:        /*
                   2282:         *      Create an object if necessary.
                   2283:         */
                   2284:        if (entry->object.vm_object == NULL) {
                   2285: 
                   2286:                if (lock_read_to_write(&share_map->lock)) {
                   2287:                        if (share_map != map)
                   2288:                                vm_map_unlock_read(map);
                   2289:                        goto RetryLookup;
                   2290:                }
                   2291: 
                   2292:                entry->object.vm_object = vm_object_allocate(
                   2293:                                        (vm_size_t)(entry->end - entry->start));
                   2294:                entry->offset = 0;
                   2295:                lock_write_to_read(&share_map->lock);
                   2296:        }
                   2297: 
                   2298:        /*
                   2299:         *      Return the object/offset from this entry.  If the entry
                   2300:         *      was copy-on-write or empty, it has been fixed up.
                   2301:         */
                   2302: 
                   2303:        *offset = (share_offset - entry->start) + entry->offset;
                   2304:        *object = entry->object.vm_object;
                   2305: 
                   2306:        /*
                   2307:         *      Return whether this is the only map sharing this data.
                   2308:         */
                   2309: 
                   2310:        if (!su) {
                   2311:                simple_lock(&share_map->ref_lock);
                   2312:                su = (share_map->ref_count == 1);
                   2313:                simple_unlock(&share_map->ref_lock);
                   2314:        }
                   2315: 
                   2316:        *out_prot = prot;
                   2317:        *single_use = su;
                   2318: 
                   2319:        return(KERN_SUCCESS);
                   2320:        
                   2321: #undef RETURN
                   2322: }
                   2323: 
                   2324: /*
                   2325:  *     vm_map_lookup_done:
                   2326:  *
                   2327:  *     Releases locks acquired by a vm_map_lookup
                   2328:  *     (according to the handle returned by that lookup).
                   2329:  */
                   2330: 
                   2331: void vm_map_lookup_done(map, entry)
                   2332:        register vm_map_t       map;
                   2333:        vm_map_entry_t          entry;
                   2334: {
                   2335:        /*
                   2336:         *      If this entry references a map, unlock it first.
                   2337:         */
                   2338: 
                   2339:        if (entry->is_a_map)
                   2340:                vm_map_unlock_read(entry->object.share_map);
                   2341: 
                   2342:        /*
                   2343:         *      Unlock the main-level map
                   2344:         */
                   2345: 
                   2346:        vm_map_unlock_read(map);
                   2347: }
                   2348: 
                   2349: /*
                   2350:  *     Routine:        vm_map_simplify
                   2351:  *     Purpose:
                   2352:  *             Attempt to simplify the map representation in
                   2353:  *             the vicinity of the given starting address.
                   2354:  *     Note:
                   2355:  *             This routine is intended primarily to keep the
                   2356:  *             kernel maps more compact -- they generally don't
                   2357:  *             benefit from the "expand a map entry" technology
                   2358:  *             at allocation time because the adjacent entry
                   2359:  *             is often wired down.
                   2360:  */
                   2361: void vm_map_simplify(map, start)
                   2362:        vm_map_t        map;
                   2363:        vm_offset_t     start;
                   2364: {
                   2365:        vm_map_entry_t  this_entry;
                   2366:        vm_map_entry_t  prev_entry;
                   2367: 
                   2368:        vm_map_lock(map);
                   2369:        if (
                   2370:                (vm_map_lookup_entry(map, start, &this_entry)) &&
                   2371:                ((prev_entry = this_entry->prev) != &map->header) &&
                   2372: 
                   2373:                (prev_entry->end == start) &&
                   2374:                (map->is_main_map) &&
                   2375: 
                   2376:                (prev_entry->is_a_map == FALSE) &&
                   2377:                (prev_entry->is_sub_map == FALSE) &&
                   2378: 
                   2379:                (this_entry->is_a_map == FALSE) &&
                   2380:                (this_entry->is_sub_map == FALSE) &&
                   2381: 
                   2382:                (prev_entry->inheritance == this_entry->inheritance) &&
                   2383:                (prev_entry->protection == this_entry->protection) &&
                   2384:                (prev_entry->max_protection == this_entry->max_protection) &&
                   2385:                (prev_entry->wired_count == this_entry->wired_count) &&
                   2386:                
                   2387:                (prev_entry->copy_on_write == this_entry->copy_on_write) &&
                   2388:                (prev_entry->needs_copy == this_entry->needs_copy) &&
                   2389:                
                   2390:                (prev_entry->object.vm_object == this_entry->object.vm_object) &&
                   2391:                ((prev_entry->offset + (prev_entry->end - prev_entry->start))
                   2392:                     == this_entry->offset)
                   2393:        ) {
                   2394:                if (map->first_free == this_entry)
                   2395:                        map->first_free = prev_entry;
                   2396: 
                   2397:                SAVE_HINT(map, prev_entry);
                   2398:                vm_map_entry_unlink(map, this_entry);
                   2399:                prev_entry->end = this_entry->end;
                   2400:                vm_object_deallocate(this_entry->object.vm_object);
                   2401:                vm_map_entry_dispose(map, this_entry);
                   2402:        }
                   2403:        vm_map_unlock(map);
                   2404: }
                   2405: 
                   2406: /*
                   2407:  *     vm_map_print:   [ debug ]
                   2408:  */
                   2409: void vm_map_print(map, full)
                   2410:        register vm_map_t       map;
                   2411:        boolean_t               full;
                   2412: {
                   2413:        register vm_map_entry_t entry;
                   2414:        extern int indent;
                   2415: 
                   2416:        iprintf("%s map 0x%x: pmap=0x%x,ref=%d,nentries=%d,version=%d\n",
                   2417:                (map->is_main_map ? "Task" : "Share"),
                   2418:                (int) map, (int) (map->pmap), map->ref_count, map->nentries,
                   2419:                map->timestamp);
                   2420: 
                   2421:        if (!full && indent)
                   2422:                return;
                   2423: 
                   2424:        indent += 2;
                   2425:        for (entry = map->header.next; entry != &map->header;
                   2426:                                entry = entry->next) {
                   2427:                iprintf("map entry 0x%x: start=0x%x, end=0x%x, ",
                   2428:                        (int) entry, (int) entry->start, (int) entry->end);
                   2429:                if (map->is_main_map) {
                   2430:                        static char *inheritance_name[4] =
                   2431:                                { "share", "copy", "none", "donate_copy"};
                   2432:                        printf("prot=%x/%x/%s, ",
                   2433:                                entry->protection,
                   2434:                                entry->max_protection,
                   2435:                                inheritance_name[entry->inheritance]);
                   2436:                        if (entry->wired_count != 0)
                   2437:                                printf("wired, ");
                   2438:                }
                   2439: 
                   2440:                if (entry->is_a_map || entry->is_sub_map) {
                   2441:                        printf("share=0x%x, offset=0x%x\n",
                   2442:                                (int) entry->object.share_map,
                   2443:                                (int) entry->offset);
                   2444:                        if ((entry->prev == &map->header) ||
                   2445:                            (!entry->prev->is_a_map) ||
                   2446:                            (entry->prev->object.share_map !=
                   2447:                             entry->object.share_map)) {
                   2448:                                indent += 2;
                   2449:                                vm_map_print(entry->object.share_map, full);
                   2450:                                indent -= 2;
                   2451:                        }
                   2452:                                
                   2453:                }
                   2454:                else {
                   2455:                        printf("object=0x%x, offset=0x%x",
                   2456:                                (int) entry->object.vm_object,
                   2457:                                (int) entry->offset);
                   2458:                        if (entry->copy_on_write)
                   2459:                                printf(", copy (%s)",
                   2460:                                       entry->needs_copy ? "needed" : "done");
                   2461:                        printf("\n");
                   2462: 
                   2463:                        if ((entry->prev == &map->header) ||
                   2464:                            (entry->prev->is_a_map) ||
                   2465:                            (entry->prev->object.vm_object !=
                   2466:                             entry->object.vm_object)) {
                   2467:                                indent += 2;
                   2468:                                vm_object_print(entry->object.vm_object, full);
                   2469:                                indent -= 2;
                   2470:                        }
                   2471:                }
                   2472:        }
                   2473:        indent -= 2;
                   2474: }

unix.superglobalmegacorp.com

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