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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1993-1987 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  *     File:   vm/vm_map.c
                     52:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     53:  *     Date:   1985
                     54:  *
                     55:  *     Virtual memory mapping module.
                     56:  */
                     57: 
                     58: #import <mach/features.h>
                     59: 
                     60: #define        USE_VERSIONS    MACH_XP
                     61: 
                     62: #import <mach/vm_param.h>
                     63: #import <vm/vm_map.h>
                     64: #import <kern/zalloc.h>
                     65: #import <mach/kern_return.h>
                     66: #import <vm/vm_page.h>
                     67: #import <vm/vm_object.h>
                     68: #import <mach/port.h>
                     69: #import <mach/vm_attributes.h>
                     70: 
                     71: 
                     72: /*
                     73:  * Macros to copy a vm_map_entry. We must be careful to correctly
                     74:  * manage the wired page count. vm_map_entry_copy() creates a new
                     75:  * map entry to the same memory - the wired count in the new entry
                     76:  * must be set to zero. vm_map_entry_copy_full() creates a new
                     77:  * entry that is identical to the old entry.  This preserves the
                     78:  * wire count; it's used for map splitting and zone changing in
                     79:  * vm_map_copyout.
                     80:  */
                     81: #define vm_map_entry_copy(NEW,OLD) \
                     82: MACRO_BEGIN                                     \
                     83:                 *(NEW) = *(OLD);                \
                     84:                 (NEW)->is_shared = FALSE;      \
                     85:                 (NEW)->needs_wakeup = FALSE;    \
                     86:                 (NEW)->in_transition = FALSE;   \
                     87:                 (NEW)->wired_count = 0;         \
                     88:                 (NEW)->user_wired_count = 0;    \
                     89: MACRO_END
                     90: 
                     91: #define vm_map_entry_copy_full(NEW,OLD)        (*(NEW) = *(OLD))
                     92: 
                     93: /*
                     94:  *     Virtual memory maps provide for the mapping, protection,
                     95:  *     and sharing of virtual memory objects.  In addition,
                     96:  *     this module provides for an efficient virtual copy of
                     97:  *     memory from one map to another.
                     98:  *
                     99:  *     Synchronization is required prior to most operations.
                    100:  *
                    101:  *     Maps consist of an ordered doubly-linked list of simple
                    102:  *     entries; a single hint is used to speed up lookups.
                    103:  *
                    104:  *     In order to properly represent the sharing of virtual
                    105:  *     memory regions among maps, the map structure is bi-level.
                    106:  *     Top-level ("address") maps refer to regions of sharable
                    107:  *     virtual memory.  These regions are implemented as
                    108:  *     ("sharing") maps, which then refer to the actual virtual
                    109:  *     memory objects.  When two address maps "share" memory,
                    110:  *     their top-level maps both have references to the same
                    111:  *     sharing map.  When memory is virtual-copied from one
                    112:  *     address map to another, the references in the sharing
                    113:  *     maps are actually copied -- no copying occurs at the
                    114:  *     virtual memory object level.
                    115:  *
                    116:  *     Since portions of maps are specified by start/end addreses,
                    117:  *     which may not align with existing map entries, all
                    118:  *     routines merely "clip" entries to these start/end values.
                    119:  *     [That is, an entry is split into two, bordering at a
                    120:  *     start or end value.]  Note that these clippings may not
                    121:  *     always be necessary (as the two resulting entries are then
                    122:  *     not changed); however, the clipping is done for convenience.
                    123:  *     No attempt is currently made to "glue back together" two
                    124:  *     abutting entries.
                    125:  *
                    126:  *     As mentioned above, virtual copy operations are performed
                    127:  *     by copying VM object references from one sharing map to
                    128:  *     another, and then marking both regions as copy-on-write.
                    129:  *     It is important to note that only one writeable reference
                    130:  *     to a VM object region exists in any map -- this means that
                    131:  *     shadow object creation can be delayed until a write operation
                    132:  *     occurs.
                    133:  */
                    134: 
                    135: zone_t         vm_map_zone;            /* zone for vm_map structures */
                    136: zone_t         vm_map_entry_zone;      /* zone for vm_map_entry structures */
                    137: zone_t         vm_map_kentry_zone;     /* zone for kernel entry structures */
                    138: 
                    139: vm_object_t    vm_submap_object;
                    140: 
                    141: /*
                    142:  *     vm_map_init:
                    143:  *
                    144:  *     Initialize the vm_map module.  Must be called before
                    145:  *     any other vm_map routines.
                    146:  *
                    147:  *     Map and entry structures are allocated from zones -- we must
                    148:  *     initialize those zones.
                    149:  *
                    150:  *     There are three zones of interest:
                    151:  *
                    152:  *     vm_map_zone:            used to allocate maps.
                    153:  *     vm_map_entry_zone:      used to allocate map entries.
                    154:  *     vm_map_kentry_zone:     used to allocate map entries for the kernel.
                    155:  *
                    156:  *     The kernel allocates map entries from a special zone that is initially
                    157:  *     "crammed" with memory.  It would be difficult (perhaps impossible) for
                    158:  *     the kernel to allocate more memory to a entry zone when it became
                    159:  *     empty since the very act of allocating memory implies the creatio
                    160:  *     of a new entry.  Further, since the kernel map is created from the
                    161:  *     map zone, the map zone is initially "crammed" with enough memory
                    162:  *     to fullfill that need.
                    163:  */
                    164: 
                    165: void vm_map_init()
                    166: {
                    167:        extern vm_offset_t      map_data, kentry_data;
                    168:        extern vm_size_t        map_data_size, kentry_data_size;
                    169: 
                    170:        vm_map_zone = zinit((vm_size_t) sizeof(struct vm_map), 100*1024,
                    171:                                        0, FALSE, "maps");
                    172:        vm_map_entry_zone = zinit((vm_size_t) sizeof(struct vm_map_entry),
                    173:                                        1024*1024, 0,
                    174:                                        FALSE, "non-kernel map entries");
                    175:        vm_map_kentry_zone = zinit((vm_size_t) sizeof(struct vm_map_entry),
                    176:                                        kentry_data_size, 0,
                    177:                                        FALSE, "kernel map entries");
                    178:        zchange(vm_map_kentry_zone, FALSE, FALSE, FALSE, FALSE);
                    179: 
                    180:        /*
                    181:         *      Cram the map and kentry zones with initial data.
                    182:         */
                    183:        zcram(vm_map_zone, map_data, map_data_size);
                    184:        zcram(vm_map_kentry_zone, kentry_data, kentry_data_size);
                    185: }
                    186: 
                    187: /*
                    188:  *     vm_map_create:
                    189:  *
                    190:  *     Creates and returns a new empty VM map with
                    191:  *     the given physical map structure, and having
                    192:  *     the given lower and upper address bounds.
                    193:  */
                    194: vm_map_t vm_map_create(pmap, min, max, pageable)
                    195:        pmap_t          pmap;
                    196:        vm_offset_t     min, max;
                    197:        boolean_t       pageable;
                    198: {
                    199:        register vm_map_t       result;
                    200: 
                    201:        result = (vm_map_t) zalloc(vm_map_zone);
                    202:        if (result == VM_MAP_NULL)
                    203:                panic("vm_map_create");
                    204: 
                    205:        vm_map_first_entry(result) = vm_map_to_entry(result);
                    206:        vm_map_last_entry(result)  = vm_map_to_entry(result);
                    207:        result->hdr.nentries = 0;
                    208:        result->hdr.entries_pageable = pageable;
                    209: 
                    210:        result->size = 0;
                    211:        result->ref_count = 1;
                    212:        result->pmap = pmap;
                    213: #if    OLD_VM_CODE
                    214:        result->is_main_map = TRUE;
                    215: #endif
                    216:        result->min_offset = min;
                    217:        result->max_offset = max;
                    218:        result->wiring_required = FALSE;
                    219:        result->wait_for_space = FALSE;
                    220:        result->first_free = vm_map_to_entry(result);
                    221:        result->hint = vm_map_to_entry(result);
                    222: #if    OLD_VM_CODE
                    223:        result->timestamp = 0;
                    224: #endif
                    225:        vm_map_lock_init(result);
                    226:        simple_lock_init(&result->ref_lock);
                    227:        simple_lock_init(&result->hint_lock);
                    228: 
                    229:        return(result);
                    230: }
                    231: 
                    232: /*
                    233:  *     vm_map_entry_create:    [ internal use only ]
                    234:  *
                    235:  *     Allocates a VM map entry for insertion in the
                    236:  *     given map (or map copy).  No fields are filled.
                    237:  */
                    238: #define        vm_map_entry_create(map) \
                    239:            _vm_map_entry_create(&(map)->hdr)
                    240: 
                    241: #define        vm_map_copy_entry_create(copy) \
                    242:            _vm_map_entry_create(&(copy)->cpy_hdr)
                    243: 
                    244: vm_map_entry_t _vm_map_entry_create(map_header)
                    245:        register struct vm_map_header *map_header;
                    246: {
                    247:        register zone_t zone;
                    248:        register vm_map_entry_t entry;
                    249: 
                    250:        if (map_header->entries_pageable)
                    251:            zone = vm_map_entry_zone;
                    252:        else
                    253:            zone = vm_map_kentry_zone;
                    254: 
                    255:        entry = (vm_map_entry_t) zalloc(zone);
                    256:        if (entry == VM_MAP_ENTRY_NULL)
                    257:                panic("vm_map_entry_create");
                    258: 
                    259:        return(entry);
                    260: }
                    261: 
                    262: /*
                    263:  *     vm_map_entry_dispose:   [ internal use only ]
                    264:  *
                    265:  *     Inverse of vm_map_entry_create.
                    266:  */
                    267: #define        vm_map_entry_dispose(map, entry) \
                    268:        _vm_map_entry_dispose(&(map)->hdr, (entry))
                    269: 
                    270: #define        vm_map_copy_entry_dispose(map, entry) \
                    271:        _vm_map_entry_dispose(&(copy)->cpy_hdr, (entry))
                    272: 
                    273: void _vm_map_entry_dispose(map_header, entry)
                    274:        register struct vm_map_header *map_header;
                    275:        register vm_map_entry_t entry;
                    276: {
                    277:        register zone_t         zone;
                    278: 
                    279:        if (map_header->entries_pageable)
                    280:            zone = vm_map_entry_zone;
                    281:        else
                    282:            zone = vm_map_kentry_zone;
                    283: 
                    284:        zfree(zone, (vm_offset_t) entry);
                    285: }
                    286: 
                    287: /*
                    288:  *     vm_map_entry_{un,}link:
                    289:  *
                    290:  *     Insert/remove entries from maps (or map copies).
                    291:  */
                    292: #define vm_map_entry_link(map, after_where, entry)     \
                    293:        _vm_map_entry_link(&(map)->hdr, after_where, entry)
                    294: 
                    295: #define vm_map_copy_entry_link(copy, after_where, entry)       \
                    296:        _vm_map_entry_link(&(copy)->cpy_hdr, after_where, entry)
                    297: 
                    298: #define _vm_map_entry_link(hdr, after_where, entry)    \
                    299:        MACRO_BEGIN                                     \
                    300:        (hdr)->nentries++;                              \
                    301:        (entry)->vme_prev = (after_where);              \
                    302:        (entry)->vme_next = (after_where)->vme_next;    \
                    303:        (entry)->vme_prev->vme_next =                   \
                    304:         (entry)->vme_next->vme_prev = (entry);         \
                    305:        MACRO_END
                    306: 
                    307: #define vm_map_entry_unlink(map, entry)                        \
                    308:        _vm_map_entry_unlink(&(map)->hdr, entry)
                    309: 
                    310: #define vm_map_copy_entry_unlink(copy, entry)                  \
                    311:        _vm_map_entry_unlink(&(copy)->cpy_hdr, entry)
                    312: 
                    313: #define _vm_map_entry_unlink(hdr, entry)               \
                    314:        MACRO_BEGIN                                     \
                    315:        (hdr)->nentries--;                              \
                    316:        (entry)->vme_next->vme_prev = (entry)->vme_prev; \
                    317:        (entry)->vme_prev->vme_next = (entry)->vme_next; \
                    318:        MACRO_END
                    319: 
                    320: /*
                    321:  *     vm_map_reference:
                    322:  *
                    323:  *     Creates another valid reference to the given map.
                    324:  *
                    325:  */
                    326: void vm_map_reference(map)
                    327:        register vm_map_t       map;
                    328: {
                    329:        if (map == VM_MAP_NULL)
                    330:                return;
                    331: 
                    332:        simple_lock(&map->ref_lock);
                    333:        map->ref_count++;
                    334:        simple_unlock(&map->ref_lock);
                    335: }
                    336: 
                    337: /*
                    338:  *     vm_map_deallocate:
                    339:  *
                    340:  *     Removes a reference from the specified map,
                    341:  *     destroying it if no references remain.
                    342:  *     The map should not be locked.
                    343:  */
                    344: void vm_map_deallocate(map)
                    345:        register vm_map_t       map;
                    346: {
                    347:        register int            c;
                    348: 
                    349:        if (map == VM_MAP_NULL)
                    350:                return;
                    351: 
                    352:        simple_lock(&map->ref_lock);
                    353:        c = --map->ref_count;
                    354:        simple_unlock(&map->ref_lock);
                    355: 
                    356:        if (c > 0) {
                    357:                return;
                    358:        }
                    359: 
                    360:        /*
                    361:         *      Lock the map, to wait out all other references
                    362:         *      to it.
                    363:         */
                    364: 
                    365:        vm_map_lock(map);
                    366: 
                    367:        (void) vm_map_delete(map, map->min_offset, map->max_offset);
                    368: 
                    369:        pmap_destroy(map->pmap);
                    370: 
                    371:        zfree(vm_map_zone, (vm_offset_t) map);
                    372: }
                    373: 
                    374: /*
                    375:  *     vm_map_insert:  [ internal use only ]
                    376:  *
                    377:  *     Inserts the given whole VM object into the target
                    378:  *     map at the specified address range.  The object's
                    379:  *     size should match that of the address range.
                    380:  *
                    381:  *     Requires that the map be locked, and leaves it so.
                    382:  */
                    383: kern_return_t vm_map_insert(map, object, offset, start, end)
                    384:        vm_map_t        map;
                    385:        vm_object_t     object;
                    386:        vm_offset_t     offset;
                    387:        vm_offset_t     start;
                    388:        vm_offset_t     end;
                    389: {
                    390:        vm_map_entry_t          new_entry;
                    391:        vm_map_entry_t          prev_entry;
                    392:        boolean_t vm_map_lookup_entry();
                    393: 
                    394:        /*
                    395:         *      Check that the start and end points are not bogus.
                    396:         */
                    397: 
                    398:        if ((start < map->min_offset) || (end > map->max_offset) ||
                    399:                        (start >= end))
                    400:                return(KERN_INVALID_ADDRESS);
                    401: 
                    402:        /*
                    403:         *      Find the entry prior to the proposed
                    404:         *      starting address; if it's part of an
                    405:         *      existing entry, this range is bogus.
                    406:         */
                    407: 
                    408:        if (vm_map_lookup_entry(map, start, &prev_entry))
                    409:                return(KERN_NO_SPACE);
                    410: 
                    411:        /*
                    412:         *      Assert that the next entry doesn't overlap the
                    413:         *      end point.
                    414:         */
                    415: 
                    416:        if ((prev_entry->vme_next != vm_map_to_entry(map)) &&
                    417:                        (prev_entry->vme_next->vme_start < end))
                    418:                return(KERN_NO_SPACE);
                    419: 
                    420:        /*
                    421:         *      See if we can avoid creating a new entry by
                    422:         *      extending one of our neighbors.
                    423:         */
                    424: 
                    425:        if (object == VM_OBJECT_NULL) {
                    426:                if ((prev_entry != vm_map_to_entry(map)) &&
                    427:                    (prev_entry->vme_end == start) &&
                    428:                    (prev_entry->is_a_map == FALSE) &&
                    429:                    (prev_entry->is_sub_map == FALSE) &&
                    430:                    (prev_entry->inheritance == VM_INHERIT_DEFAULT) &&
                    431:                    (prev_entry->protection == VM_PROT_DEFAULT) &&
                    432:                    (prev_entry->max_protection == VM_PROT_ALL) &&
                    433:                    (prev_entry->wired_count == 0)) {
                    434: 
                    435:                        if (vm_object_coalesce(prev_entry->object.vm_object,
                    436:                                        VM_OBJECT_NULL,
                    437:                                        prev_entry->offset,
                    438:                                        (vm_offset_t) 0,
                    439:                                        (vm_size_t)(prev_entry->vme_end
                    440:                                                     - prev_entry->vme_start),
                    441:                                        (vm_size_t)(end -
                    442:                                                prev_entry->vme_end))) {
                    443:                                /*
                    444:                                 *      Coalesced the two objects - can extend
                    445:                                 *      the previous map entry to include the
                    446:                                 *      new range.
                    447:                                 */
                    448:                                map->size += (end - prev_entry->vme_end);
                    449:                                prev_entry->vme_end = end;
                    450:                                return(KERN_SUCCESS);
                    451:                        }
                    452:                }
                    453:        }
                    454: 
                    455:        /*
                    456:         *      Create a new entry
                    457:         */
                    458: 
                    459:        new_entry = vm_map_entry_create(map);
                    460:        new_entry->vme_start = start;
                    461:        new_entry->vme_end = end;
                    462: 
                    463:        new_entry->is_a_map = FALSE;
                    464:        new_entry->is_sub_map = FALSE;
                    465:        new_entry->object.vm_object = object;
                    466:        new_entry->offset = offset;
                    467: 
                    468:        new_entry->copy_on_write = FALSE;
                    469:        new_entry->needs_copy = FALSE;
                    470: 
                    471:        if (map->is_main_map) {
                    472:                new_entry->inheritance = VM_INHERIT_DEFAULT;
                    473:                new_entry->protection = VM_PROT_DEFAULT;
                    474:                new_entry->max_protection = VM_PROT_ALL;
                    475:                new_entry->wired_count = 0;
                    476:        }
                    477: 
                    478:        /*
                    479:         *      Insert the new entry into the list
                    480:         */
                    481: 
                    482:        vm_map_entry_link(map, prev_entry, new_entry);
                    483:        map->size += new_entry->vme_end - new_entry->vme_start;
                    484: 
                    485:        /*
                    486:         *      Update the free space hint
                    487:         */
                    488: 
                    489:        if ((map->first_free == prev_entry) && (prev_entry->vme_end >= new_entry->vme_start))
                    490:                map->first_free = new_entry;
                    491: 
                    492:        return(KERN_SUCCESS);
                    493: }
                    494: 
                    495: /*
                    496:  *     SAVE_HINT:
                    497:  *
                    498:  *     Saves the specified entry as the hint for
                    499:  *     future lookups.  Performs necessary interlocks.
                    500:  */
                    501: #define        SAVE_HINT(map,value) \
                    502:                simple_lock(&(map)->hint_lock); \
                    503:                (map)->hint = (value); \
                    504:                simple_unlock(&(map)->hint_lock);
                    505: 
                    506: /*
                    507:  *     vm_map_lookup_entry:    [ internal use only ]
                    508:  *
                    509:  *     Finds the map entry containing (or
                    510:  *     immediately preceding) the specified address
                    511:  *     in the given map; the entry is returned
                    512:  *     in the "entry" parameter.  The boolean
                    513:  *     result indicates whether the address is
                    514:  *     actually contained in the map.
                    515:  */
                    516: boolean_t vm_map_lookup_entry(map, address, entry)
                    517:        register vm_map_t       map;
                    518:        register vm_offset_t    address;
                    519:        vm_map_entry_t          *entry;         /* OUT */
                    520: {
                    521:        register vm_map_entry_t         cur;
                    522:        register vm_map_entry_t         last;
                    523: 
                    524:        /*
                    525:         *      Start looking either from the head of the
                    526:         *      list, or from the hint.
                    527:         */
                    528: 
                    529:        simple_lock(&map->hint_lock);
                    530:        cur = map->hint;
                    531:        simple_unlock(&map->hint_lock);
                    532: 
                    533:        if (cur == vm_map_to_entry(map))
                    534:                cur = cur->vme_next;
                    535: 
                    536:        if (address >= cur->vme_start) {
                    537:                /*
                    538:                 *      Go from hint to end of list.
                    539:                 *
                    540:                 *      But first, make a quick check to see if
                    541:                 *      we are already looking at the entry we
                    542:                 *      want (which is usually the case).
                    543:                 *      Note also that we don't need to save the hint
                    544:                 *      here... it is the same hint (unless we are
                    545:                 *      at the header, in which case the hint didn't
                    546:                 *      buy us anything anyway).
                    547:                 */
                    548:                last = vm_map_to_entry(map);
                    549:                if ((cur != last) && (cur->vme_end > address)) {
                    550:                        *entry = cur;
                    551:                        return(TRUE);
                    552:                }
                    553:        }
                    554:        else {
                    555:                /*
                    556:                 *      Go from start to hint, *inclusively*
                    557:                 */
                    558:                last = cur->vme_next;
                    559:                cur = vm_map_first_entry(map);
                    560:        }
                    561: 
                    562:        /*
                    563:         *      Search linearly
                    564:         */
                    565: 
                    566:        while (cur != last) {
                    567:                if (cur->vme_end > address) {
                    568:                        if (address >= cur->vme_start) {
                    569:                                /*
                    570:                                 *      Save this lookup for future
                    571:                                 *      hints, and return
                    572:                                 */
                    573: 
                    574:                                *entry = cur;
                    575:                                SAVE_HINT(map, cur);
                    576:                                return(TRUE);
                    577:                        }
                    578:                        break;
                    579:                }
                    580:                cur = cur->vme_next;
                    581:        }
                    582:        *entry = cur->vme_prev;
                    583:        SAVE_HINT(map, *entry);
                    584:        return(FALSE);
                    585: }
                    586: 
                    587: /*
                    588:  *     Routine:        vm_map_find_entry
                    589:  *     Purpose:
                    590:  *             Allocate a range in the specified virtual address map,
                    591:  *             returning the entry allocated for that range.
                    592:  *             Used by kmem_alloc, etc.  Returns wired entries.
                    593:  *
                    594:  *             The map must be locked.
                    595:  *
                    596:  *             If an entry is allocated, the object/offset fields
                    597:  *             are initialized to zero.  If an object is supplied,
                    598:  *             then an existing entry may be extended.
                    599:  */
                    600: kern_return_t vm_map_find_entry(map, address, size, mask, object, o_entry)
                    601:        register vm_map_t       map;
                    602:        vm_offset_t             *address;       /* OUT */
                    603:        vm_size_t               size;
                    604:        vm_offset_t             mask;
                    605:        vm_object_t             object;
                    606:        vm_map_entry_t          *o_entry;       /* OUT */
                    607: {
                    608:        register vm_map_entry_t entry, new_entry;
                    609:        register vm_offset_t    start;
                    610:        register vm_offset_t    end;
                    611: 
                    612:        /*
                    613:         *      Look for the first possible address;
                    614:         *      if there's already something at this
                    615:         *      address, we have to start after it.
                    616:         */
                    617: 
                    618:        if ((entry = map->first_free) == vm_map_to_entry(map))
                    619:                start = map->min_offset;
                    620:        else
                    621:                start = entry->vme_end;
                    622: 
                    623:        /*
                    624:         *      In any case, the "entry" always precedes
                    625:         *      the proposed new region throughout the loop:
                    626:         */
                    627: 
                    628:        while (TRUE) {
                    629:                register vm_map_entry_t next;
                    630: 
                    631:                /*
                    632:                 *      Find the end of the proposed new region.
                    633:                 *      Be sure we didn't go beyond the end, or
                    634:                 *      wrap around the address.
                    635:                 */
                    636: 
                    637:                start = ((start + mask) & ~mask);
                    638:                end = start + size;
                    639: 
                    640:                if ((end > map->max_offset) || (end < start))
                    641:                        return(KERN_NO_SPACE);
                    642: 
                    643:                /*
                    644:                 *      If there are no more entries, we must win.
                    645:                 */
                    646: 
                    647:                next = entry->vme_next;
                    648:                if (next == vm_map_to_entry(map))
                    649:                        break;
                    650: 
                    651:                /*
                    652:                 *      If there is another entry, it must be
                    653:                 *      after the end of the potential new region.
                    654:                 */
                    655: 
                    656:                if (next->vme_start >= end)
                    657:                        break;
                    658: 
                    659:                /*
                    660:                 *      Didn't fit -- move to the next entry.
                    661:                 */
                    662: 
                    663:                entry = next;
                    664:                start = entry->vme_end;
                    665:        }
                    666: 
                    667:        /*
                    668:         *      At this point,
                    669:         *              "start" and "end" should define the endpoints of the
                    670:         *                      available new range, and
                    671:         *              "entry" should refer to the region before the new
                    672:         *                      range, and
                    673:         *
                    674:         *              the map should be locked.
                    675:         */
                    676: 
                    677:        *address = start;
                    678: 
                    679:        /*
                    680:         *      See whether we can avoid creating a new entry by
                    681:         *      extending one of our neighbors.  [So far, we only attempt to
                    682:         *      extend from below.]
                    683:         */
                    684: 
                    685:        if ((object != VM_OBJECT_NULL) &&
                    686:            (entry != vm_map_to_entry(map)) &&
                    687:            (entry->vme_end == start) &&
                    688:            (!entry->is_shared) &&
                    689:            (!entry->is_sub_map) &&
                    690:            (entry->object.vm_object == object) &&
                    691:            (entry->needs_copy == FALSE) &&
                    692:            (entry->inheritance == VM_INHERIT_DEFAULT) &&
                    693:            (entry->protection == VM_PROT_DEFAULT) &&
                    694:            (entry->max_protection == VM_PROT_ALL) &&
                    695:            (entry->wired_count == 1) &&
                    696:            (entry->user_wired_count == 0)) {
                    697:                /*
                    698:                 *      Because this is a special case,
                    699:                 *      we don't need to use vm_object_coalesce.
                    700:                 */
                    701: 
                    702:                entry->vme_end = end;
                    703:                new_entry = entry;
                    704:        } else {
                    705:                new_entry = vm_map_entry_create(map);
                    706: 
                    707:                new_entry->vme_start = start;
                    708:                new_entry->vme_end = end;
                    709: 
                    710:                new_entry->is_shared = FALSE;
                    711:                new_entry->is_sub_map = FALSE;
                    712:                new_entry->object.vm_object = VM_OBJECT_NULL;
                    713:                new_entry->offset = (vm_offset_t) 0;
                    714: 
                    715:                new_entry->needs_copy = FALSE;
                    716: 
                    717:                new_entry->inheritance = VM_INHERIT_DEFAULT;
                    718:                new_entry->protection = VM_PROT_DEFAULT;
                    719:                new_entry->max_protection = VM_PROT_ALL;
                    720:                new_entry->wired_count = 1;
                    721:                new_entry->user_wired_count = 0;
                    722: 
                    723:                new_entry->in_transition = FALSE;
                    724:                new_entry->needs_wakeup = FALSE;
                    725: 
                    726:                /*
                    727:                 *      Insert the new entry into the list
                    728:                 */
                    729: 
                    730:                vm_map_entry_link(map, entry, new_entry);
                    731:        }
                    732: 
                    733:        map->size += size;
                    734: 
                    735:        /*
                    736:         *      Update the free space hint and the lookup hint
                    737:         */
                    738: 
                    739:        map->first_free = new_entry;
                    740:        SAVE_HINT(map, new_entry);
                    741: 
                    742:        *o_entry = new_entry;
                    743:        return(KERN_SUCCESS);
                    744: }
                    745: 
                    746: /*
                    747:  *     vm_map_find finds an unallocated region in the target address
                    748:  *     map with the given length.  The search is defined to be
                    749:  *     first-fit from the specified address; the region found is
                    750:  *     returned in the same parameter.
                    751:  *
                    752:  */
                    753: kern_return_t vm_map_find(map, object, offset, addr, length, find_space)
                    754:        vm_map_t        map;
                    755:        vm_object_t     object;
                    756:        vm_offset_t     offset;
                    757:        vm_offset_t     *addr;          /* IN/OUT */
                    758:        vm_size_t       length;
                    759:        boolean_t       find_space;
                    760: {
                    761:        register vm_map_entry_t entry;
                    762:        register vm_offset_t    start;
                    763:        register vm_offset_t    end;
                    764:        kern_return_t           result;
                    765: 
                    766:        start = *addr;
                    767: 
                    768:        vm_map_lock(map);
                    769: 
                    770:        if (find_space) {
                    771:                /*
                    772:                 *      Calculate the first possible address.
                    773:                 */
                    774: 
                    775:                if (start < map->min_offset)
                    776:                        start = map->min_offset;
                    777:                if (start > map->max_offset) {
                    778:                        vm_map_unlock(map);
                    779:                        return (KERN_NO_SPACE);
                    780:                }
                    781: 
                    782:                /*
                    783:                 *      Look for the first possible address;
                    784:                 *      if there's already something at this
                    785:                 *      address, we have to start after it.
                    786:                 */
                    787: 
                    788:                if (start == map->min_offset) {
                    789:                        if ((entry = map->first_free) != vm_map_to_entry(map))
                    790:                                start = entry->vme_end;
                    791:                } else {
                    792:                        vm_map_entry_t  tmp_entry;
                    793:                        if (vm_map_lookup_entry(map, start, &tmp_entry))
                    794:                                start = tmp_entry->vme_end;
                    795:                        entry = tmp_entry;
                    796:                }
                    797: 
                    798:                /*
                    799:                 *      In any case, the "entry" always precedes
                    800:                 *      the proposed new region throughout the
                    801:                 *      loop:
                    802:                 */
                    803: 
                    804:                while (TRUE) {
                    805:                        register vm_map_entry_t next;
                    806: 
                    807:                        /*
                    808:                         *      Find the end of the proposed new region.
                    809:                         *      Be sure we didn't go beyond the end, or
                    810:                         *      wrap around the address.
                    811:                         */
                    812: 
                    813:                        end = start + length;
                    814: 
                    815:                        if ((end > map->max_offset) || (end < start)) {
                    816:                                vm_map_unlock(map);
                    817:                                return (KERN_NO_SPACE);
                    818:                        }
                    819: 
                    820:                        /*
                    821:                         *      If there are no more entries, we must win.
                    822:                         */
                    823: 
                    824:                        next = entry->vme_next;
                    825:                        if (next == vm_map_to_entry(map))
                    826:                                break;
                    827: 
                    828:                        /*
                    829:                         *      If there is another entry, it must be
                    830:                         *      after the end of the potential new region.
                    831:                         */
                    832: 
                    833:                        if (next->vme_start >= end)
                    834:                                break;
                    835: 
                    836:                        /*
                    837:                         *      Didn't fit -- move to the next entry.
                    838:                         */
                    839: 
                    840:                        entry = next;
                    841:                        start = entry->vme_end;
                    842:                }
                    843:                *addr = start;
                    844:                
                    845:                SAVE_HINT(map, entry);
                    846:        }
                    847: 
                    848:        result = vm_map_insert(map, object, offset, start, start + length);
                    849:        
                    850:        vm_map_unlock(map);
                    851:        return(result);
                    852: }
                    853: 
                    854: /*
                    855:  *     vm_map_clip_start:      [ internal use only ]
                    856:  *
                    857:  *     Asserts that the given entry begins at or after
                    858:  *     the specified address; if necessary,
                    859:  *     it splits the entry into two.
                    860:  */
                    861: void _vm_map_clip_start();
                    862: #define vm_map_clip_start(map, entry, startaddr) \
                    863:        MACRO_BEGIN \
                    864:        if ((startaddr) > (entry)->vme_start) \
                    865:                _vm_map_clip_start(&(map)->hdr,(entry),(startaddr)); \
                    866:        MACRO_END
                    867: 
                    868: void _vm_map_copy_clip_start();
                    869: #define vm_map_copy_clip_start(copy, entry, startaddr) \
                    870:        MACRO_BEGIN \
                    871:        if ((startaddr) > (entry)->vme_start) \
                    872:                _vm_map_clip_start(&(copy)->cpy_hdr,(entry),(startaddr)); \
                    873:        MACRO_END
                    874: 
                    875: /*
                    876:  *     This routine is called only when it is known that
                    877:  *     the entry must be split.
                    878:  */
                    879: void _vm_map_clip_start(map_header, entry, start)
                    880:        register struct vm_map_header *map_header;
                    881:        register vm_map_entry_t entry;
                    882:        register vm_offset_t    start;
                    883: {
                    884:        register vm_map_entry_t new_entry;
                    885: 
                    886:        /*
                    887:         *      Split off the front portion --
                    888:         *      note that we must insert the new
                    889:         *      entry BEFORE this one, so that
                    890:         *      this entry has the specified starting
                    891:         *      address.
                    892:         */
                    893: 
                    894:        new_entry = _vm_map_entry_create(map_header);
                    895:        vm_map_entry_copy_full(new_entry, entry);
                    896: 
                    897:        new_entry->vme_end = start;
                    898:        entry->offset += (start - entry->vme_start);
                    899:        entry->vme_start = start;
                    900: 
                    901:        _vm_map_entry_link(map_header, entry->vme_prev, new_entry);
                    902: 
                    903:        if (entry->is_a_map || entry->is_sub_map)
                    904:                vm_map_reference(new_entry->object.share_map);
                    905:        else
                    906:                vm_object_reference(new_entry->object.vm_object);
                    907: }
                    908: 
                    909: /*
                    910:  *     vm_map_clip_end:        [ internal use only ]
                    911:  *
                    912:  *     Asserts that the given entry ends at or before
                    913:  *     the specified address; if necessary,
                    914:  *     it splits the entry into two.
                    915:  */
                    916: void _vm_map_clip_end();
                    917: #define vm_map_clip_end(map, entry, endaddr) \
                    918:        MACRO_BEGIN \
                    919:        if ((endaddr) < (entry)->vme_end) \
                    920:                _vm_map_clip_end(&(map)->hdr,(entry),(endaddr)); \
                    921:        MACRO_END
                    922: 
                    923: void _vm_map_copy_clip_end();
                    924: #define vm_map_copy_clip_end(copy, entry, endaddr) \
                    925:        MACRO_BEGIN \
                    926:        if ((endaddr) < (entry)->vme_end) \
                    927:                _vm_map_clip_end(&(copy)->cpy_hdr,(entry),(endaddr)); \
                    928:        MACRO_END
                    929: 
                    930: /*
                    931:  *     This routine is called only when it is known that
                    932:  *     the entry must be split.
                    933:  */
                    934: void _vm_map_clip_end(map_header, entry, end)
                    935:        register struct vm_map_header *map_header;
                    936:        register vm_map_entry_t entry;
                    937:        register vm_offset_t    end;
                    938: {
                    939:        register vm_map_entry_t new_entry;
                    940: 
                    941:        /*
                    942:         *      Create a new entry and insert it
                    943:         *      AFTER the specified entry
                    944:         */
                    945: 
                    946:        new_entry = _vm_map_entry_create(map_header);
                    947:        vm_map_entry_copy_full(new_entry, entry);
                    948: 
                    949:        new_entry->vme_start = entry->vme_end = end;
                    950:        new_entry->offset += (end - entry->vme_start);
                    951: 
                    952:        _vm_map_entry_link(map_header, entry, new_entry);
                    953: 
                    954:        if (entry->is_a_map || entry->is_sub_map)
                    955:                vm_map_reference(new_entry->object.share_map);
                    956:        else
                    957:                vm_object_reference(new_entry->object.vm_object);
                    958: }
                    959: 
                    960: /*
                    961:  *     VM_MAP_RANGE_CHECK:     [ internal use only ]
                    962:  *
                    963:  *     Asserts that the starting and ending region
                    964:  *     addresses fall within the valid range of the map.
                    965:  */
                    966: #define        VM_MAP_RANGE_CHECK(map, start, end)             \
                    967:                {                                       \
                    968:                if (start < vm_map_min(map))            \
                    969:                        start = vm_map_min(map);        \
                    970:                if (end > vm_map_max(map))              \
                    971:                        end = vm_map_max(map);          \
                    972:                if (start > end)                        \
                    973:                        start = end;                    \
                    974:                }
                    975: 
                    976: /*
                    977:  *     vm_map_submap:          [ kernel use only ]
                    978:  *
                    979:  *     Mark the given range as handled by a subordinate map.
                    980:  *
                    981:  *     This range must have been created with vm_map_find,
                    982:  *     and no other operations may have been performed on this
                    983:  *     range prior to calling vm_map_submap.
                    984:  *
                    985:  *     Only a limited number of operations can be performed
                    986:  *     within this rage after calling vm_map_submap:
                    987:  *             vm_fault
                    988:  *     [Don't try vm_map_copy!]
                    989:  *
                    990:  *     To remove a submapping, one must first remove the
                    991:  *     range from the superior map, and then destroy the
                    992:  *     submap (if desired).  [Better yet, don't try it.]
                    993:  */
                    994: kern_return_t vm_map_submap(map, start, end, submap)
                    995:        register vm_map_t       map;
                    996:        register vm_offset_t    start;
                    997:        register vm_offset_t    end;
                    998:        vm_map_t                submap;
                    999: {
                   1000:        vm_map_entry_t          entry;
                   1001:        register kern_return_t  result = KERN_INVALID_ARGUMENT;
                   1002:        register vm_object_t    object;
                   1003: 
                   1004:        vm_map_lock(map);
                   1005: 
                   1006:        VM_MAP_RANGE_CHECK(map, start, end);
                   1007: 
                   1008:        if (vm_map_lookup_entry(map, start, &entry)) {
                   1009:                vm_map_clip_start(map, entry, start);
                   1010:        }
                   1011:         else
                   1012:                entry = entry->vme_next;
                   1013: 
                   1014:        vm_map_clip_end(map, entry, end);
                   1015: 
                   1016:        if ((entry->vme_start == start) && (entry->vme_end == end) &&
                   1017:            (!entry->is_a_map) &&
                   1018:            ((object = entry->object.vm_object) == vm_submap_object) &&
                   1019:            (!entry->copy_on_write)) {
                   1020:                entry->object.vm_object = VM_OBJECT_NULL;
                   1021:                vm_object_deallocate(object);
                   1022:                entry->is_sub_map = TRUE;
                   1023:                vm_map_reference(entry->object.sub_map = submap);
                   1024:                result = KERN_SUCCESS;
                   1025:        }
                   1026:        vm_map_unlock(map);
                   1027: 
                   1028:        return(result);
                   1029: }
                   1030: 
                   1031: /*
                   1032:  *     vm_map_protect:
                   1033:  *
                   1034:  *     Sets the protection of the specified address
                   1035:  *     region in the target map.  If "set_max" is
                   1036:  *     specified, the maximum protection is to be set;
                   1037:  *     otherwise, only the current protection is affected.
                   1038:  */
                   1039: kern_return_t vm_map_protect(map, start, end, new_prot, set_max)
                   1040:        register vm_map_t       map;
                   1041:        register vm_offset_t    start;
                   1042:        register vm_offset_t    end;
                   1043:        register vm_prot_t      new_prot;
                   1044:        register boolean_t      set_max;
                   1045: {
                   1046:        register vm_map_entry_t         current;
                   1047:        vm_map_entry_t                  entry;
                   1048: 
                   1049:        vm_map_lock(map);
                   1050: 
                   1051:        VM_MAP_RANGE_CHECK(map, start, end);
                   1052: 
                   1053:        if (vm_map_lookup_entry(map, start, &entry)) {
                   1054:                vm_map_clip_start(map, entry, start);
                   1055:        }
                   1056:         else
                   1057:                entry = entry->vme_next;
                   1058: 
                   1059:        /*
                   1060:         *      Make a first pass to check for protection
                   1061:         *      violations.
                   1062:         */
                   1063: 
                   1064:        current = entry;
                   1065:        while ((current != vm_map_to_entry(map)) &&
                   1066:               (current->vme_start < end)) {
                   1067:                if (current->is_sub_map) {
                   1068:                        vm_map_unlock(map);
                   1069:                        return(KERN_INVALID_ARGUMENT);
                   1070:                }
                   1071:                if ((new_prot & current->max_protection) != new_prot) {
                   1072:                        vm_map_unlock(map);
                   1073:                        return(KERN_PROTECTION_FAILURE);
                   1074:                }
                   1075: 
                   1076:                current = current->vme_next;
                   1077:        }
                   1078: 
                   1079:        /*
                   1080:         *      Go back and fix up protections.
                   1081:         *      [Note that clipping is not necessary the second time.]
                   1082:         */
                   1083: 
                   1084:        current = entry;
                   1085: 
                   1086:        while ((current != vm_map_to_entry(map)) &&
                   1087:               (current->vme_start < end)) {
                   1088:                vm_prot_t       old_prot;
                   1089: 
                   1090:                vm_map_clip_end(map, current, end);
                   1091: 
                   1092:                old_prot = current->protection;
                   1093:                if (set_max)
                   1094:                        current->protection =
                   1095:                                (current->max_protection = new_prot) &
                   1096:                                        old_prot;
                   1097:                else
                   1098:                        current->protection = new_prot;
                   1099: 
                   1100:                /*
                   1101:                 *      Update physical map if necessary.
                   1102:                 *      Worry about copy-on-write here -- CHECK THIS XXX
                   1103:                 */
                   1104: 
                   1105:                if (current->protection != old_prot) {
                   1106: 
                   1107: #define MASK(entry)    ((entry)->copy_on_write ? ~VM_PROT_WRITE : \
                   1108:                                                        VM_PROT_ALL)
                   1109: #define        max(a,b)        ((a) > (b) ? (a) : (b))
                   1110: 
                   1111:                        if (current->is_a_map) {
                   1112:                                vm_map_entry_t  share_entry;
                   1113:                                vm_offset_t     share_end;
                   1114: 
                   1115:                                vm_map_lock(current->object.share_map);
                   1116:                                (void) vm_map_lookup_entry(
                   1117:                                                current->object.share_map,
                   1118:                                                current->offset,
                   1119:                                                &share_entry);
                   1120:                                share_end = current->offset +
                   1121:                                        (current->vme_end -
                   1122:                                                current->vme_start);
                   1123:                                while ((share_entry !=
                   1124:                                        vm_map_to_entry(
                   1125:                                                current->object.share_map)) &&
                   1126:                                        (share_entry->vme_start < share_end)) {
                   1127: 
                   1128:                                        pmap_protect(map->pmap,
                   1129:                                                (max(share_entry->vme_start,
                   1130:                                                        current->offset) -
                   1131:                                                        current->offset +
                   1132:                                                        current->vme_start),
                   1133:                                                max(share_entry->vme_end,
                   1134:                                                        share_end) -
                   1135:                                                current->offset +
                   1136:                                                current->vme_start,
                   1137:                                                current->protection &
                   1138:                                                        MASK(share_entry));
                   1139: 
                   1140:                                        share_entry = share_entry->vme_next;
                   1141:                                }
                   1142:                                vm_map_unlock(current->object.share_map);
                   1143:                        }
                   1144:                        else
                   1145:                                pmap_protect(map->pmap, current->vme_start,
                   1146:                                        current->vme_end,
                   1147:                                        current->protection & MASK(entry));
                   1148: #undef max
                   1149: #undef MASK
                   1150:                }
                   1151:                current = current->vme_next;
                   1152:        }
                   1153: 
                   1154:        vm_map_unlock(map);
                   1155:        return(KERN_SUCCESS);
                   1156: }
                   1157: 
                   1158: /*
                   1159:  *     vm_map_inherit:
                   1160:  *
                   1161:  *     Sets the inheritance of the specified address
                   1162:  *     range in the target map.  Inheritance
                   1163:  *     affects how the map will be shared with
                   1164:  *     child maps at the time of vm_map_fork.
                   1165:  */
                   1166: kern_return_t vm_map_inherit(map, start, end, new_inheritance)
                   1167:        register vm_map_t       map;
                   1168:        register vm_offset_t    start;
                   1169:        register vm_offset_t    end;
                   1170:        register vm_inherit_t   new_inheritance;
                   1171: {
                   1172:        register vm_map_entry_t entry;
                   1173:        vm_map_entry_t  temp_entry;
                   1174: 
                   1175:        switch (new_inheritance) {
                   1176:        case VM_INHERIT_NONE:
                   1177:        case VM_INHERIT_COPY:
                   1178:        case VM_INHERIT_SHARE:
                   1179:                break;
                   1180:        default:
                   1181:                return(KERN_INVALID_ARGUMENT);
                   1182:        }
                   1183: 
                   1184:        vm_map_lock(map);
                   1185: 
                   1186:        VM_MAP_RANGE_CHECK(map, start, end);
                   1187: 
                   1188:        if (vm_map_lookup_entry(map, start, &temp_entry)) {
                   1189:                entry = temp_entry;
                   1190:                vm_map_clip_start(map, entry, start);
                   1191:        }
                   1192:        else
                   1193:                entry = temp_entry->vme_next;
                   1194: 
                   1195:        while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
                   1196:                vm_map_clip_end(map, entry, end);
                   1197: 
                   1198:                entry->inheritance = new_inheritance;
                   1199: 
                   1200:                entry = entry->vme_next;
                   1201:        }
                   1202: 
                   1203:        vm_map_unlock(map);
                   1204:        return(KERN_SUCCESS);
                   1205: }
                   1206: 
                   1207: #if NeXT
                   1208: extern vm_map_t kernel_map;
                   1209: #endif
                   1210: 
                   1211: /*
                   1212:  *     vm_map_pageable:
                   1213:  *
                   1214:  *     Sets the pageability of the specified address
                   1215:  *     range in the target map.  Regions specified
                   1216:  *     as not pageable require locked-down physical
                   1217:  *     memory and physical page maps.
                   1218:  *
                   1219:  *     The map must not be locked, but a reference
                   1220:  *     must remain to the map throughout the call.
                   1221:  */
                   1222: kern_return_t vm_map_pageable(map, start, end, new_pageable)
                   1223:        register vm_map_t       map;
                   1224:        register vm_offset_t    start;
                   1225:        register vm_offset_t    end;
                   1226:        register boolean_t      new_pageable;
                   1227: {
                   1228:        register vm_map_entry_t entry;
                   1229:        vm_map_entry_t          temp_entry;
                   1230: #if NeXT
                   1231:        int map_locked = 1;
                   1232: #endif
                   1233: 
                   1234:        vm_map_lock(map);
                   1235: 
                   1236:        VM_MAP_RANGE_CHECK(map, start, end);
                   1237: 
                   1238:        /*
                   1239:         *      Only one pageability change may take place at one
                   1240:         *      time, since vm_fault assumes it will be called
                   1241:         *      only once for each wiring/unwiring.  Therefore, we
                   1242:         *      have to make sure we're actually changing the pageability
                   1243:         *      for the entire region.  We do so before making any changes.
                   1244:         */
                   1245: 
                   1246:        if (vm_map_lookup_entry(map, start, &temp_entry)) {
                   1247:                entry = temp_entry;
                   1248:                vm_map_clip_start(map, entry, start);
                   1249:        }
                   1250:        else
                   1251:                entry = temp_entry->vme_next;
                   1252:        temp_entry = entry;
                   1253: 
                   1254:        /*
                   1255:         *      Actions are rather different for wiring and unwiring,
                   1256:         *      so we have two separate cases.
                   1257:         */
                   1258: 
                   1259:        if (new_pageable) {
                   1260: 
                   1261:                /*
                   1262:                 *      Unwiring.  First ensure that the range to be
                   1263:                 *      unwired is really wired down.
                   1264:                 */
                   1265:                while ((entry != vm_map_to_entry(map)) &&
                   1266:                       (entry->vme_start < end)) {
                   1267: 
                   1268:                    if (entry->wired_count == 0) {
                   1269:                        vm_map_unlock(map);
                   1270:                        return(KERN_INVALID_ARGUMENT);
                   1271:                    }
                   1272:                    entry = entry->vme_next;
                   1273:                }
                   1274: 
                   1275:                /*
                   1276:                 *      Now decrement the wiring count for each region.
                   1277:                 *      If a region becomes completely unwired,
                   1278:                 *      unwire its physical pages and mappings.
                   1279:                 */
                   1280:                entry = temp_entry;
                   1281:                while ((entry != vm_map_to_entry(map)) && 
                   1282:                       (entry->vme_start < end)) {
                   1283:                    vm_map_clip_end(map, entry, end);
                   1284: 
                   1285:                    entry->wired_count--;
                   1286:                    if (entry->wired_count == 0)
                   1287:                        vm_fault_unwire(map, entry);
                   1288: 
                   1289:                    entry = entry->vme_next;
                   1290:                }
                   1291:        }
                   1292: 
                   1293:        else {
                   1294:                /*
                   1295:                 *      Wiring.  We must do this in two passes:
                   1296:                 *
                   1297:                 *      1.  Holding the write lock, we increment the
                   1298:                 *          wiring count.  For any area that is not already
                   1299:                 *          wired, we create any shadow objects that need
                   1300:                 *          to be created.
                   1301:                 *
                   1302:                 *      2.  We downgrade to a read lock, and call
                   1303:                 *          vm_fault_wire to fault in the pages for any
                   1304:                 *          newly wired area (wired_count is 1).
                   1305:                 *
                   1306:                 *      Downgrading to a read lock for vm_fault_wire avoids
                   1307:                 *      a possible deadlock with another thread that may have
                   1308:                 *      faulted on one of the pages to be wired (it would mark
                   1309:                 *      the page busy, blocking us, then in turn block on the
                   1310:                 *      map lock that we hold).  Because of problems in the
                   1311:                 *      recursive lock package, we cannot upgrade to a write
                   1312:                 *      lock in vm_map_lookup.  Thus, any actions that require
                   1313:                 *      the write lock must be done beforehand.  Because we
                   1314:                 *      keep the read lock on the map, the copy-on-write status
                   1315:                 *      of the entries we modify here cannot change.
                   1316:                 */
                   1317: 
                   1318:                /*
                   1319:                 *      Pass 1.
                   1320:                 */
                   1321:                entry = temp_entry;
                   1322:                while ((entry != vm_map_to_entry(map)) &&
                   1323:                       (entry->vme_start < end)) {
                   1324:                    vm_map_clip_end(map, entry, end);
                   1325: 
1.1.1.2 ! root     1326:                    if (++entry->wired_count == 0)
        !          1327:                        panic("vm_map_pageable: wired_count");
1.1       root     1328:                    if (entry->wired_count == 1) {
                   1329: 
                   1330:                        /*
                   1331:                         *      Perform actions of vm_map_lookup that need
                   1332:                         *      the write lock on the map: create a shadow
                   1333:                         *      object for a copy-on-write region, or an
                   1334:                         *      object for a zero-fill region.
                   1335:                         *
                   1336:                         *      We don't have to do this for entries that
                   1337:                         *      point to sharing maps, because we won't hold
                   1338:                         *      the lock on the sharing map.
                   1339:                         */
                   1340:                        if (!entry->is_a_map) {
                   1341:                            if (entry->needs_copy &&
                   1342:                                ((entry->protection & VM_PROT_WRITE) != 0)) {
                   1343: 
                   1344:                                vm_object_shadow(&entry->object.vm_object,
                   1345:                                                &entry->offset,
                   1346:                                                (vm_size_t)(entry->vme_end
                   1347:                                                        - entry->vme_start));
                   1348:                                entry->needs_copy = FALSE;
                   1349:                            }
                   1350:                            else if (entry->object.vm_object == VM_OBJECT_NULL) {
                   1351:                                entry->object.vm_object =
                   1352:                                    vm_object_allocate(
                   1353:                                        (vm_size_t)(entry->vme_end
                   1354:                                                        - entry->vme_start));
                   1355:                                entry->offset = (vm_offset_t)0;
                   1356:                            }
                   1357:                        }
                   1358:                    }
                   1359: 
                   1360:                    entry = entry->vme_next;
                   1361:                }
                   1362: 
                   1363:                /*
                   1364:                 *      Pass 2.
                   1365:                 */
                   1366: 
                   1367:                /* If we are wiring pages in the kernel map 
                   1368:                 * we know that the map will not be modified in a
                   1369:                 * destructive way. Drivers call us to wire in
                   1370:                 * pages after they do a vm_map_copy into the
                   1371:                 * kernel. Enhancing submaps to allow vm_map_copies
                   1372:                 * is a better long term solution. For now we will 
                   1373:                 * release the lock to prevent deadlock.
                   1374:                 */
                   1375:                if (map == kernel_map){
                   1376:                        map_locked = 0;
                   1377:                        vm_map_unlock(map);
                   1378:                } else {
                   1379:                        lock_set_recursive(&map->lock);
                   1380:                        lock_write_to_read(&map->lock);
                   1381:                }
                   1382: 
                   1383:                entry = temp_entry;
                   1384:                while ((entry != vm_map_to_entry(map)) &&
                   1385:                       (entry->vme_start < end)) {
                   1386:                    if (entry->wired_count == 1) {
                   1387:                        vm_fault_wire(map, entry);
                   1388:                    }
                   1389:                    entry = entry->vme_next;
                   1390:                }
                   1391: 
                   1392:                if (map_locked){
                   1393:                        lock_clear_recursive(&map->lock);
                   1394:                }
                   1395:        }
                   1396: 
                   1397:        if (map_locked){
                   1398:                vm_map_unlock(map);
                   1399:        }
                   1400: 
                   1401:        return(KERN_SUCCESS);
                   1402: }
                   1403: 
                   1404: /*
                   1405:  *     vm_map_entry_unwire:    [ internal use only ]
                   1406:  *
                   1407:  *     Make the region specified by this entry pageable.
                   1408:  *
                   1409:  *     The map in question should be locked.
                   1410:  *     [This is the reason for this routine's existence.]
                   1411:  */
                   1412: void vm_map_entry_unwire(map, entry)
                   1413:        vm_map_t                map;
                   1414:        register vm_map_entry_t entry;
                   1415: {
                   1416:        vm_fault_unwire(map, entry);
                   1417:        entry->wired_count = 0;
                   1418: }
                   1419: 
                   1420: /*
                   1421:  *     vm_map_entry_delete:    [ internal use only ]
                   1422:  *
                   1423:  *     Deallocate the given entry from the target map.
                   1424:  */            
                   1425: void vm_map_entry_delete(map, entry)
                   1426:        register vm_map_t       map;
                   1427:        register vm_map_entry_t entry;
                   1428: {
                   1429:        if (entry->wired_count != 0)
                   1430:                vm_map_entry_unwire(map, entry);
                   1431:                
                   1432:        vm_map_entry_unlink(map, entry);
                   1433:        map->size -= entry->vme_end - entry->vme_start;
                   1434: 
                   1435:        if (entry->is_a_map || entry->is_sub_map)
                   1436:                vm_map_deallocate(entry->object.share_map);
                   1437:        else
                   1438:                vm_object_deallocate(entry->object.vm_object);
                   1439: 
                   1440:        vm_map_entry_dispose(map, entry);
                   1441: }
                   1442: 
                   1443: /*
                   1444:  *     vm_map_delete:  [ internal use only ]
                   1445:  *
                   1446:  *     Deallocates the given address range from the target
                   1447:  *     map.
                   1448:  *
                   1449:  *     When called with a sharing map, removes pages from
                   1450:  *     that region from all physical maps.
                   1451:  */
                   1452: kern_return_t vm_map_delete(map, start, end)
                   1453:        register vm_map_t       map;
                   1454:        vm_offset_t             start;
                   1455:        register vm_offset_t    end;
                   1456: {
                   1457:        register vm_map_entry_t entry;
                   1458:        vm_map_entry_t          first_entry;
                   1459: 
                   1460:        /*
                   1461:         *      Find the start of the region, and clip it
                   1462:         */
                   1463: 
                   1464:        if (!vm_map_lookup_entry(map, start, &first_entry))
                   1465:                entry = first_entry->vme_next;
                   1466:        else {
                   1467:                entry = first_entry;
                   1468:                vm_map_clip_start(map, entry, start);
                   1469: 
                   1470:                /*
                   1471:                 *      Fix the lookup hint now, rather than each
                   1472:                 *      time though the loop.
                   1473:                 */
                   1474: 
                   1475:                SAVE_HINT(map, entry->vme_prev);
                   1476:        }
                   1477: 
                   1478:        /*
                   1479:         *      Save the free space hint
                   1480:         */
                   1481: 
                   1482:        if (map->first_free->vme_start >= start)
                   1483:                map->first_free = entry->vme_prev;
                   1484: 
                   1485:        /*
                   1486:         *      Step through all entries in this region
                   1487:         */
                   1488: 
                   1489:        while ((entry != vm_map_to_entry(map)) &&
                   1490:               (entry->vme_start < end)) {
                   1491:                vm_map_entry_t          next;
                   1492:                register vm_offset_t    s, e;
                   1493:                register vm_object_t    object;
                   1494:                extern vm_object_t      kernel_object;
                   1495: 
                   1496:                vm_map_clip_end(map, entry, end);
                   1497: 
                   1498:                next = entry->vme_next;
                   1499:                s = entry->vme_start;
                   1500:                e = entry->vme_end;
                   1501: 
                   1502:                /*
                   1503:                 *      Unwire before removing addresses from the pmap;
                   1504:                 *      otherwise, unwiring will put the entries back in
                   1505:                 *      the pmap.
                   1506:                 */
                   1507: 
                   1508:                object = entry->object.vm_object;
                   1509:                if (entry->wired_count != 0)
                   1510:                        vm_map_entry_unwire(map, entry);
                   1511: 
                   1512:                if (object == kernel_object)
                   1513:                        vm_object_page_remove(object, entry->offset,
                   1514:                                        entry->offset + (e - s));
                   1515:                
                   1516:                /*
                   1517:                 *      If this is a sharing map, we must remove
                   1518:                 *      *all* references to this data, since we can't
                   1519:                 *      find all of the physical maps which are sharing
                   1520:                 *      it.
                   1521:                 */
                   1522: 
                   1523:                if (!map->is_main_map)
                   1524:                        vm_object_pmap_remove(object,
                   1525:                                         entry->offset,
                   1526:                                         entry->offset + (e - s));
                   1527: 
                   1528:                pmap_remove(map->pmap, s, e);
                   1529: 
                   1530:                /*
                   1531:                 *      Delete the entry (which may delete the object)
                   1532:                 *      only after removing all pmap entries pointing
                   1533:                 *      to its pages.  (Otherwise, its page frames may
                   1534:                 *      be reallocated, and any modify bits will be
                   1535:                 *      set in the wrong object!)
                   1536:                 */
                   1537: 
                   1538:                vm_map_entry_delete(map, entry);
                   1539:                entry = next;
                   1540:        }
                   1541:        return(KERN_SUCCESS);
                   1542: }
                   1543: 
                   1544: /*
                   1545:  *     vm_map_remove:
                   1546:  *
                   1547:  *     Remove the given address range from the target map.
                   1548:  *     This is the exported form of vm_map_delete.
                   1549:  */
                   1550: kern_return_t vm_map_remove(map, start, end)
                   1551:        register vm_map_t       map;
                   1552:        register vm_offset_t    start;
                   1553:        register vm_offset_t    end;
                   1554: {
                   1555:        register kern_return_t  result;
                   1556: 
                   1557:        vm_map_lock(map);
                   1558:        VM_MAP_RANGE_CHECK(map, start, end);
                   1559:        result = vm_map_delete(map, start, end);
                   1560:        vm_map_unlock(map);
                   1561: 
                   1562:        return(result);
                   1563: }
                   1564: 
                   1565: kern_return_t vm_map_reallocate(map, start, end)
                   1566:        register vm_map_t       map;
                   1567:        register vm_offset_t    start;
                   1568:        register vm_offset_t    end;
                   1569: {
                   1570:        register vm_map_entry_t entry;
                   1571:        vm_map_entry_t          first_entry;
                   1572: 
                   1573:        vm_map_lock(map);
                   1574:        VM_MAP_RANGE_CHECK(map, start, end);
                   1575: 
                   1576:        /*
                   1577:         *      Find the start of the region, and clip it
                   1578:         */
                   1579: 
                   1580:        if (!vm_map_lookup_entry(map, start, &first_entry))
                   1581:                entry = first_entry->vme_next;
                   1582:        else {
                   1583:                entry = first_entry;
                   1584:                vm_map_clip_start(map, entry, start);
                   1585: 
                   1586:                /*
                   1587:                 *      Fix the lookup hint now, rather than each
                   1588:                 *      time though the loop.
                   1589:                 */
                   1590: 
                   1591:                SAVE_HINT(map, entry->vme_prev);
                   1592:        }
                   1593: 
                   1594:        /*
                   1595:         *      Step through all entries in this region
                   1596:         */
                   1597: 
                   1598:        while ((entry != vm_map_to_entry(map)) &&
                   1599:               (entry->vme_start < end)) {
                   1600:                vm_map_entry_t          next;
                   1601:                register vm_offset_t    s, e;
                   1602:                register vm_object_t    object;
                   1603:                extern vm_object_t      kernel_object;
                   1604: 
                   1605:                vm_map_clip_end(map, entry, end);
                   1606: 
                   1607:                next = entry->vme_next;
                   1608:                s = entry->vme_start;
                   1609:                e = entry->vme_end;
                   1610: 
                   1611:                /*
                   1612:                 *      Unwire before removing addresses from the pmap;
                   1613:                 *      otherwise, unwiring will put the entries back in
                   1614:                 *      the pmap.
                   1615:                 */
                   1616: 
                   1617:                object = entry->object.vm_object;
                   1618:                if (entry->wired_count != 0)
                   1619:                        vm_map_entry_unwire(map, entry);
                   1620: 
                   1621:                if (object == kernel_object)
                   1622:                        vm_object_page_remove(object, entry->offset,
                   1623:                                        entry->offset + (e - s));
                   1624:                
                   1625:                /*
                   1626:                 *      If this is a sharing map, we must remove
                   1627:                 *      *all* references to this data, since we can't
                   1628:                 *      find all of the physical maps which are sharing
                   1629:                 *      it.
                   1630:                 */
                   1631: 
                   1632:                if (!map->is_main_map)
                   1633:                        vm_object_pmap_remove(object,
                   1634:                                         entry->offset,
                   1635:                                         entry->offset + (e - s));
                   1636: 
                   1637:                pmap_remove(map->pmap, s, e);
                   1638: 
                   1639:                /*
                   1640:                 *      Release the reference to the underlying object
                   1641:                 *      only after removing all pmap entries pointing
                   1642:                 *      to its pages.  (Otherwise, its page frames may
                   1643:                 *      be reallocated, and any modify bits will be
                   1644:                 *      set in the wrong object!)
                   1645:                 */
                   1646: 
                   1647:                if (entry->is_a_map || entry->is_sub_map)
                   1648:                        vm_map_deallocate(entry->object.share_map);
                   1649:                else
                   1650:                        vm_object_deallocate(entry->object.vm_object);
                   1651: 
                   1652:                entry->is_a_map = FALSE;
                   1653:                entry->is_sub_map = FALSE;
                   1654:                entry->object.vm_object = VM_OBJECT_NULL;
                   1655:                entry->offset = 0;
                   1656: 
                   1657:                entry->copy_on_write = FALSE;
                   1658:                entry->needs_copy = FALSE;
                   1659: 
                   1660:                if (map->is_main_map) {
                   1661:                        entry->protection =
                   1662:                                (entry->max_protection & VM_PROT_DEFAULT);
                   1663:                        entry->wired_count = 0;
                   1664:                }
                   1665: 
                   1666:                entry = next;
                   1667:        }
                   1668: 
                   1669:        vm_map_unlock(map);
                   1670: 
                   1671:        return(KERN_SUCCESS);
                   1672: }
                   1673: 
                   1674: /*
                   1675:  *     vm_map_check_protection:
                   1676:  *
                   1677:  *     Assert that the target map allows the specified
                   1678:  *     privilege on the entire address region given.
                   1679:  *     The entire region must be allocated.
                   1680:  */
                   1681: boolean_t vm_map_check_protection(map, start, end, protection)
                   1682:        register vm_map_t       map;
                   1683:        register vm_offset_t    start;
                   1684:        register vm_offset_t    end;
                   1685:        register vm_prot_t      protection;
                   1686: {
                   1687:        register vm_map_entry_t entry;
                   1688:        vm_map_entry_t          tmp_entry;
                   1689: 
                   1690:        if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   1691:                return(FALSE);
                   1692:        }
                   1693: 
                   1694:        entry = tmp_entry;
                   1695: 
                   1696:        while (start < end) {
                   1697:                if (entry == vm_map_to_entry(map)) {
                   1698:                        return(FALSE);
                   1699:                }
                   1700: 
                   1701:                /*
                   1702:                 *      No holes allowed!
                   1703:                 */
                   1704: 
                   1705:                if (start < entry->vme_start) {
                   1706:                        return(FALSE);
                   1707:                }
                   1708: 
                   1709:                /*
                   1710:                 * Check protection associated with entry.
                   1711:                 */
                   1712: 
                   1713:                if ((entry->protection & protection) != protection) {
                   1714:                        return(FALSE);
                   1715:                }
                   1716: 
                   1717:                /* go to next entry */
                   1718: 
                   1719:                start = entry->vme_end;
                   1720:                entry = entry->vme_next;
                   1721:        }
                   1722:        return(TRUE);
                   1723: }
                   1724: 
                   1725: /*
                   1726:  *     vm_map_copy_entry:
                   1727:  *
                   1728:  *     Copies the contents of the source entry to the destination
                   1729:  *     entry.  The entries *must* be aligned properly.
                   1730:  */
                   1731: void vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry)
                   1732:        vm_map_t                src_map, dst_map;
                   1733:        register vm_map_entry_t src_entry, dst_entry;
                   1734: {
                   1735:        vm_object_t     temp_object;
                   1736: 
                   1737:        if (src_entry->is_sub_map || dst_entry->is_sub_map)
                   1738:                return;
                   1739: 
                   1740:        /*
                   1741:         *      If our destination map was wired down,
                   1742:         *      unwire it now.
                   1743:         */
                   1744: 
                   1745:        if (dst_entry->wired_count != 0)
                   1746:                vm_map_entry_unwire(dst_map, dst_entry);
                   1747: 
                   1748:        /*
                   1749:         *      If we're dealing with a sharing map, we
                   1750:         *      must remove the destination pages from
                   1751:         *      all maps (since we cannot know which maps
                   1752:         *      this sharing map belongs in).
                   1753:         */
                   1754: 
                   1755:        if (!dst_map->is_main_map)
                   1756:                vm_object_pmap_remove(dst_entry->object.vm_object,
                   1757:                        dst_entry->offset,
                   1758:                        dst_entry->offset +
                   1759:                                (dst_entry->vme_end - dst_entry->vme_start));
                   1760: 
                   1761:        pmap_remove(dst_map->pmap, dst_entry->vme_start, dst_entry->vme_end);
                   1762: 
                   1763:        if (src_entry->wired_count == 0) {
                   1764: 
                   1765:                boolean_t       src_needs_copy;
                   1766: 
                   1767:                /*
                   1768:                 *      If the source entry is marked needs_copy,
                   1769:                 *      it is already write-protected.
                   1770:                 */
                   1771:                if (!src_entry->needs_copy) {
                   1772: 
                   1773:                        boolean_t       su;
                   1774: 
                   1775:                        /*
                   1776:                         *      If the source entry has only one mapping,
                   1777:                         *      we can just protect the virtual address
                   1778:                         *      range.
                   1779:                         */
                   1780:                        if (!(su = src_map->is_main_map)) {
                   1781:                                simple_lock(&src_map->ref_lock);
                   1782:                                su = (src_map->ref_count == 1);
                   1783:                                simple_unlock(&src_map->ref_lock);
                   1784:                        }
                   1785: 
                   1786:                        if (su) {
                   1787:                                pmap_protect(src_map->pmap,
                   1788:                                        src_entry->vme_start,
                   1789:                                        src_entry->vme_end,
                   1790:                                        src_entry->protection & ~VM_PROT_WRITE);
                   1791:                        }
                   1792:                        else {
                   1793:                                vm_object_pmap_copy(src_entry->object.vm_object,
                   1794:                                        src_entry->offset,
                   1795:                                        src_entry->offset + (src_entry->vme_end
                   1796:                                                            -src_entry->vme_start));
                   1797:                        }
                   1798:                }
                   1799: 
                   1800:                /*
                   1801:                 *      Make a copy of the object.
                   1802:                 */
                   1803:                temp_object = dst_entry->object.vm_object;
                   1804:                vm_object_copy(src_entry->object.vm_object,
                   1805:                                src_entry->offset,
                   1806:                                (vm_size_t)(src_entry->vme_end -
                   1807:                                            src_entry->vme_start),
                   1808:                                &dst_entry->object.vm_object,
                   1809:                                &dst_entry->offset,
                   1810:                                &src_needs_copy);
                   1811:                /*
                   1812:                 *      If we didn't get a copy-object now, mark the
                   1813:                 *      source map entry so that a shadow will be created
                   1814:                 *      to hold its changed pages.
                   1815:                 */
                   1816:                if (src_needs_copy)
                   1817:                        src_entry->needs_copy = TRUE;
                   1818: 
                   1819:                /*
                   1820:                 *      The destination always needs to have a shadow
                   1821:                 *      created.
                   1822:                 */
                   1823:                dst_entry->needs_copy = TRUE;
                   1824: 
                   1825:                /*
                   1826:                 *      Mark the entries copy-on-write, so that write-enabling
                   1827:                 *      the entry won't make copy-on-write pages writable.
                   1828:                 */
                   1829:                src_entry->copy_on_write = TRUE;
                   1830:                dst_entry->copy_on_write = TRUE;
                   1831: /* XXX */
                   1832:                if (src_entry->protection & VM_PROT_EXECUTE)
                   1833:                        dst_entry->protection |= (VM_PROT_EXECUTE & dst_entry->max_protection);
                   1834: /* XXX */
                   1835:                /*
                   1836:                 *      Get rid of the old object.
                   1837:                 */
                   1838:                vm_object_deallocate(temp_object);
                   1839: 
                   1840:                pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->vme_start,
                   1841:                        dst_entry->vme_end - dst_entry->vme_start, src_entry->vme_start);
                   1842:        }
                   1843:        else {
                   1844:                /*
                   1845:                 *      Of course, wired down pages can't be set copy-on-write.
                   1846:                 *      Cause wired pages to be copied into the new
                   1847:                 *      map by simulating faults (the new pages are
                   1848:                 *      pageable)
                   1849:                 */
                   1850:                vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry);
                   1851:        }
                   1852: }
                   1853: 
                   1854: /*
                   1855:  *     vm_map_copy:
                   1856:  *
                   1857:  *     Perform a virtual memory copy from the source
                   1858:  *     address map/range to the destination map/range.
                   1859:  *
                   1860:  *     If src_destroy or dst_alloc is requested,
                   1861:  *     the source and destination regions should be
                   1862:  *     disjoint, not only in the top-level map, but
                   1863:  *     in the sharing maps as well.  [The best way
                   1864:  *     to guarantee this is to use a new intermediate
                   1865:  *     map to make copies.  This also reduces map
                   1866:  *     fragmentation.]
                   1867:  */
                   1868: kern_return_t vm_map_copy(dst_map, src_map,
                   1869:                          dst_addr, len, src_addr,
                   1870:                          dst_alloc, src_destroy)
                   1871:        vm_map_t        dst_map;
                   1872:        vm_map_t        src_map;
                   1873:        vm_offset_t     dst_addr;
                   1874:        vm_size_t       len;
                   1875:        vm_offset_t     src_addr;
                   1876:        boolean_t       dst_alloc;
                   1877:        boolean_t       src_destroy;
                   1878: {
                   1879:        register
                   1880:        vm_map_entry_t  src_entry;
                   1881:        register
                   1882:        vm_map_entry_t  dst_entry;
                   1883:        vm_map_entry_t  tmp_entry;
                   1884:        vm_offset_t     src_start;
                   1885:        vm_offset_t     src_end;
                   1886:        vm_offset_t     dst_start;
                   1887:        vm_offset_t     dst_end;
                   1888:        vm_offset_t     src_clip;
                   1889:        vm_offset_t     dst_clip;
                   1890:        kern_return_t   result;
                   1891:        boolean_t       old_src_destroy;
                   1892: 
                   1893:        /*
                   1894:         *      XXX While we figure out why src_destroy screws up,
                   1895:         *      we'll do it by explicitly vm_map_delete'ing at the end.
                   1896:         */
                   1897: 
                   1898:        old_src_destroy = src_destroy;
                   1899:        src_destroy = FALSE;
                   1900: 
                   1901:        /*
                   1902:         *      Compute start and end of region in both maps
                   1903:         */
                   1904: 
                   1905:        src_start = src_addr;
                   1906:        src_end = src_start + len;
                   1907:        dst_start = dst_addr;
                   1908:        dst_end = dst_start + len;
                   1909: 
                   1910:        /*
                   1911:         *      Check that the region can exist in both source
                   1912:         *      and destination.
                   1913:         */
                   1914: 
                   1915:        if ((dst_end < dst_start) || (src_end < src_start))
                   1916:                return(KERN_NO_SPACE);
                   1917: 
                   1918:        /*
                   1919:         *      Lock the maps in question -- we avoid deadlock
                   1920:         *      by ordering lock acquisition by map value
                   1921:         */
                   1922: 
                   1923:        if (src_map == dst_map) {
                   1924:                vm_map_lock(src_map);
                   1925:        }
                   1926:        else if ((int) src_map < (int) dst_map) {
                   1927:                vm_map_lock(src_map);
                   1928:                vm_map_lock(dst_map);
                   1929:        } else {
                   1930:                vm_map_lock(dst_map);
                   1931:                vm_map_lock(src_map);
                   1932:        }
                   1933: 
                   1934:        result = KERN_SUCCESS;
                   1935: 
                   1936:        /*
                   1937:         *      Check protections... source must be completely readable and
                   1938:         *      destination must be completely writable.  [Note that if we're
                   1939:         *      allocating the destination region, we don't have to worry
                   1940:         *      about protection, but instead about whether the region
                   1941:         *      exists.]
                   1942:         */
                   1943: 
                   1944:        if (src_map->is_main_map && dst_map->is_main_map) {
                   1945:                if (!vm_map_check_protection(src_map, src_start, src_end,
                   1946:                                        VM_PROT_READ)) {
                   1947:                        result = KERN_PROTECTION_FAILURE;
                   1948:                        goto Return;
                   1949:                }
                   1950: 
                   1951:                if (dst_alloc) {
                   1952:                        /* XXX Consider making this a vm_map_find instead */
                   1953:                        if ((result = vm_map_insert(dst_map, VM_OBJECT_NULL,
                   1954:                                        (vm_offset_t) 0, dst_start, dst_end)) != KERN_SUCCESS)
                   1955:                                goto Return;
                   1956:                }
                   1957:                else if (!vm_map_check_protection(dst_map, dst_start, dst_end,
                   1958:                                        VM_PROT_WRITE)) {
                   1959:                        result = KERN_PROTECTION_FAILURE;
                   1960:                        goto Return;
                   1961:                }
                   1962:        }
                   1963: 
                   1964:        /*
                   1965:         *      Find the start entries and clip.
                   1966:         *
                   1967:         *      Note that checking protection asserts that the
                   1968:         *      lookup cannot fail.
                   1969:         *
                   1970:         *      Also note that we wait to do the second lookup
                   1971:         *      until we have done the first clip, as the clip
                   1972:         *      may affect which entry we get!
                   1973:         */
                   1974: 
                   1975:        (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
                   1976:        src_entry = tmp_entry;
                   1977:        vm_map_clip_start(src_map, src_entry, src_start);
                   1978: 
                   1979:        (void) vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry);
                   1980:        dst_entry = tmp_entry;
                   1981:        vm_map_clip_start(dst_map, dst_entry, dst_start);
                   1982: 
                   1983:        /*
                   1984:         *      If both source and destination entries are the same,
                   1985:         *      retry the first lookup, as it may have changed.
                   1986:         */
                   1987: 
                   1988:        if (src_entry == dst_entry) {
                   1989:                (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
                   1990:                src_entry = tmp_entry;
                   1991:        }
                   1992: 
                   1993:        /*
                   1994:         *      If source and destination entries are still the same,
                   1995:         *      a null copy is being performed.
                   1996:         */
                   1997: 
                   1998:        if (src_entry == dst_entry)
                   1999:                goto Return;
                   2000: 
                   2001:        /*
                   2002:         *      Go through entries until we get to the end of the
                   2003:         *      region.
                   2004:         */
                   2005: 
                   2006:        while (src_start < src_end) {
                   2007:                /*
                   2008:                 *      Clip the entries to the endpoint of the entire region.
                   2009:                 */
                   2010: 
                   2011:                vm_map_clip_end(src_map, src_entry, src_end);
                   2012:                vm_map_clip_end(dst_map, dst_entry, dst_end);
                   2013: 
                   2014:                /*
                   2015:                 *      Clip each entry to the endpoint of the other entry.
                   2016:                 */
                   2017: 
                   2018:                src_clip = src_entry->vme_start + (dst_entry->vme_end - dst_entry->vme_start);
                   2019:                vm_map_clip_end(src_map, src_entry, src_clip);
                   2020: 
                   2021:                dst_clip = dst_entry->vme_start + (src_entry->vme_end - src_entry->vme_start);
                   2022:                vm_map_clip_end(dst_map, dst_entry, dst_clip);
                   2023: 
                   2024:                /*
                   2025:                 *      Both entries now match in size and relative endpoints.
                   2026:                 *
                   2027:                 *      If both entries refer to a VM object, we can
                   2028:                 *      deal with them now.
                   2029:                 */
                   2030: 
                   2031:                if (!src_entry->is_a_map && !dst_entry->is_a_map) {
                   2032:                        vm_map_copy_entry(src_map, dst_map, src_entry,
                   2033:                                                dst_entry);
                   2034:                }
                   2035:                else {
                   2036:                        register vm_map_t       new_dst_map;
                   2037:                        vm_offset_t             new_dst_start;
                   2038:                        vm_size_t               new_size;
                   2039:                        vm_map_t                new_src_map;
                   2040:                        vm_offset_t             new_src_start;
                   2041: 
                   2042:                        /*
                   2043:                         *      We have to follow at least one sharing map.
                   2044:                         */
                   2045: 
                   2046:                        new_size = (dst_entry->vme_end - dst_entry->vme_start);
                   2047: 
                   2048:                        if (src_entry->is_a_map) {
                   2049:                                new_src_map = src_entry->object.share_map;
                   2050:                                new_src_start = src_entry->offset;
                   2051:                        }
                   2052:                        else {
                   2053:                                new_src_map = src_map;
                   2054:                                new_src_start = src_entry->vme_start;
                   2055:                                lock_set_recursive(&src_map->lock);
                   2056:                        }
                   2057: 
                   2058:                        if (dst_entry->is_a_map) {
                   2059:                                vm_offset_t     new_dst_end;
                   2060: 
                   2061:                                new_dst_map = dst_entry->object.share_map;
                   2062:                                new_dst_start = dst_entry->offset;
                   2063: 
                   2064:                                /*
                   2065:                                 *      Since the destination sharing entries
                   2066:                                 *      will be merely deallocated, we can
                   2067:                                 *      do that now, and replace the region
                   2068:                                 *      with a null object.  [This prevents
                   2069:                                 *      splitting the source map to match
                   2070:                                 *      the form of the destination map.]
                   2071:                                 *      Note that we can only do so if the
                   2072:                                 *      source and destination do not overlap.
                   2073:                                 */
                   2074: 
                   2075:                                new_dst_end = new_dst_start + new_size;
                   2076: 
                   2077:                                if (new_dst_map != new_src_map) {
                   2078:                                        vm_map_lock(new_dst_map);
                   2079:                                        (void) vm_map_delete(new_dst_map,
                   2080:                                                        new_dst_start,
                   2081:                                                        new_dst_end);
                   2082:                                        (void) vm_map_insert(new_dst_map,
                   2083:                                                        VM_OBJECT_NULL,
                   2084:                                                        (vm_offset_t) 0,
                   2085:                                                        new_dst_start,
                   2086:                                                        new_dst_end);
                   2087:                                        vm_map_unlock(new_dst_map);
                   2088:                                }
                   2089:                        }
                   2090:                        else {
                   2091:                                new_dst_map = dst_map;
                   2092:                                new_dst_start = dst_entry->vme_start;
                   2093:                                lock_set_recursive(&dst_map->lock);
                   2094:                        }
                   2095: 
                   2096:                        /*
                   2097:                         *      Recursively copy the sharing map.
                   2098:                         */
                   2099: 
                   2100:                        (void) vm_map_copy(new_dst_map, new_src_map,
                   2101:                                new_dst_start, new_size, new_src_start,
                   2102:                                FALSE, FALSE);
                   2103: 
                   2104:                        if (dst_map == new_dst_map)
                   2105:                                lock_clear_recursive(&dst_map->lock);
                   2106:                        if (src_map == new_src_map)
                   2107:                                lock_clear_recursive(&src_map->lock);
                   2108:                }
                   2109: 
                   2110:                /*
                   2111:                 *      Update variables for next pass through the loop.
                   2112:                 */
                   2113: 
                   2114:                src_start = src_entry->vme_end;
                   2115:                src_entry = src_entry->vme_next;
                   2116:                dst_start = dst_entry->vme_end;
                   2117:                dst_entry = dst_entry->vme_next;
                   2118: 
                   2119:                /*
                   2120:                 *      If the source is to be destroyed, here is the
                   2121:                 *      place to do it.
                   2122:                 */
                   2123: 
                   2124:                if (src_destroy && src_map->is_main_map &&
                   2125:                                                dst_map->is_main_map)
                   2126:                        vm_map_entry_delete(src_map, src_entry->vme_prev);
                   2127:        }
                   2128: 
                   2129:        /*
                   2130:         *      Update the physical maps as appropriate
                   2131:         */
                   2132: 
                   2133:        if (src_map->is_main_map && dst_map->is_main_map) {
                   2134:                if (src_destroy)
                   2135:                        pmap_remove(src_map->pmap, src_addr, src_addr + len);
                   2136:        }
                   2137: 
                   2138:        /*
                   2139:         *      Unlock the maps
                   2140:         */
                   2141: 
                   2142:        Return: ;
                   2143: 
                   2144:        if (old_src_destroy)
                   2145:                vm_map_delete(src_map, src_addr, src_addr + len);
                   2146: 
                   2147:        vm_map_unlock(src_map);
                   2148:        if (src_map != dst_map)
                   2149:                vm_map_unlock(dst_map);
                   2150: 
                   2151:        return(result);
                   2152: }
                   2153: 
                   2154: /*
                   2155:  *     vm_map_fork:
                   2156:  *
                   2157:  *     Create and return a new map based on the old
                   2158:  *     map, according to the inheritance values on the
                   2159:  *     regions in that map.
                   2160:  *
                   2161:  *     The source map must not be locked.
                   2162:  */
                   2163: vm_map_t vm_map_fork(old_map)
                   2164:        vm_map_t        old_map;
                   2165: {
                   2166:        vm_map_t        new_map;
                   2167:        vm_map_entry_t  old_entry;
                   2168:        vm_map_entry_t  new_entry;
                   2169:        pmap_t          new_pmap;
                   2170: 
                   2171:        vm_map_lock(old_map);
                   2172: 
                   2173:        new_pmap = pmap_create((vm_size_t) 0);
                   2174:        new_map = vm_map_create(new_pmap,
                   2175:                        old_map->min_offset,
                   2176:                        old_map->max_offset,
                   2177:                        old_map->hdr.entries_pageable);
                   2178: 
                   2179:        old_entry = vm_map_first_entry(old_map);
                   2180: 
                   2181:        while (old_entry != vm_map_to_entry(old_map)) {
                   2182:                if (old_entry->is_sub_map)
                   2183:                        panic("vm_map_fork: encountered a submap");
                   2184: 
                   2185:                switch (old_entry->inheritance) {
                   2186:                case VM_INHERIT_NONE:
                   2187:                        break;
                   2188: 
                   2189:                case VM_INHERIT_SHARE:
                   2190:                        /*
                   2191:                         *      If we don't already have a sharing map:
                   2192:                         */
                   2193: 
                   2194:                        if (!old_entry->is_a_map) {
                   2195:                                vm_map_t        new_share_map;
                   2196:                                vm_map_entry_t  new_share_entry;
                   2197:                                
                   2198:                                /*
                   2199:                                 *      Create a new sharing map
                   2200:                                 */
                   2201:                                 
                   2202:                                new_share_map = vm_map_create(PMAP_NULL,
                   2203:                                                        old_entry->vme_start,
                   2204:                                                        old_entry->vme_end,
                   2205:                                                        TRUE);
                   2206:                                new_share_map->is_main_map = FALSE;
                   2207: 
                   2208:                                /*
                   2209:                                 *      Create the only sharing entry from the
                   2210:                                 *      old task map entry.
                   2211:                                 */
                   2212: 
                   2213:                                new_share_entry =
                   2214:                                        vm_map_entry_create(new_share_map);
                   2215:                                *new_share_entry = *old_entry;
                   2216: 
                   2217:                                /*
                   2218:                                 *      Insert the entry into the new sharing
                   2219:                                 *      map
                   2220:                                 */
                   2221: 
                   2222:                                vm_map_entry_link(new_share_map,
                   2223:                                        vm_map_last_entry(new_share_map),
                   2224:                                                new_share_entry);
                   2225: 
                   2226:                                /*
                   2227:                                 *      Fix up the task map entry to refer
                   2228:                                 *      to the sharing map now.
                   2229:                                 */
                   2230: 
                   2231:                                old_entry->is_a_map = TRUE;
                   2232:                                old_entry->object.share_map = new_share_map;
                   2233:                                old_entry->offset = old_entry->vme_start;
                   2234:                        }
                   2235: 
                   2236:                        /*
                   2237:                         *      Clone the entry, referencing the sharing map.
                   2238:                         */
                   2239: 
                   2240:                        new_entry = vm_map_entry_create(new_map);
                   2241:                        *new_entry = *old_entry;
                   2242:                        vm_map_reference(new_entry->object.share_map);
                   2243: 
                   2244:                        /*
                   2245:                         *      Insert the entry into the new map -- we
                   2246:                         *      know we're inserting at the end of the new
                   2247:                         *      map.
                   2248:                         */
                   2249: 
                   2250:                        vm_map_entry_link(new_map,
                   2251:                                vm_map_last_entry(new_map),
                   2252:                                                new_entry);
                   2253: 
                   2254:                        /*
                   2255:                         *      Update the physical map
                   2256:                         */
                   2257: 
                   2258:                        pmap_copy(new_map->pmap, old_map->pmap,
                   2259:                                new_entry->vme_start,
                   2260:                                (old_entry->vme_end - old_entry->vme_start),
                   2261:                                old_entry->vme_start);
                   2262:                        break;
                   2263: 
                   2264:                case VM_INHERIT_COPY:
                   2265:                        /*
                   2266:                         *      Clone the entry and link into the map.
                   2267:                         */
                   2268: 
                   2269:                        new_entry = vm_map_entry_create(new_map);
                   2270:                        *new_entry = *old_entry;
                   2271:                        new_entry->wired_count = 0;
                   2272:                        new_entry->object.vm_object = VM_OBJECT_NULL;
                   2273:                        new_entry->is_a_map = FALSE;
                   2274:                        vm_map_entry_link(new_map,
                   2275:                                vm_map_last_entry(new_map),
                   2276:                                                        new_entry);
                   2277:                        if (old_entry->is_a_map) {
                   2278:                                kern_return_t   check;
                   2279: 
                   2280:                                check = vm_map_copy(new_map,
                   2281:                                                old_entry->object.share_map,
                   2282:                                                new_entry->vme_start,
                   2283:                                                (vm_size_t)
                   2284:                                                        (new_entry->vme_end -
                   2285:                                                        new_entry->vme_start),
                   2286:                                                old_entry->offset,
                   2287:                                                FALSE, FALSE);
                   2288:                                if (check != KERN_SUCCESS)
                   2289:                                        kprintf("vm_map_fork: copy in share_map region failed\n");
                   2290:                        }
                   2291:                        else {
                   2292:                                vm_map_copy_entry(old_map, new_map, old_entry,
                   2293:                                                new_entry);
                   2294:                        }
                   2295:                        break;
                   2296:                }
                   2297:                old_entry = old_entry->vme_next;
                   2298:        }
                   2299: 
                   2300:        new_map->size = old_map->size;
                   2301:        vm_map_unlock(old_map);
                   2302: 
                   2303:        return(new_map);
                   2304: }
                   2305: 
                   2306: /*
                   2307:  *     vm_map_lookup:
                   2308:  *
                   2309:  *     Finds the VM object, offset, and
                   2310:  *     protection for a given virtual address in the
                   2311:  *     specified map, assuming a page fault of the
                   2312:  *     type specified.
                   2313:  *
                   2314: #if    USE_VERSIONS
                   2315:  *     Returns the (object, offset, protection) for
                   2316:  *     this address, whether it is wired down, and whether
                   2317:  *     this map has the only reference to the data in question.
                   2318:  *     In order to later verify this lookup, a "version"
                   2319:  *     is returned.
                   2320:  *
                   2321:  *     The map should not be locked; it will not be
                   2322:  *     locked on exit.  In order to guarantee the
                   2323:  *     existence of the returned object, it is returned
                   2324:  *     locked.
                   2325: #else  USE_VERSIONS
                   2326:  *     Leaves the map in question locked for read; return
                   2327:  *     values are guaranteed until a vm_map_lookup_done
                   2328:  *     call is performed.  Note that the map argument
                   2329:  *     is in/out; the returned map must be used in
                   2330:  *     the call to vm_map_lookup_done.
                   2331:  *
                   2332:  *     A handle (out_entry) is returned for use in
                   2333:  *     vm_map_lookup_done, to make that fast.
                   2334: #endif USE_VERSIONS
                   2335:  *
                   2336:  *     If a lookup is requested with "write protection"
                   2337:  *     specified, the map may be changed to perform virtual
                   2338:  *     copying operations, although the data referenced will
                   2339:  *     remain the same.
                   2340:  */
                   2341: #if    USE_VERSIONS
                   2342: kern_return_t vm_map_lookup(var_map, vaddr, fault_type, out_version,
                   2343:                                object, offset, out_prot, wired, single_use)
                   2344: #else  USE_VERSIONS
                   2345: kern_return_t vm_map_lookup(var_map, vaddr, fault_type, out_entry,
                   2346:                                object, offset, out_prot, wired, single_use)
                   2347: #endif USE_VERSIONS
                   2348:        vm_map_t                *var_map;       /* IN/OUT */
                   2349:        register vm_offset_t    vaddr;
                   2350:        register vm_prot_t      fault_type;
                   2351: 
                   2352: #if    USE_VERSIONS
                   2353:        vm_map_version_t        *out_version;   /* OUT */
                   2354: #else  USE_VERSIONS
                   2355:        vm_map_entry_t          *out_entry;     /* OUT */
                   2356: #endif USE_VERSIONS
                   2357:        vm_object_t             *object;        /* OUT */
                   2358:        vm_offset_t             *offset;        /* OUT */
                   2359:        vm_prot_t               *out_prot;      /* OUT */
                   2360:        boolean_t               *wired;         /* OUT */
                   2361:        boolean_t               *single_use;    /* OUT */
                   2362: {
                   2363:        vm_map_t                        share_map;
                   2364:        vm_offset_t                     share_offset;
                   2365:        register vm_map_entry_t         entry;
                   2366:        register vm_map_t               map = *var_map;
                   2367:        register vm_prot_t              prot;
                   2368:        register boolean_t              su;
                   2369: 
                   2370:        RetryLookup: ;
                   2371: 
                   2372:        /*
                   2373:         *      Lookup the faulting address.
                   2374:         */
                   2375: 
                   2376:        vm_map_lock_read(map);
                   2377: 
                   2378: #define        L_RETURN(why) \
                   2379:                { \
                   2380:                vm_map_unlock_read(map); \
                   2381:                return(why); \
                   2382:                }
                   2383: 
                   2384:        /*
                   2385:         *      If the map has an interesting hint, try it before calling
                   2386:         *      full blown lookup routine.
                   2387:         */
                   2388: 
                   2389:        simple_lock(&map->hint_lock);
                   2390:        entry = map->hint;
                   2391:        simple_unlock(&map->hint_lock);
                   2392: 
                   2393: #if    !USE_VERSIONS
                   2394:        *out_entry = entry;
                   2395: #endif !USE_VERSIONS
                   2396: 
                   2397:        if ((entry == vm_map_to_entry(map)) ||
                   2398:            (vaddr < entry->vme_start) || (vaddr >= entry->vme_end)) {
                   2399:                vm_map_entry_t  tmp_entry;
                   2400: 
                   2401:                /*
                   2402:                 *      Entry was either not a valid hint, or the vaddr
                   2403:                 *      was not contained in the entry, so do a full lookup.
                   2404:                 */
                   2405:                if (!vm_map_lookup_entry(map, vaddr, &tmp_entry))
                   2406:                        L_RETURN(KERN_INVALID_ADDRESS);
                   2407: 
                   2408:                entry = tmp_entry;
                   2409: #if    !USE_VERSIONS
                   2410:                *out_entry = entry;
                   2411: #endif !USE_VERSIONS
                   2412:        }
                   2413: 
                   2414:        /*
                   2415:         *      Handle submaps.
                   2416:         */
                   2417: 
                   2418:        if (entry->is_sub_map) {
                   2419:                vm_map_t        old_map = map;
                   2420: 
                   2421:                *var_map = map = entry->object.sub_map;
                   2422:                vm_map_unlock_read(old_map);
                   2423:                goto RetryLookup;
                   2424:        }
                   2425:                
                   2426:        /*
                   2427:         *      Check whether this task is allowed to have
                   2428:         *      this page.
                   2429:         */
                   2430: 
                   2431:        prot = entry->protection;
                   2432:        if ((fault_type & (prot)) != fault_type)
                   2433:                L_RETURN(KERN_PROTECTION_FAILURE);
                   2434: 
                   2435:        /*
                   2436:         *      If this page is not pageable, we have to get
                   2437:         *      it for all possible accesses.
                   2438:         */
                   2439: 
                   2440:        if (*wired = (entry->wired_count != 0))
                   2441:                prot = fault_type = entry->protection;
                   2442: 
                   2443:        /*
                   2444:         *      If we don't already have a VM object, track
                   2445:         *      it down.
                   2446:         */
                   2447: 
                   2448:        if (su = !entry->is_a_map) {
                   2449:                share_map = map;
                   2450:                share_offset = vaddr;
                   2451:        }
                   2452:        else {
                   2453:                vm_map_entry_t  share_entry;
                   2454: 
                   2455:                /*
                   2456:                 *      Compute the sharing map, and offset into it.
                   2457:                 */
                   2458: 
                   2459:                share_map = entry->object.share_map;
                   2460:                share_offset = (vaddr - entry->vme_start) + entry->offset;
                   2461: 
                   2462:                /*
                   2463:                 *      Look for the backing store object and offset
                   2464:                 */
                   2465: 
                   2466:                vm_map_lock_read(share_map);
                   2467: 
                   2468:                if (!vm_map_lookup_entry(share_map, share_offset,
                   2469:                                        &share_entry)) {
                   2470:                        vm_map_unlock_read(share_map);
                   2471:                        L_RETURN(KERN_INVALID_ADDRESS);
                   2472:                }
                   2473:                entry = share_entry;
                   2474:        }
                   2475: 
                   2476:        /*
                   2477:         *      If the entry was copy-on-write, we either ...
                   2478:         */
                   2479: 
                   2480:        if (entry->needs_copy) {
                   2481:                /*
                   2482:                 *      If we want to write the page, we may as well
                   2483:                 *      handle that now since we've got the sharing
                   2484:                 *      map locked.
                   2485:                 *
                   2486:                 *      If we don't need to write the page, we just
                   2487:                 *      demote the permissions allowed.
                   2488:                 */
                   2489: 
                   2490:                if (fault_type & VM_PROT_WRITE) {
                   2491:                        /*
                   2492:                         *      Make a new object, and place it in the
                   2493:                         *      object chain.  Note that no new references
                   2494:                         *      have appeared -- one just moved from the
                   2495:                         *      share map to the new object.
                   2496:                         */
                   2497: 
                   2498:                        if (lock_read_to_write(&share_map->lock)) {
                   2499:                                if (share_map != map)
                   2500:                                        vm_map_unlock_read(map);
                   2501:                                goto RetryLookup;
                   2502:                        }
                   2503: 
                   2504:                        vm_object_shadow(
                   2505:                                &entry->object.vm_object,
                   2506:                                &entry->offset,
                   2507:                                (vm_size_t) (entry->vme_end -
                   2508:                                                        entry->vme_start));
                   2509:                                
                   2510:                        entry->needs_copy = FALSE;
                   2511:                        
                   2512:                        lock_write_to_read(&share_map->lock);
                   2513:                }
                   2514:                else {
                   2515:                        /*
                   2516:                         *      We're attempting to read a copy-on-write
                   2517:                         *      page -- don't allow writes.
                   2518:                         */
                   2519: 
                   2520:                        prot &= (~VM_PROT_WRITE);
                   2521:                }
                   2522:        }
                   2523: 
                   2524:        /*
                   2525:         *      Create an object if necessary.
                   2526:         */
                   2527:        if (entry->object.vm_object == VM_OBJECT_NULL) {
                   2528: 
                   2529:                if (lock_read_to_write(&share_map->lock)) {
                   2530:                        if (share_map != map)
                   2531:                                vm_map_unlock_read(map);
                   2532:                        goto RetryLookup;
                   2533:                }
                   2534: 
                   2535:                entry->object.vm_object = vm_object_allocate(
                   2536:                                        (vm_size_t)(entry->vme_end -
                   2537:                                                        entry->vme_start));
                   2538:                entry->offset = 0;
                   2539:                lock_write_to_read(&share_map->lock);
                   2540:        }
                   2541: 
                   2542:        /*
                   2543:         *      Return the object/offset from this entry.  If the entry
                   2544:         *      was copy-on-write or empty, it has been fixed up.
                   2545:         */
                   2546: 
                   2547:        *offset = (share_offset - entry->vme_start) + entry->offset;
                   2548:        *object = entry->object.vm_object;
                   2549: 
                   2550:        /*
                   2551:         *      Return whether this is the only map sharing this data.
                   2552:         */
                   2553: 
                   2554:        if (!su) {
                   2555:                simple_lock(&share_map->ref_lock);
                   2556:                su = (share_map->ref_count == 1);
                   2557:                simple_unlock(&share_map->ref_lock);
                   2558:        }
                   2559: 
                   2560:        *out_prot = prot;
                   2561:        *single_use = su;
                   2562: 
                   2563: #if    USE_VERSIONS
                   2564:        /*
                   2565:         *      Lock the object to prevent it from disappearing
                   2566:         */
                   2567: 
                   2568:        vm_object_lock(*object);
                   2569: 
                   2570:        /*
                   2571:         *      Save the version numbers and unlock the map(s).
                   2572:         */
                   2573: 
                   2574:        if (share_map != map) {
                   2575:                out_version->share_timestamp = share_map->timestamp;
                   2576:                vm_map_unlock_read(share_map);
                   2577:        }
                   2578:        out_version->share_map = share_map;
                   2579:        out_version->main_timestamp = map->timestamp;
                   2580: 
                   2581:        vm_map_unlock_read(map);
                   2582: #endif USE_VERSIONS
                   2583: 
                   2584:        return(KERN_SUCCESS);
                   2585:        
                   2586: #undef L_RETURN
                   2587: }
                   2588: 
                   2589: #if    USE_VERSIONS
                   2590: /*
                   2591:  *     vm_map_verify:
                   2592:  *
                   2593:  *     Verifies that the map in question has not changed
                   2594:  *     since the given version.  If successful, the map
                   2595:  *     will not change until vm_map_verify_done() is called.
                   2596:  */
                   2597: boolean_t      vm_map_verify(map, version)
                   2598:        register
                   2599:        vm_map_t        map;
                   2600:        register
                   2601:        vm_map_version_t *version;      /* REF */
                   2602: {
                   2603:        boolean_t       result;
                   2604: 
                   2605:        vm_map_lock_read(map);
                   2606:        if (result = (map->timestamp == version->main_timestamp)) {
                   2607:                register
                   2608:                vm_map_t        share_map = version->share_map;
                   2609: 
                   2610:                if (share_map != map) {
                   2611:                        vm_map_lock_read(version->share_map);
                   2612:                        if (!(result = (share_map->timestamp == version->share_timestamp))) {
                   2613:                                vm_map_unlock_read(share_map);
                   2614:                        }
                   2615:                }
                   2616:        }
                   2617: 
                   2618:        if (!result)
                   2619:                vm_map_unlock_read(map);
                   2620: 
                   2621:        return(result);
                   2622: }
                   2623: 
                   2624: /*
                   2625:  *     vm_map_verify_done:
                   2626:  *
                   2627:  *     Releases locks acquired by a vm_map_verify.
                   2628:  */
                   2629: void           vm_map_verify_done(map, version)
                   2630:        register vm_map_t       map;
                   2631:        vm_map_version_t        *version;       /* REF */
                   2632: {
                   2633:        if (version->share_map != map)
                   2634:                vm_map_unlock_read(version->share_map);
                   2635:        vm_map_unlock_read(map);
                   2636: }
                   2637: 
                   2638: #else  USE_VERSIONS
                   2639: 
                   2640: /*
                   2641:  *     vm_map_lookup_done:
                   2642:  *
                   2643:  *     Releases locks acquired by a vm_map_lookup
                   2644:  *     (according to the handle returned by that lookup).
                   2645:  */
                   2646: 
                   2647: void vm_map_lookup_done(map, entry)
                   2648:        register vm_map_t       map;
                   2649:        vm_map_entry_t          entry;
                   2650: {
                   2651:        /*
                   2652:         *      If this entry references a map, unlock it first.
                   2653:         */
                   2654: 
                   2655:        if (entry->is_a_map)
                   2656:                vm_map_unlock_read(entry->object.share_map);
                   2657: 
                   2658:        /*
                   2659:         *      Unlock the main-level map
                   2660:         */
                   2661: 
                   2662:        vm_map_unlock_read(map);
                   2663: }
                   2664: #endif USE_VERSIONS
                   2665: 
                   2666: /*
                   2667:  *     Routine:        vm_map_machine_attribute
                   2668:  *     Purpose:
                   2669:  *             Provide machine-specific attributes to mappings,
                   2670:  *             such as cachability etc. for machines that provide
                   2671:  *             them.  NUMA architectures and machines with big/strange
                   2672:  *             caches will use this.
                   2673:  *     Note:
                   2674:  *             Responsibilities for locking and checking are handled here,
                   2675:  *             everything else in the pmap module. If any non-volatile
                   2676:  *             information must be kept, the pmap module should handle
                   2677:  *             it itself. [This assumes that attributes do not
                   2678:  *             need to be inherited, which seems ok to me]
                   2679:  */
                   2680: kern_return_t vm_map_machine_attribute(map, address, size, attribute, value)
                   2681:        vm_map_t        map;
                   2682:        vm_offset_t     address;
                   2683:        vm_size_t       size;
                   2684:        vm_machine_attribute_t  attribute;
                   2685:        vm_machine_attribute_val_t* value;              /* IN/OUT */
                   2686: {
                   2687:        kern_return_t   ret;
                   2688: 
                   2689:        if (address < vm_map_min(map) ||
                   2690:            (address + size) > vm_map_max(map))
                   2691:                return KERN_INVALID_ARGUMENT;
                   2692: 
                   2693:        vm_map_lock(map);
                   2694: 
                   2695:        ret = pmap_attribute(map->pmap, address, size, attribute, value);
                   2696: 
                   2697:        vm_map_unlock(map);
                   2698: 
                   2699:        return ret;
                   2700: }
                   2701: 
                   2702: #if    DEBUG
                   2703: /*
                   2704:  *     vm_map_print:   [ debug ]
                   2705:  */
                   2706: #if    1
                   2707: /*
                   2708:  * vm_map_print() is way out of date...
                   2709:  */
                   2710: void vm_map_print(vm_map_t map)
                   2711: {
                   2712: 
                   2713: }
                   2714: #else  1
                   2715: void vm_map_print(map)
                   2716:        register vm_map_t       map;
                   2717: {
                   2718:        register vm_map_entry_t entry;
                   2719:        extern int indent;
                   2720: 
                   2721:        iprintf("%s map 0x%x: pmap=0x%x,ref=%d,nentries=%d,version=%d\n",
                   2722:                (map->is_main_map ? "Task" : "Share"),
                   2723:                (int) map, (int) (map->pmap), map->ref_count, map->nentries,
                   2724:                map->timestamp);
                   2725:        indent += 2;
                   2726:        for (entry = map->header.next; entry != &map->header;
                   2727:                                entry = entry->next) {
                   2728:                iprintf("map entry 0x%x: start=0x%x, end=0x%x, ",
                   2729:                        (int) entry, (int) entry->start, (int) entry->end);
                   2730:                if (map->is_main_map) {
                   2731:                        static char *inheritance_name[4] =
                   2732:                                { "share", "copy", "none", "donate_copy"};
                   2733:                        printf("prot=%x/%x/%s, ",
                   2734:                                entry->protection,
                   2735:                                entry->max_protection,
                   2736:                                inheritance_name[entry->inheritance]);
                   2737:                        if (entry->wired_count != 0)
                   2738:                                printf("wired, ");
                   2739:                }
                   2740: 
                   2741:                if (entry->is_a_map) {
                   2742:                        printf("share=0x%x, offset=0x%x\n",
                   2743:                                (int) entry->object.share_map,
                   2744:                                (int) entry->offset);
                   2745:                        if ((entry->prev == &map->header) || (!entry->prev->is_a_map) ||
                   2746:                            (entry->prev->object.share_map != entry->object.share_map)) {
                   2747:                                indent += 2;
                   2748:                                vm_map_print(entry->object.share_map);
                   2749:                                indent -= 2;
                   2750:                        }
                   2751:                                
                   2752:                }
                   2753:                else {
                   2754:                        printf("object=0x%x, offset=0x%x",
                   2755:                                (int) entry->object.vm_object,
                   2756:                                (int) entry->offset);
                   2757:                        if (entry->copy_on_write)
                   2758:                                printf(", copy (%s)", entry->needs_copy ? "needed" : "done");
                   2759:                        printf("\n");
                   2760: 
                   2761:                        if ((entry->prev == &map->header) || (entry->prev->is_a_map) ||
                   2762:                            (entry->prev->object.vm_object != entry->object.vm_object)) {
                   2763:                                indent += 2;
                   2764:                                vm_object_print(entry->object.vm_object);
                   2765:                                indent -= 2;
                   2766:                        }
                   2767:                }
                   2768:        }
                   2769:        indent -= 2;
                   2770: }
                   2771: #endif 1
                   2772: #endif DEBUG
                   2773: 
                   2774: kern_return_t  vm_region(map, address, size,
                   2775:                                protection, max_protection,
                   2776:                                inheritance, is_shared,
                   2777:                                object_name, offset_in_object)
                   2778:        vm_map_t        map;
                   2779:        vm_offset_t     *address;               /* IN/OUT */
                   2780:        vm_size_t       *size;                  /* OUT */
                   2781:        vm_prot_t       *protection;            /* OUT */
                   2782:        vm_prot_t       *max_protection;        /* OUT */
                   2783:        vm_inherit_t    *inheritance;           /* OUT */
                   2784:        boolean_t       *is_shared;             /* OUT */
                   2785:        port_t          *object_name;           /* OUT */
                   2786:        vm_offset_t     *offset_in_object;      /* OUT */
                   2787: {
                   2788:        vm_map_entry_t  tmp_entry;
                   2789:        register
                   2790:        vm_map_entry_t  entry;
                   2791:        register
                   2792:        vm_offset_t     tmp_offset;
                   2793:        vm_offset_t     start, inaddress = *address;
                   2794: 
                   2795:        if (map == VM_MAP_NULL)
                   2796:                return(KERN_INVALID_ARGUMENT);
                   2797: 
                   2798: again_after_submap:    
                   2799:        start = *address;
                   2800: 
                   2801:        vm_map_lock_read(map);
                   2802:        if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   2803:                if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
                   2804:                        vm_map_unlock_read(map);
                   2805:                        return(KERN_NO_SPACE);
                   2806:                }
                   2807:        } else {
                   2808:                entry = tmp_entry;
                   2809:        }
                   2810: 
                   2811:        start = entry->vme_start;
                   2812:        *protection = entry->protection;
                   2813:        *max_protection = entry->max_protection;
                   2814:        *inheritance = entry->inheritance;
                   2815:        *address = start;
                   2816:        *size = (entry->vme_end - start);
                   2817: 
                   2818:        tmp_offset = entry->offset;
                   2819: #define VM_OBJECT_NAME(object)         \
                   2820:        vm_object_name((map == kernel_map) ? object : VM_OBJECT_NULL)
                   2821: 
                   2822:        if (entry->is_a_map) {
                   2823:                register
                   2824:                vm_map_t        share_map;
                   2825:                vm_size_t       share_size;
                   2826: 
                   2827:                share_map = entry->object.share_map;
                   2828: 
                   2829:                vm_map_lock_read(share_map);
                   2830:                (void) vm_map_lookup_entry(share_map, tmp_offset, &tmp_entry);
                   2831: 
                   2832:                if ((share_size = (tmp_entry->vme_end - tmp_offset)) < *size)
                   2833:                        *size = share_size;
                   2834: 
                   2835:                *object_name = VM_OBJECT_NAME(tmp_entry->object.vm_object);
                   2836:                *offset_in_object = tmp_entry->offset +
                   2837:                                        (tmp_offset - tmp_entry->vme_start);
                   2838: 
                   2839:                *is_shared = (share_map->ref_count != 1);
                   2840:                vm_map_unlock_read(share_map);
                   2841:        } else if (entry->is_sub_map) {
                   2842:                vm_map_t        sub_map;
                   2843:                vm_offset_t     oldstart = start;
                   2844: 
                   2845:                sub_map = entry->object.sub_map;
                   2846:                vm_map_reference(sub_map);
                   2847:                vm_map_unlock_read(map);
                   2848: 
                   2849:                vm_map_lock_read(sub_map);
                   2850: 
                   2851:                if (!vm_map_lookup_entry(sub_map, inaddress, &tmp_entry)) {
                   2852:                        if ((entry = tmp_entry->vme_next) ==
                   2853:                                        vm_map_to_entry(sub_map)) {
                   2854:                                vm_map_unlock_read(sub_map);
                   2855:                                vm_map_deallocate(sub_map);
                   2856:                                inaddress = *address = oldstart + *size;
                   2857:                                goto again_after_submap;
                   2858:                        }
                   2859:                }
                   2860:                else
                   2861:                        entry = tmp_entry;
                   2862: 
                   2863:                start = entry->vme_start;
                   2864:                *protection = entry->protection;
                   2865:                *max_protection = entry->max_protection;
                   2866:                *inheritance = entry->inheritance;
                   2867:                *address = start;
                   2868:                *size = (entry->vme_end - start);
                   2869: 
                   2870:                *is_shared = sub_map->hdr.entries_pageable;
                   2871:                *object_name = VM_OBJECT_NAME(entry->object.vm_object);
                   2872:                *offset_in_object = entry->offset;
                   2873: 
                   2874:                vm_map_unlock_read(sub_map);
                   2875: 
                   2876:                vm_map_deallocate(sub_map);
                   2877: 
                   2878:                return(KERN_SUCCESS);
                   2879:        } else {
                   2880:                *is_shared = FALSE;
                   2881:                *object_name = VM_OBJECT_NAME(entry->object.vm_object);
                   2882:                *offset_in_object = tmp_offset;
                   2883:        }
                   2884: #undef VM_OBJECT_NAME
                   2885: 
                   2886:        vm_map_unlock_read(map);
                   2887: 
                   2888:        return(KERN_SUCCESS);
                   2889: }
                   2890: 
                   2891: #if    MACH_DEBUG
                   2892: #include <kern/host.h>
                   2893: 
                   2894: kern_return_t  host_vm_region(
                   2895:        host_t          host,
                   2896:        vm_offset_t     *address,               /* IN/OUT */
                   2897:        vm_size_t       *size,                  /* OUT */
                   2898:        vm_prot_t       *protection,            /* OUT */
                   2899:        vm_prot_t       *max_protection,        /* OUT */
                   2900:        vm_inherit_t    *inheritance,           /* OUT */
                   2901:        boolean_t       *is_pageable,           /* OUT */
                   2902:        port_t          *object_name,           /* OUT */
                   2903:        vm_offset_t     *offset_in_object       /* OUT */
                   2904: )
                   2905: {
                   2906:        if (host == HOST_NULL)
                   2907:                return(KERN_INVALID_ARGUMENT);
                   2908: 
                   2909:        return vm_region(kernel_map, address, size,
                   2910:                         protection, max_protection,
                   2911:                         inheritance, is_pageable,
                   2912:                         object_name, offset_in_object);
                   2913: }
                   2914: #endif /* MACH_DEBUG */
                   2915: 
                   2916: /*
                   2917:  *     vm_move:
                   2918:  *
                   2919:  *     Move memory from source to destination map, possibly deallocating
                   2920:  *     the source map reference to the memory.
                   2921:  *
                   2922:  *     Parameters are as follows:
                   2923:  *
                   2924:  *     src_map         Source address map
                   2925:  *     src_addr        Address within source map
                   2926:  *     dst_map         Destination address map
                   2927:  *     num_bytes       Amount of data (in bytes) to copy/move
                   2928:  *     src_dealloc     Should source be removed after copy?
                   2929:  *
                   2930:  *     Assumes the src and dst maps are not already locked.
                   2931:  *
                   2932:  *     If successful, returns destination address in dst_addr.
                   2933:  */
                   2934: kern_return_t vm_move(src_map,src_addr,dst_map,num_bytes,src_dealloc,dst_addr)
                   2935:        vm_map_t                src_map;
                   2936:        register vm_offset_t    src_addr;
                   2937:        register vm_map_t       dst_map;
                   2938:        vm_offset_t             num_bytes;
                   2939:        boolean_t               src_dealloc;
                   2940:        vm_offset_t             *dst_addr;
                   2941: {
                   2942:        register vm_offset_t    src_start;      /* Beginning of region */
                   2943:        register vm_size_t      src_size;       /* Size of rounded region */
                   2944:        vm_offset_t             dst_start;      /* destination address */
                   2945:        register kern_return_t  result;
                   2946: 
                   2947:        if (num_bytes == 0) {
                   2948:                *dst_addr = 0;
                   2949:                return KERN_SUCCESS;
                   2950:        }
                   2951: 
                   2952:        /*
                   2953:         *      Page-align the source region
                   2954:         */
                   2955: 
                   2956:        src_start = trunc_page(src_addr);
                   2957:        src_size = round_page(src_addr + num_bytes) - src_start;
                   2958: 
                   2959:        /*
                   2960:         *      Allocate a place to put the copy
                   2961:         */
                   2962: 
                   2963:        dst_start = (vm_offset_t) 0;
                   2964:        result = vm_allocate(dst_map, &dst_start, src_size, TRUE);
                   2965:        if (result == KERN_SUCCESS) {
                   2966:                /*
                   2967:                 *      Perform the copy, asking for deallocation if desired
                   2968:                 */
                   2969:                result = vm_map_copy(dst_map, src_map, dst_start, src_size,
                   2970:                                     src_start, FALSE, src_dealloc);
                   2971: 
                   2972:                /*
                   2973:                 *      Return the destination address corresponding to
                   2974:                 *      the source address given (rather than the front
                   2975:                 *      of the newly-allocated page).
                   2976:                 */
                   2977: 
                   2978:                if (result == KERN_SUCCESS)
                   2979:                        *dst_addr = dst_start + (src_addr - src_start);
                   2980:                else
                   2981:                        (void) vm_deallocate(dst_map, dst_start, src_size);
                   2982:        }
                   2983: 
                   2984:        return(result);
                   2985: }
                   2986: 
                   2987: pmap_t
                   2988: vm_map_pmap_EXTERNAL(
                   2989:        vm_map_t                map
                   2990: )
                   2991: {
                   2992:        return (vm_map_pmap(map));
                   2993: }

unix.superglobalmegacorp.com

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