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

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

unix.superglobalmegacorp.com

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