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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* 
                     26:  * 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: 
                   1326:                    entry->wired_count++;
                   1327:                    if (entry->wired_count == 1) {
                   1328: 
                   1329:                        /*
                   1330:                         *      Perform actions of vm_map_lookup that need
                   1331:                         *      the write lock on the map: create a shadow
                   1332:                         *      object for a copy-on-write region, or an
                   1333:                         *      object for a zero-fill region.
                   1334:                         *
                   1335:                         *      We don't have to do this for entries that
                   1336:                         *      point to sharing maps, because we won't hold
                   1337:                         *      the lock on the sharing map.
                   1338:                         */
                   1339:                        if (!entry->is_a_map) {
                   1340:                            if (entry->needs_copy &&
                   1341:                                ((entry->protection & VM_PROT_WRITE) != 0)) {
                   1342: 
                   1343:                                vm_object_shadow(&entry->object.vm_object,
                   1344:                                                &entry->offset,
                   1345:                                                (vm_size_t)(entry->vme_end
                   1346:                                                        - entry->vme_start));
                   1347:                                entry->needs_copy = FALSE;
                   1348:                            }
                   1349:                            else if (entry->object.vm_object == VM_OBJECT_NULL) {
                   1350:                                entry->object.vm_object =
                   1351:                                    vm_object_allocate(
                   1352:                                        (vm_size_t)(entry->vme_end
                   1353:                                                        - entry->vme_start));
                   1354:                                entry->offset = (vm_offset_t)0;
                   1355:                            }
                   1356:                        }
                   1357:                    }
                   1358: 
                   1359:                    entry = entry->vme_next;
                   1360:                }
                   1361: 
                   1362:                /*
                   1363:                 *      Pass 2.
                   1364:                 */
                   1365: 
                   1366:                /* If we are wiring pages in the kernel map 
                   1367:                 * we know that the map will not be modified in a
                   1368:                 * destructive way. Drivers call us to wire in
                   1369:                 * pages after they do a vm_map_copy into the
                   1370:                 * kernel. Enhancing submaps to allow vm_map_copies
                   1371:                 * is a better long term solution. For now we will 
                   1372:                 * release the lock to prevent deadlock.
                   1373:                 */
                   1374:                if (map == kernel_map){
                   1375:                        map_locked = 0;
                   1376:                        vm_map_unlock(map);
                   1377:                } else {
                   1378:                        lock_set_recursive(&map->lock);
                   1379:                        lock_write_to_read(&map->lock);
                   1380:                }
                   1381: 
                   1382:                entry = temp_entry;
                   1383:                while ((entry != vm_map_to_entry(map)) &&
                   1384:                       (entry->vme_start < end)) {
                   1385:                    if (entry->wired_count == 1) {
                   1386:                        vm_fault_wire(map, entry);
                   1387:                    }
                   1388:                    entry = entry->vme_next;
                   1389:                }
                   1390: 
                   1391:                if (map_locked){
                   1392:                        lock_clear_recursive(&map->lock);
                   1393:                }
                   1394:        }
                   1395: 
                   1396:        if (map_locked){
                   1397:                vm_map_unlock(map);
                   1398:        }
                   1399: 
                   1400:        return(KERN_SUCCESS);
                   1401: }
                   1402: 
                   1403: /*
                   1404:  *     vm_map_entry_unwire:    [ internal use only ]
                   1405:  *
                   1406:  *     Make the region specified by this entry pageable.
                   1407:  *
                   1408:  *     The map in question should be locked.
                   1409:  *     [This is the reason for this routine's existence.]
                   1410:  */
                   1411: void vm_map_entry_unwire(map, entry)
                   1412:        vm_map_t                map;
                   1413:        register vm_map_entry_t entry;
                   1414: {
                   1415:        vm_fault_unwire(map, entry);
                   1416:        entry->wired_count = 0;
                   1417: }
                   1418: 
                   1419: /*
                   1420:  *     vm_map_entry_delete:    [ internal use only ]
                   1421:  *
                   1422:  *     Deallocate the given entry from the target map.
                   1423:  */            
                   1424: void vm_map_entry_delete(map, entry)
                   1425:        register vm_map_t       map;
                   1426:        register vm_map_entry_t entry;
                   1427: {
                   1428:        if (entry->wired_count != 0)
                   1429:                vm_map_entry_unwire(map, entry);
                   1430:                
                   1431:        vm_map_entry_unlink(map, entry);
                   1432:        map->size -= entry->vme_end - entry->vme_start;
                   1433: 
                   1434:        if (entry->is_a_map || entry->is_sub_map)
                   1435:                vm_map_deallocate(entry->object.share_map);
                   1436:        else
                   1437:                vm_object_deallocate(entry->object.vm_object);
                   1438: 
                   1439:        vm_map_entry_dispose(map, entry);
                   1440: }
                   1441: 
                   1442: /*
                   1443:  *     vm_map_delete:  [ internal use only ]
                   1444:  *
                   1445:  *     Deallocates the given address range from the target
                   1446:  *     map.
                   1447:  *
                   1448:  *     When called with a sharing map, removes pages from
                   1449:  *     that region from all physical maps.
                   1450:  */
                   1451: kern_return_t vm_map_delete(map, start, end)
                   1452:        register vm_map_t       map;
                   1453:        vm_offset_t             start;
                   1454:        register vm_offset_t    end;
                   1455: {
                   1456:        register vm_map_entry_t entry;
                   1457:        vm_map_entry_t          first_entry;
                   1458: 
                   1459:        /*
                   1460:         *      Find the start of the region, and clip it
                   1461:         */
                   1462: 
                   1463:        if (!vm_map_lookup_entry(map, start, &first_entry))
                   1464:                entry = first_entry->vme_next;
                   1465:        else {
                   1466:                entry = first_entry;
                   1467:                vm_map_clip_start(map, entry, start);
                   1468: 
                   1469:                /*
                   1470:                 *      Fix the lookup hint now, rather than each
                   1471:                 *      time though the loop.
                   1472:                 */
                   1473: 
                   1474:                SAVE_HINT(map, entry->vme_prev);
                   1475:        }
                   1476: 
                   1477:        /*
                   1478:         *      Save the free space hint
                   1479:         */
                   1480: 
                   1481:        if (map->first_free->vme_start >= start)
                   1482:                map->first_free = entry->vme_prev;
                   1483: 
                   1484:        /*
                   1485:         *      Step through all entries in this region
                   1486:         */
                   1487: 
                   1488:        while ((entry != vm_map_to_entry(map)) &&
                   1489:               (entry->vme_start < end)) {
                   1490:                vm_map_entry_t          next;
                   1491:                register vm_offset_t    s, e;
                   1492:                register vm_object_t    object;
                   1493:                extern vm_object_t      kernel_object;
                   1494: 
                   1495:                vm_map_clip_end(map, entry, end);
                   1496: 
                   1497:                next = entry->vme_next;
                   1498:                s = entry->vme_start;
                   1499:                e = entry->vme_end;
                   1500: 
                   1501:                /*
                   1502:                 *      Unwire before removing addresses from the pmap;
                   1503:                 *      otherwise, unwiring will put the entries back in
                   1504:                 *      the pmap.
                   1505:                 */
                   1506: 
                   1507:                object = entry->object.vm_object;
                   1508:                if (entry->wired_count != 0)
                   1509:                        vm_map_entry_unwire(map, entry);
                   1510: 
                   1511:                if (object == kernel_object)
                   1512:                        vm_object_page_remove(object, entry->offset,
                   1513:                                        entry->offset + (e - s));
                   1514:                
                   1515:                /*
                   1516:                 *      If this is a sharing map, we must remove
                   1517:                 *      *all* references to this data, since we can't
                   1518:                 *      find all of the physical maps which are sharing
                   1519:                 *      it.
                   1520:                 */
                   1521: 
                   1522:                if (!map->is_main_map)
                   1523:                        vm_object_pmap_remove(object,
                   1524:                                         entry->offset,
                   1525:                                         entry->offset + (e - s));
                   1526: 
                   1527:                pmap_remove(map->pmap, s, e);
                   1528: 
                   1529:                /*
                   1530:                 *      Delete the entry (which may delete the object)
                   1531:                 *      only after removing all pmap entries pointing
                   1532:                 *      to its pages.  (Otherwise, its page frames may
                   1533:                 *      be reallocated, and any modify bits will be
                   1534:                 *      set in the wrong object!)
                   1535:                 */
                   1536: 
                   1537:                vm_map_entry_delete(map, entry);
                   1538:                entry = next;
                   1539:        }
                   1540:        return(KERN_SUCCESS);
                   1541: }
                   1542: 
                   1543: /*
                   1544:  *     vm_map_remove:
                   1545:  *
                   1546:  *     Remove the given address range from the target map.
                   1547:  *     This is the exported form of vm_map_delete.
                   1548:  */
                   1549: kern_return_t vm_map_remove(map, start, end)
                   1550:        register vm_map_t       map;
                   1551:        register vm_offset_t    start;
                   1552:        register vm_offset_t    end;
                   1553: {
                   1554:        register kern_return_t  result;
                   1555: 
                   1556:        vm_map_lock(map);
                   1557:        VM_MAP_RANGE_CHECK(map, start, end);
                   1558:        result = vm_map_delete(map, start, end);
                   1559:        vm_map_unlock(map);
                   1560: 
                   1561:        return(result);
                   1562: }
                   1563: 
                   1564: kern_return_t vm_map_reallocate(map, start, end)
                   1565:        register vm_map_t       map;
                   1566:        register vm_offset_t    start;
                   1567:        register vm_offset_t    end;
                   1568: {
                   1569:        register vm_map_entry_t entry;
                   1570:        vm_map_entry_t          first_entry;
                   1571: 
                   1572:        vm_map_lock(map);
                   1573:        VM_MAP_RANGE_CHECK(map, start, end);
                   1574: 
                   1575:        /*
                   1576:         *      Find the start of the region, and clip it
                   1577:         */
                   1578: 
                   1579:        if (!vm_map_lookup_entry(map, start, &first_entry))
                   1580:                entry = first_entry->vme_next;
                   1581:        else {
                   1582:                entry = first_entry;
                   1583:                vm_map_clip_start(map, entry, start);
                   1584: 
                   1585:                /*
                   1586:                 *      Fix the lookup hint now, rather than each
                   1587:                 *      time though the loop.
                   1588:                 */
                   1589: 
                   1590:                SAVE_HINT(map, entry->vme_prev);
                   1591:        }
                   1592: 
                   1593:        /*
                   1594:         *      Step through all entries in this region
                   1595:         */
                   1596: 
                   1597:        while ((entry != vm_map_to_entry(map)) &&
                   1598:               (entry->vme_start < end)) {
                   1599:                vm_map_entry_t          next;
                   1600:                register vm_offset_t    s, e;
                   1601:                register vm_object_t    object;
                   1602:                extern vm_object_t      kernel_object;
                   1603: 
                   1604:                vm_map_clip_end(map, entry, end);
                   1605: 
                   1606:                next = entry->vme_next;
                   1607:                s = entry->vme_start;
                   1608:                e = entry->vme_end;
                   1609: 
                   1610:                /*
                   1611:                 *      Unwire before removing addresses from the pmap;
                   1612:                 *      otherwise, unwiring will put the entries back in
                   1613:                 *      the pmap.
                   1614:                 */
                   1615: 
                   1616:                object = entry->object.vm_object;
                   1617:                if (entry->wired_count != 0)
                   1618:                        vm_map_entry_unwire(map, entry);
                   1619: 
                   1620:                if (object == kernel_object)
                   1621:                        vm_object_page_remove(object, entry->offset,
                   1622:                                        entry->offset + (e - s));
                   1623:                
                   1624:                /*
                   1625:                 *      If this is a sharing map, we must remove
                   1626:                 *      *all* references to this data, since we can't
                   1627:                 *      find all of the physical maps which are sharing
                   1628:                 *      it.
                   1629:                 */
                   1630: 
                   1631:                if (!map->is_main_map)
                   1632:                        vm_object_pmap_remove(object,
                   1633:                                         entry->offset,
                   1634:                                         entry->offset + (e - s));
                   1635: 
                   1636:                pmap_remove(map->pmap, s, e);
                   1637: 
                   1638:                /*
                   1639:                 *      Release the reference to the underlying object
                   1640:                 *      only after removing all pmap entries pointing
                   1641:                 *      to its pages.  (Otherwise, its page frames may
                   1642:                 *      be reallocated, and any modify bits will be
                   1643:                 *      set in the wrong object!)
                   1644:                 */
                   1645: 
                   1646:                if (entry->is_a_map || entry->is_sub_map)
                   1647:                        vm_map_deallocate(entry->object.share_map);
                   1648:                else
                   1649:                        vm_object_deallocate(entry->object.vm_object);
                   1650: 
                   1651:                entry->is_a_map = FALSE;
                   1652:                entry->is_sub_map = FALSE;
                   1653:                entry->object.vm_object = VM_OBJECT_NULL;
                   1654:                entry->offset = 0;
                   1655: 
                   1656:                entry->copy_on_write = FALSE;
                   1657:                entry->needs_copy = FALSE;
                   1658: 
                   1659:                if (map->is_main_map) {
                   1660:                        entry->protection =
                   1661:                                (entry->max_protection & VM_PROT_DEFAULT);
                   1662:                        entry->wired_count = 0;
                   1663:                }
                   1664: 
                   1665:                entry = next;
                   1666:        }
                   1667: 
                   1668:        vm_map_unlock(map);
                   1669: 
                   1670:        return(KERN_SUCCESS);
                   1671: }
                   1672: 
                   1673: /*
                   1674:  *     vm_map_check_protection:
                   1675:  *
                   1676:  *     Assert that the target map allows the specified
                   1677:  *     privilege on the entire address region given.
                   1678:  *     The entire region must be allocated.
                   1679:  */
                   1680: boolean_t vm_map_check_protection(map, start, end, protection)
                   1681:        register vm_map_t       map;
                   1682:        register vm_offset_t    start;
                   1683:        register vm_offset_t    end;
                   1684:        register vm_prot_t      protection;
                   1685: {
                   1686:        register vm_map_entry_t entry;
                   1687:        vm_map_entry_t          tmp_entry;
                   1688: 
                   1689:        if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   1690:                return(FALSE);
                   1691:        }
                   1692: 
                   1693:        entry = tmp_entry;
                   1694: 
                   1695:        while (start < end) {
                   1696:                if (entry == vm_map_to_entry(map)) {
                   1697:                        return(FALSE);
                   1698:                }
                   1699: 
                   1700:                /*
                   1701:                 *      No holes allowed!
                   1702:                 */
                   1703: 
                   1704:                if (start < entry->vme_start) {
                   1705:                        return(FALSE);
                   1706:                }
                   1707: 
                   1708:                /*
                   1709:                 * Check protection associated with entry.
                   1710:                 */
                   1711: 
                   1712:                if ((entry->protection & protection) != protection) {
                   1713:                        return(FALSE);
                   1714:                }
                   1715: 
                   1716:                /* go to next entry */
                   1717: 
                   1718:                start = entry->vme_end;
                   1719:                entry = entry->vme_next;
                   1720:        }
                   1721:        return(TRUE);
                   1722: }
                   1723: 
                   1724: /*
                   1725:  *     vm_map_copy_entry:
                   1726:  *
                   1727:  *     Copies the contents of the source entry to the destination
                   1728:  *     entry.  The entries *must* be aligned properly.
                   1729:  */
                   1730: void vm_map_copy_entry(src_map, dst_map, src_entry, dst_entry)
                   1731:        vm_map_t                src_map, dst_map;
                   1732:        register vm_map_entry_t src_entry, dst_entry;
                   1733: {
                   1734:        vm_object_t     temp_object;
                   1735: 
                   1736:        if (src_entry->is_sub_map || dst_entry->is_sub_map)
                   1737:                return;
                   1738: 
                   1739:        /*
                   1740:         *      If our destination map was wired down,
                   1741:         *      unwire it now.
                   1742:         */
                   1743: 
                   1744:        if (dst_entry->wired_count != 0)
                   1745:                vm_map_entry_unwire(dst_map, dst_entry);
                   1746: 
                   1747:        /*
                   1748:         *      If we're dealing with a sharing map, we
                   1749:         *      must remove the destination pages from
                   1750:         *      all maps (since we cannot know which maps
                   1751:         *      this sharing map belongs in).
                   1752:         */
                   1753: 
                   1754:        if (!dst_map->is_main_map)
                   1755:                vm_object_pmap_remove(dst_entry->object.vm_object,
                   1756:                        dst_entry->offset,
                   1757:                        dst_entry->offset +
                   1758:                                (dst_entry->vme_end - dst_entry->vme_start));
                   1759: 
                   1760:        pmap_remove(dst_map->pmap, dst_entry->vme_start, dst_entry->vme_end);
                   1761: 
                   1762:        if (src_entry->wired_count == 0) {
                   1763: 
                   1764:                boolean_t       src_needs_copy;
                   1765: 
                   1766:                /*
                   1767:                 *      If the source entry is marked needs_copy,
                   1768:                 *      it is already write-protected.
                   1769:                 */
                   1770:                if (!src_entry->needs_copy) {
                   1771: 
                   1772:                        boolean_t       su;
                   1773: 
                   1774:                        /*
                   1775:                         *      If the source entry has only one mapping,
                   1776:                         *      we can just protect the virtual address
                   1777:                         *      range.
                   1778:                         */
                   1779:                        if (!(su = src_map->is_main_map)) {
                   1780:                                simple_lock(&src_map->ref_lock);
                   1781:                                su = (src_map->ref_count == 1);
                   1782:                                simple_unlock(&src_map->ref_lock);
                   1783:                        }
                   1784: 
                   1785:                        if (su) {
                   1786:                                pmap_protect(src_map->pmap,
                   1787:                                        src_entry->vme_start,
                   1788:                                        src_entry->vme_end,
                   1789:                                        src_entry->protection & ~VM_PROT_WRITE);
                   1790:                        }
                   1791:                        else {
                   1792:                                vm_object_pmap_copy(src_entry->object.vm_object,
                   1793:                                        src_entry->offset,
                   1794:                                        src_entry->offset + (src_entry->vme_end
                   1795:                                                            -src_entry->vme_start));
                   1796:                        }
                   1797:                }
                   1798: 
                   1799:                /*
                   1800:                 *      Make a copy of the object.
                   1801:                 */
                   1802:                temp_object = dst_entry->object.vm_object;
                   1803:                vm_object_copy(src_entry->object.vm_object,
                   1804:                                src_entry->offset,
                   1805:                                (vm_size_t)(src_entry->vme_end -
                   1806:                                            src_entry->vme_start),
                   1807:                                &dst_entry->object.vm_object,
                   1808:                                &dst_entry->offset,
                   1809:                                &src_needs_copy);
                   1810:                /*
                   1811:                 *      If we didn't get a copy-object now, mark the
                   1812:                 *      source map entry so that a shadow will be created
                   1813:                 *      to hold its changed pages.
                   1814:                 */
                   1815:                if (src_needs_copy)
                   1816:                        src_entry->needs_copy = TRUE;
                   1817: 
                   1818:                /*
                   1819:                 *      The destination always needs to have a shadow
                   1820:                 *      created.
                   1821:                 */
                   1822:                dst_entry->needs_copy = TRUE;
                   1823: 
                   1824:                /*
                   1825:                 *      Mark the entries copy-on-write, so that write-enabling
                   1826:                 *      the entry won't make copy-on-write pages writable.
                   1827:                 */
                   1828:                src_entry->copy_on_write = TRUE;
                   1829:                dst_entry->copy_on_write = TRUE;
                   1830: /* XXX */
                   1831:                if (src_entry->protection & VM_PROT_EXECUTE)
                   1832:                        dst_entry->protection |= (VM_PROT_EXECUTE & dst_entry->max_protection);
                   1833: /* XXX */
                   1834:                /*
                   1835:                 *      Get rid of the old object.
                   1836:                 */
                   1837:                vm_object_deallocate(temp_object);
                   1838: 
                   1839:                pmap_copy(dst_map->pmap, src_map->pmap, dst_entry->vme_start,
                   1840:                        dst_entry->vme_end - dst_entry->vme_start, src_entry->vme_start);
                   1841:        }
                   1842:        else {
                   1843:                /*
                   1844:                 *      Of course, wired down pages can't be set copy-on-write.
                   1845:                 *      Cause wired pages to be copied into the new
                   1846:                 *      map by simulating faults (the new pages are
                   1847:                 *      pageable)
                   1848:                 */
                   1849:                vm_fault_copy_entry(dst_map, src_map, dst_entry, src_entry);
                   1850:        }
                   1851: }
                   1852: 
                   1853: /*
                   1854:  *     vm_map_copy:
                   1855:  *
                   1856:  *     Perform a virtual memory copy from the source
                   1857:  *     address map/range to the destination map/range.
                   1858:  *
                   1859:  *     If src_destroy or dst_alloc is requested,
                   1860:  *     the source and destination regions should be
                   1861:  *     disjoint, not only in the top-level map, but
                   1862:  *     in the sharing maps as well.  [The best way
                   1863:  *     to guarantee this is to use a new intermediate
                   1864:  *     map to make copies.  This also reduces map
                   1865:  *     fragmentation.]
                   1866:  */
                   1867: kern_return_t vm_map_copy(dst_map, src_map,
                   1868:                          dst_addr, len, src_addr,
                   1869:                          dst_alloc, src_destroy)
                   1870:        vm_map_t        dst_map;
                   1871:        vm_map_t        src_map;
                   1872:        vm_offset_t     dst_addr;
                   1873:        vm_size_t       len;
                   1874:        vm_offset_t     src_addr;
                   1875:        boolean_t       dst_alloc;
                   1876:        boolean_t       src_destroy;
                   1877: {
                   1878:        register
                   1879:        vm_map_entry_t  src_entry;
                   1880:        register
                   1881:        vm_map_entry_t  dst_entry;
                   1882:        vm_map_entry_t  tmp_entry;
                   1883:        vm_offset_t     src_start;
                   1884:        vm_offset_t     src_end;
                   1885:        vm_offset_t     dst_start;
                   1886:        vm_offset_t     dst_end;
                   1887:        vm_offset_t     src_clip;
                   1888:        vm_offset_t     dst_clip;
                   1889:        kern_return_t   result;
                   1890:        boolean_t       old_src_destroy;
                   1891: 
                   1892:        /*
                   1893:         *      XXX While we figure out why src_destroy screws up,
                   1894:         *      we'll do it by explicitly vm_map_delete'ing at the end.
                   1895:         */
                   1896: 
                   1897:        old_src_destroy = src_destroy;
                   1898:        src_destroy = FALSE;
                   1899: 
                   1900:        /*
                   1901:         *      Compute start and end of region in both maps
                   1902:         */
                   1903: 
                   1904:        src_start = src_addr;
                   1905:        src_end = src_start + len;
                   1906:        dst_start = dst_addr;
                   1907:        dst_end = dst_start + len;
                   1908: 
                   1909:        /*
                   1910:         *      Check that the region can exist in both source
                   1911:         *      and destination.
                   1912:         */
                   1913: 
                   1914:        if ((dst_end < dst_start) || (src_end < src_start))
                   1915:                return(KERN_NO_SPACE);
                   1916: 
                   1917:        /*
                   1918:         *      Lock the maps in question -- we avoid deadlock
                   1919:         *      by ordering lock acquisition by map value
                   1920:         */
                   1921: 
                   1922:        if (src_map == dst_map) {
                   1923:                vm_map_lock(src_map);
                   1924:        }
                   1925:        else if ((int) src_map < (int) dst_map) {
                   1926:                vm_map_lock(src_map);
                   1927:                vm_map_lock(dst_map);
                   1928:        } else {
                   1929:                vm_map_lock(dst_map);
                   1930:                vm_map_lock(src_map);
                   1931:        }
                   1932: 
                   1933:        result = KERN_SUCCESS;
                   1934: 
                   1935:        /*
                   1936:         *      Check protections... source must be completely readable and
                   1937:         *      destination must be completely writable.  [Note that if we're
                   1938:         *      allocating the destination region, we don't have to worry
                   1939:         *      about protection, but instead about whether the region
                   1940:         *      exists.]
                   1941:         */
                   1942: 
                   1943:        if (src_map->is_main_map && dst_map->is_main_map) {
                   1944:                if (!vm_map_check_protection(src_map, src_start, src_end,
                   1945:                                        VM_PROT_READ)) {
                   1946:                        result = KERN_PROTECTION_FAILURE;
                   1947:                        goto Return;
                   1948:                }
                   1949: 
                   1950:                if (dst_alloc) {
                   1951:                        /* XXX Consider making this a vm_map_find instead */
                   1952:                        if ((result = vm_map_insert(dst_map, VM_OBJECT_NULL,
                   1953:                                        (vm_offset_t) 0, dst_start, dst_end)) != KERN_SUCCESS)
                   1954:                                goto Return;
                   1955:                }
                   1956:                else if (!vm_map_check_protection(dst_map, dst_start, dst_end,
                   1957:                                        VM_PROT_WRITE)) {
                   1958:                        result = KERN_PROTECTION_FAILURE;
                   1959:                        goto Return;
                   1960:                }
                   1961:        }
                   1962: 
                   1963:        /*
                   1964:         *      Find the start entries and clip.
                   1965:         *
                   1966:         *      Note that checking protection asserts that the
                   1967:         *      lookup cannot fail.
                   1968:         *
                   1969:         *      Also note that we wait to do the second lookup
                   1970:         *      until we have done the first clip, as the clip
                   1971:         *      may affect which entry we get!
                   1972:         */
                   1973: 
                   1974:        (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
                   1975:        src_entry = tmp_entry;
                   1976:        vm_map_clip_start(src_map, src_entry, src_start);
                   1977: 
                   1978:        (void) vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry);
                   1979:        dst_entry = tmp_entry;
                   1980:        vm_map_clip_start(dst_map, dst_entry, dst_start);
                   1981: 
                   1982:        /*
                   1983:         *      If both source and destination entries are the same,
                   1984:         *      retry the first lookup, as it may have changed.
                   1985:         */
                   1986: 
                   1987:        if (src_entry == dst_entry) {
                   1988:                (void) vm_map_lookup_entry(src_map, src_addr, &tmp_entry);
                   1989:                src_entry = tmp_entry;
                   1990:        }
                   1991: 
                   1992:        /*
                   1993:         *      If source and destination entries are still the same,
                   1994:         *      a null copy is being performed.
                   1995:         */
                   1996: 
                   1997:        if (src_entry == dst_entry)
                   1998:                goto Return;
                   1999: 
                   2000:        /*
                   2001:         *      Go through entries until we get to the end of the
                   2002:         *      region.
                   2003:         */
                   2004: 
                   2005:        while (src_start < src_end) {
                   2006:                /*
                   2007:                 *      Clip the entries to the endpoint of the entire region.
                   2008:                 */
                   2009: 
                   2010:                vm_map_clip_end(src_map, src_entry, src_end);
                   2011:                vm_map_clip_end(dst_map, dst_entry, dst_end);
                   2012: 
                   2013:                /*
                   2014:                 *      Clip each entry to the endpoint of the other entry.
                   2015:                 */
                   2016: 
                   2017:                src_clip = src_entry->vme_start + (dst_entry->vme_end - dst_entry->vme_start);
                   2018:                vm_map_clip_end(src_map, src_entry, src_clip);
                   2019: 
                   2020:                dst_clip = dst_entry->vme_start + (src_entry->vme_end - src_entry->vme_start);
                   2021:                vm_map_clip_end(dst_map, dst_entry, dst_clip);
                   2022: 
                   2023:                /*
                   2024:                 *      Both entries now match in size and relative endpoints.
                   2025:                 *
                   2026:                 *      If both entries refer to a VM object, we can
                   2027:                 *      deal with them now.
                   2028:                 */
                   2029: 
                   2030:                if (!src_entry->is_a_map && !dst_entry->is_a_map) {
                   2031:                        vm_map_copy_entry(src_map, dst_map, src_entry,
                   2032:                                                dst_entry);
                   2033:                }
                   2034:                else {
                   2035:                        register vm_map_t       new_dst_map;
                   2036:                        vm_offset_t             new_dst_start;
                   2037:                        vm_size_t               new_size;
                   2038:                        vm_map_t                new_src_map;
                   2039:                        vm_offset_t             new_src_start;
                   2040: 
                   2041:                        /*
                   2042:                         *      We have to follow at least one sharing map.
                   2043:                         */
                   2044: 
                   2045:                        new_size = (dst_entry->vme_end - dst_entry->vme_start);
                   2046: 
                   2047:                        if (src_entry->is_a_map) {
                   2048:                                new_src_map = src_entry->object.share_map;
                   2049:                                new_src_start = src_entry->offset;
                   2050:                        }
                   2051:                        else {
                   2052:                                new_src_map = src_map;
                   2053:                                new_src_start = src_entry->vme_start;
                   2054:                                lock_set_recursive(&src_map->lock);
                   2055:                        }
                   2056: 
                   2057:                        if (dst_entry->is_a_map) {
                   2058:                                vm_offset_t     new_dst_end;
                   2059: 
                   2060:                                new_dst_map = dst_entry->object.share_map;
                   2061:                                new_dst_start = dst_entry->offset;
                   2062: 
                   2063:                                /*
                   2064:                                 *      Since the destination sharing entries
                   2065:                                 *      will be merely deallocated, we can
                   2066:                                 *      do that now, and replace the region
                   2067:                                 *      with a null object.  [This prevents
                   2068:                                 *      splitting the source map to match
                   2069:                                 *      the form of the destination map.]
                   2070:                                 *      Note that we can only do so if the
                   2071:                                 *      source and destination do not overlap.
                   2072:                                 */
                   2073: 
                   2074:                                new_dst_end = new_dst_start + new_size;
                   2075: 
                   2076:                                if (new_dst_map != new_src_map) {
                   2077:                                        vm_map_lock(new_dst_map);
                   2078:                                        (void) vm_map_delete(new_dst_map,
                   2079:                                                        new_dst_start,
                   2080:                                                        new_dst_end);
                   2081:                                        (void) vm_map_insert(new_dst_map,
                   2082:                                                        VM_OBJECT_NULL,
                   2083:                                                        (vm_offset_t) 0,
                   2084:                                                        new_dst_start,
                   2085:                                                        new_dst_end);
                   2086:                                        vm_map_unlock(new_dst_map);
                   2087:                                }
                   2088:                        }
                   2089:                        else {
                   2090:                                new_dst_map = dst_map;
                   2091:                                new_dst_start = dst_entry->vme_start;
                   2092:                                lock_set_recursive(&dst_map->lock);
                   2093:                        }
                   2094: 
                   2095:                        /*
                   2096:                         *      Recursively copy the sharing map.
                   2097:                         */
                   2098: 
                   2099:                        (void) vm_map_copy(new_dst_map, new_src_map,
                   2100:                                new_dst_start, new_size, new_src_start,
                   2101:                                FALSE, FALSE);
                   2102: 
                   2103:                        if (dst_map == new_dst_map)
                   2104:                                lock_clear_recursive(&dst_map->lock);
                   2105:                        if (src_map == new_src_map)
                   2106:                                lock_clear_recursive(&src_map->lock);
                   2107:                }
                   2108: 
                   2109:                /*
                   2110:                 *      Update variables for next pass through the loop.
                   2111:                 */
                   2112: 
                   2113:                src_start = src_entry->vme_end;
                   2114:                src_entry = src_entry->vme_next;
                   2115:                dst_start = dst_entry->vme_end;
                   2116:                dst_entry = dst_entry->vme_next;
                   2117: 
                   2118:                /*
                   2119:                 *      If the source is to be destroyed, here is the
                   2120:                 *      place to do it.
                   2121:                 */
                   2122: 
                   2123:                if (src_destroy && src_map->is_main_map &&
                   2124:                                                dst_map->is_main_map)
                   2125:                        vm_map_entry_delete(src_map, src_entry->vme_prev);
                   2126:        }
                   2127: 
                   2128:        /*
                   2129:         *      Update the physical maps as appropriate
                   2130:         */
                   2131: 
                   2132:        if (src_map->is_main_map && dst_map->is_main_map) {
                   2133:                if (src_destroy)
                   2134:                        pmap_remove(src_map->pmap, src_addr, src_addr + len);
                   2135:        }
                   2136: 
                   2137:        /*
                   2138:         *      Unlock the maps
                   2139:         */
                   2140: 
                   2141:        Return: ;
                   2142: 
                   2143:        if (old_src_destroy)
                   2144:                vm_map_delete(src_map, src_addr, src_addr + len);
                   2145: 
                   2146:        vm_map_unlock(src_map);
                   2147:        if (src_map != dst_map)
                   2148:                vm_map_unlock(dst_map);
                   2149: 
                   2150:        return(result);
                   2151: }
                   2152: 
                   2153: /*
                   2154:  *     vm_map_fork:
                   2155:  *
                   2156:  *     Create and return a new map based on the old
                   2157:  *     map, according to the inheritance values on the
                   2158:  *     regions in that map.
                   2159:  *
                   2160:  *     The source map must not be locked.
                   2161:  */
                   2162: vm_map_t vm_map_fork(old_map)
                   2163:        vm_map_t        old_map;
                   2164: {
                   2165:        vm_map_t        new_map;
                   2166:        vm_map_entry_t  old_entry;
                   2167:        vm_map_entry_t  new_entry;
                   2168:        pmap_t          new_pmap;
                   2169: 
                   2170:        vm_map_lock(old_map);
                   2171: 
                   2172:        new_pmap = pmap_create((vm_size_t) 0);
                   2173:        new_map = vm_map_create(new_pmap,
                   2174:                        old_map->min_offset,
                   2175:                        old_map->max_offset,
                   2176:                        old_map->hdr.entries_pageable);
                   2177: 
                   2178:        old_entry = vm_map_first_entry(old_map);
                   2179: 
                   2180:        while (old_entry != vm_map_to_entry(old_map)) {
                   2181:                if (old_entry->is_sub_map)
                   2182:                        panic("vm_map_fork: encountered a submap");
                   2183: 
                   2184:                switch (old_entry->inheritance) {
                   2185:                case VM_INHERIT_NONE:
                   2186:                        break;
                   2187: 
                   2188:                case VM_INHERIT_SHARE:
                   2189:                        /*
                   2190:                         *      If we don't already have a sharing map:
                   2191:                         */
                   2192: 
                   2193:                        if (!old_entry->is_a_map) {
                   2194:                                vm_map_t        new_share_map;
                   2195:                                vm_map_entry_t  new_share_entry;
                   2196:                                
                   2197:                                /*
                   2198:                                 *      Create a new sharing map
                   2199:                                 */
                   2200:                                 
                   2201:                                new_share_map = vm_map_create(PMAP_NULL,
                   2202:                                                        old_entry->vme_start,
                   2203:                                                        old_entry->vme_end,
                   2204:                                                        TRUE);
                   2205:                                new_share_map->is_main_map = FALSE;
                   2206: 
                   2207:                                /*
                   2208:                                 *      Create the only sharing entry from the
                   2209:                                 *      old task map entry.
                   2210:                                 */
                   2211: 
                   2212:                                new_share_entry =
                   2213:                                        vm_map_entry_create(new_share_map);
                   2214:                                *new_share_entry = *old_entry;
                   2215: 
                   2216:                                /*
                   2217:                                 *      Insert the entry into the new sharing
                   2218:                                 *      map
                   2219:                                 */
                   2220: 
                   2221:                                vm_map_entry_link(new_share_map,
                   2222:                                        vm_map_last_entry(new_share_map),
                   2223:                                                new_share_entry);
                   2224: 
                   2225:                                /*
                   2226:                                 *      Fix up the task map entry to refer
                   2227:                                 *      to the sharing map now.
                   2228:                                 */
                   2229: 
                   2230:                                old_entry->is_a_map = TRUE;
                   2231:                                old_entry->object.share_map = new_share_map;
                   2232:                                old_entry->offset = old_entry->vme_start;
                   2233:                        }
                   2234: 
                   2235:                        /*
                   2236:                         *      Clone the entry, referencing the sharing map.
                   2237:                         */
                   2238: 
                   2239:                        new_entry = vm_map_entry_create(new_map);
                   2240:                        *new_entry = *old_entry;
                   2241:                        vm_map_reference(new_entry->object.share_map);
                   2242: 
                   2243:                        /*
                   2244:                         *      Insert the entry into the new map -- we
                   2245:                         *      know we're inserting at the end of the new
                   2246:                         *      map.
                   2247:                         */
                   2248: 
                   2249:                        vm_map_entry_link(new_map,
                   2250:                                vm_map_last_entry(new_map),
                   2251:                                                new_entry);
                   2252: 
                   2253:                        /*
                   2254:                         *      Update the physical map
                   2255:                         */
                   2256: 
                   2257:                        pmap_copy(new_map->pmap, old_map->pmap,
                   2258:                                new_entry->vme_start,
                   2259:                                (old_entry->vme_end - old_entry->vme_start),
                   2260:                                old_entry->vme_start);
                   2261:                        break;
                   2262: 
                   2263:                case VM_INHERIT_COPY:
                   2264:                        /*
                   2265:                         *      Clone the entry and link into the map.
                   2266:                         */
                   2267: 
                   2268:                        new_entry = vm_map_entry_create(new_map);
                   2269:                        *new_entry = *old_entry;
                   2270:                        new_entry->wired_count = 0;
                   2271:                        new_entry->object.vm_object = VM_OBJECT_NULL;
                   2272:                        new_entry->is_a_map = FALSE;
                   2273:                        vm_map_entry_link(new_map,
                   2274:                                vm_map_last_entry(new_map),
                   2275:                                                        new_entry);
                   2276:                        if (old_entry->is_a_map) {
                   2277:                                kern_return_t   check;
                   2278: 
                   2279:                                check = vm_map_copy(new_map,
                   2280:                                                old_entry->object.share_map,
                   2281:                                                new_entry->vme_start,
                   2282:                                                (vm_size_t)
                   2283:                                                        (new_entry->vme_end -
                   2284:                                                        new_entry->vme_start),
                   2285:                                                old_entry->offset,
                   2286:                                                FALSE, FALSE);
                   2287:                                if (check != KERN_SUCCESS)
                   2288:                                        kprintf("vm_map_fork: copy in share_map region failed\n");
                   2289:                        }
                   2290:                        else {
                   2291:                                vm_map_copy_entry(old_map, new_map, old_entry,
                   2292:                                                new_entry);
                   2293:                        }
                   2294:                        break;
                   2295:                }
                   2296:                old_entry = old_entry->vme_next;
                   2297:        }
                   2298: 
                   2299:        new_map->size = old_map->size;
                   2300:        vm_map_unlock(old_map);
                   2301: 
                   2302:        return(new_map);
                   2303: }
                   2304: 
                   2305: /*
                   2306:  *     vm_map_lookup:
                   2307:  *
                   2308:  *     Finds the VM object, offset, and
                   2309:  *     protection for a given virtual address in the
                   2310:  *     specified map, assuming a page fault of the
                   2311:  *     type specified.
                   2312:  *
                   2313: #if    USE_VERSIONS
                   2314:  *     Returns the (object, offset, protection) for
                   2315:  *     this address, whether it is wired down, and whether
                   2316:  *     this map has the only reference to the data in question.
                   2317:  *     In order to later verify this lookup, a "version"
                   2318:  *     is returned.
                   2319:  *
                   2320:  *     The map should not be locked; it will not be
                   2321:  *     locked on exit.  In order to guarantee the
                   2322:  *     existence of the returned object, it is returned
                   2323:  *     locked.
                   2324: #else  USE_VERSIONS
                   2325:  *     Leaves the map in question locked for read; return
                   2326:  *     values are guaranteed until a vm_map_lookup_done
                   2327:  *     call is performed.  Note that the map argument
                   2328:  *     is in/out; the returned map must be used in
                   2329:  *     the call to vm_map_lookup_done.
                   2330:  *
                   2331:  *     A handle (out_entry) is returned for use in
                   2332:  *     vm_map_lookup_done, to make that fast.
                   2333: #endif USE_VERSIONS
                   2334:  *
                   2335:  *     If a lookup is requested with "write protection"
                   2336:  *     specified, the map may be changed to perform virtual
                   2337:  *     copying operations, although the data referenced will
                   2338:  *     remain the same.
                   2339:  */
                   2340: #if    USE_VERSIONS
                   2341: kern_return_t vm_map_lookup(var_map, vaddr, fault_type, out_version,
                   2342:                                object, offset, out_prot, wired, single_use)
                   2343: #else  USE_VERSIONS
                   2344: kern_return_t vm_map_lookup(var_map, vaddr, fault_type, out_entry,
                   2345:                                object, offset, out_prot, wired, single_use)
                   2346: #endif USE_VERSIONS
                   2347:        vm_map_t                *var_map;       /* IN/OUT */
                   2348:        register vm_offset_t    vaddr;
                   2349:        register vm_prot_t      fault_type;
                   2350: 
                   2351: #if    USE_VERSIONS
                   2352:        vm_map_version_t        *out_version;   /* OUT */
                   2353: #else  USE_VERSIONS
                   2354:        vm_map_entry_t          *out_entry;     /* OUT */
                   2355: #endif USE_VERSIONS
                   2356:        vm_object_t             *object;        /* OUT */
                   2357:        vm_offset_t             *offset;        /* OUT */
                   2358:        vm_prot_t               *out_prot;      /* OUT */
                   2359:        boolean_t               *wired;         /* OUT */
                   2360:        boolean_t               *single_use;    /* OUT */
                   2361: {
                   2362:        vm_map_t                        share_map;
                   2363:        vm_offset_t                     share_offset;
                   2364:        register vm_map_entry_t         entry;
                   2365:        register vm_map_t               map = *var_map;
                   2366:        register vm_prot_t              prot;
                   2367:        register boolean_t              su;
                   2368: 
                   2369:        RetryLookup: ;
                   2370: 
                   2371:        /*
                   2372:         *      Lookup the faulting address.
                   2373:         */
                   2374: 
                   2375:        vm_map_lock_read(map);
                   2376: 
                   2377: #define        L_RETURN(why) \
                   2378:                { \
                   2379:                vm_map_unlock_read(map); \
                   2380:                return(why); \
                   2381:                }
                   2382: 
                   2383:        /*
                   2384:         *      If the map has an interesting hint, try it before calling
                   2385:         *      full blown lookup routine.
                   2386:         */
                   2387: 
                   2388:        simple_lock(&map->hint_lock);
                   2389:        entry = map->hint;
                   2390:        simple_unlock(&map->hint_lock);
                   2391: 
                   2392: #if    !USE_VERSIONS
                   2393:        *out_entry = entry;
                   2394: #endif !USE_VERSIONS
                   2395: 
                   2396:        if ((entry == vm_map_to_entry(map)) ||
                   2397:            (vaddr < entry->vme_start) || (vaddr >= entry->vme_end)) {
                   2398:                vm_map_entry_t  tmp_entry;
                   2399: 
                   2400:                /*
                   2401:                 *      Entry was either not a valid hint, or the vaddr
                   2402:                 *      was not contained in the entry, so do a full lookup.
                   2403:                 */
                   2404:                if (!vm_map_lookup_entry(map, vaddr, &tmp_entry))
                   2405:                        L_RETURN(KERN_INVALID_ADDRESS);
                   2406: 
                   2407:                entry = tmp_entry;
                   2408: #if    !USE_VERSIONS
                   2409:                *out_entry = entry;
                   2410: #endif !USE_VERSIONS
                   2411:        }
                   2412: 
                   2413:        /*
                   2414:         *      Handle submaps.
                   2415:         */
                   2416: 
                   2417:        if (entry->is_sub_map) {
                   2418:                vm_map_t        old_map = map;
                   2419: 
                   2420:                *var_map = map = entry->object.sub_map;
                   2421:                vm_map_unlock_read(old_map);
                   2422:                goto RetryLookup;
                   2423:        }
                   2424:                
                   2425:        /*
                   2426:         *      Check whether this task is allowed to have
                   2427:         *      this page.
                   2428:         */
                   2429: 
                   2430:        prot = entry->protection;
                   2431:        if ((fault_type & (prot)) != fault_type)
                   2432:                L_RETURN(KERN_PROTECTION_FAILURE);
                   2433: 
                   2434:        /*
                   2435:         *      If this page is not pageable, we have to get
                   2436:         *      it for all possible accesses.
                   2437:         */
                   2438: 
                   2439:        if (*wired = (entry->wired_count != 0))
                   2440:                prot = fault_type = entry->protection;
                   2441: 
                   2442:        /*
                   2443:         *      If we don't already have a VM object, track
                   2444:         *      it down.
                   2445:         */
                   2446: 
                   2447:        if (su = !entry->is_a_map) {
                   2448:                share_map = map;
                   2449:                share_offset = vaddr;
                   2450:        }
                   2451:        else {
                   2452:                vm_map_entry_t  share_entry;
                   2453: 
                   2454:                /*
                   2455:                 *      Compute the sharing map, and offset into it.
                   2456:                 */
                   2457: 
                   2458:                share_map = entry->object.share_map;
                   2459:                share_offset = (vaddr - entry->vme_start) + entry->offset;
                   2460: 
                   2461:                /*
                   2462:                 *      Look for the backing store object and offset
                   2463:                 */
                   2464: 
                   2465:                vm_map_lock_read(share_map);
                   2466: 
                   2467:                if (!vm_map_lookup_entry(share_map, share_offset,
                   2468:                                        &share_entry)) {
                   2469:                        vm_map_unlock_read(share_map);
                   2470:                        L_RETURN(KERN_INVALID_ADDRESS);
                   2471:                }
                   2472:                entry = share_entry;
                   2473:        }
                   2474: 
                   2475:        /*
                   2476:         *      If the entry was copy-on-write, we either ...
                   2477:         */
                   2478: 
                   2479:        if (entry->needs_copy) {
                   2480:                /*
                   2481:                 *      If we want to write the page, we may as well
                   2482:                 *      handle that now since we've got the sharing
                   2483:                 *      map locked.
                   2484:                 *
                   2485:                 *      If we don't need to write the page, we just
                   2486:                 *      demote the permissions allowed.
                   2487:                 */
                   2488: 
                   2489:                if (fault_type & VM_PROT_WRITE) {
                   2490:                        /*
                   2491:                         *      Make a new object, and place it in the
                   2492:                         *      object chain.  Note that no new references
                   2493:                         *      have appeared -- one just moved from the
                   2494:                         *      share map to the new object.
                   2495:                         */
                   2496: 
                   2497:                        if (lock_read_to_write(&share_map->lock)) {
                   2498:                                if (share_map != map)
                   2499:                                        vm_map_unlock_read(map);
                   2500:                                goto RetryLookup;
                   2501:                        }
                   2502: 
                   2503:                        vm_object_shadow(
                   2504:                                &entry->object.vm_object,
                   2505:                                &entry->offset,
                   2506:                                (vm_size_t) (entry->vme_end -
                   2507:                                                        entry->vme_start));
                   2508:                                
                   2509:                        entry->needs_copy = FALSE;
                   2510:                        
                   2511:                        lock_write_to_read(&share_map->lock);
                   2512:                }
                   2513:                else {
                   2514:                        /*
                   2515:                         *      We're attempting to read a copy-on-write
                   2516:                         *      page -- don't allow writes.
                   2517:                         */
                   2518: 
                   2519:                        prot &= (~VM_PROT_WRITE);
                   2520:                }
                   2521:        }
                   2522: 
                   2523:        /*
                   2524:         *      Create an object if necessary.
                   2525:         */
                   2526:        if (entry->object.vm_object == VM_OBJECT_NULL) {
                   2527: 
                   2528:                if (lock_read_to_write(&share_map->lock)) {
                   2529:                        if (share_map != map)
                   2530:                                vm_map_unlock_read(map);
                   2531:                        goto RetryLookup;
                   2532:                }
                   2533: 
                   2534:                entry->object.vm_object = vm_object_allocate(
                   2535:                                        (vm_size_t)(entry->vme_end -
                   2536:                                                        entry->vme_start));
                   2537:                entry->offset = 0;
                   2538:                lock_write_to_read(&share_map->lock);
                   2539:        }
                   2540: 
                   2541:        /*
                   2542:         *      Return the object/offset from this entry.  If the entry
                   2543:         *      was copy-on-write or empty, it has been fixed up.
                   2544:         */
                   2545: 
                   2546:        *offset = (share_offset - entry->vme_start) + entry->offset;
                   2547:        *object = entry->object.vm_object;
                   2548: 
                   2549:        /*
                   2550:         *      Return whether this is the only map sharing this data.
                   2551:         */
                   2552: 
                   2553:        if (!su) {
                   2554:                simple_lock(&share_map->ref_lock);
                   2555:                su = (share_map->ref_count == 1);
                   2556:                simple_unlock(&share_map->ref_lock);
                   2557:        }
                   2558: 
                   2559:        *out_prot = prot;
                   2560:        *single_use = su;
                   2561: 
                   2562: #if    USE_VERSIONS
                   2563:        /*
                   2564:         *      Lock the object to prevent it from disappearing
                   2565:         */
                   2566: 
                   2567:        vm_object_lock(*object);
                   2568: 
                   2569:        /*
                   2570:         *      Save the version numbers and unlock the map(s).
                   2571:         */
                   2572: 
                   2573:        if (share_map != map) {
                   2574:                out_version->share_timestamp = share_map->timestamp;
                   2575:                vm_map_unlock_read(share_map);
                   2576:        }
                   2577:        out_version->share_map = share_map;
                   2578:        out_version->main_timestamp = map->timestamp;
                   2579: 
                   2580:        vm_map_unlock_read(map);
                   2581: #endif USE_VERSIONS
                   2582: 
                   2583:        return(KERN_SUCCESS);
                   2584:        
                   2585: #undef L_RETURN
                   2586: }
                   2587: 
                   2588: #if    USE_VERSIONS
                   2589: /*
                   2590:  *     vm_map_verify:
                   2591:  *
                   2592:  *     Verifies that the map in question has not changed
                   2593:  *     since the given version.  If successful, the map
                   2594:  *     will not change until vm_map_verify_done() is called.
                   2595:  */
                   2596: boolean_t      vm_map_verify(map, version)
                   2597:        register
                   2598:        vm_map_t        map;
                   2599:        register
                   2600:        vm_map_version_t *version;      /* REF */
                   2601: {
                   2602:        boolean_t       result;
                   2603: 
                   2604:        vm_map_lock_read(map);
                   2605:        if (result = (map->timestamp == version->main_timestamp)) {
                   2606:                register
                   2607:                vm_map_t        share_map = version->share_map;
                   2608: 
                   2609:                if (share_map != map) {
                   2610:                        vm_map_lock_read(version->share_map);
                   2611:                        if (!(result = (share_map->timestamp == version->share_timestamp))) {
                   2612:                                vm_map_unlock_read(share_map);
                   2613:                        }
                   2614:                }
                   2615:        }
                   2616: 
                   2617:        if (!result)
                   2618:                vm_map_unlock_read(map);
                   2619: 
                   2620:        return(result);
                   2621: }
                   2622: 
                   2623: /*
                   2624:  *     vm_map_verify_done:
                   2625:  *
                   2626:  *     Releases locks acquired by a vm_map_verify.
                   2627:  */
                   2628: void           vm_map_verify_done(map, version)
                   2629:        register vm_map_t       map;
                   2630:        vm_map_version_t        *version;       /* REF */
                   2631: {
                   2632:        if (version->share_map != map)
                   2633:                vm_map_unlock_read(version->share_map);
                   2634:        vm_map_unlock_read(map);
                   2635: }
                   2636: 
                   2637: #else  USE_VERSIONS
                   2638: 
                   2639: /*
                   2640:  *     vm_map_lookup_done:
                   2641:  *
                   2642:  *     Releases locks acquired by a vm_map_lookup
                   2643:  *     (according to the handle returned by that lookup).
                   2644:  */
                   2645: 
                   2646: void vm_map_lookup_done(map, entry)
                   2647:        register vm_map_t       map;
                   2648:        vm_map_entry_t          entry;
                   2649: {
                   2650:        /*
                   2651:         *      If this entry references a map, unlock it first.
                   2652:         */
                   2653: 
                   2654:        if (entry->is_a_map)
                   2655:                vm_map_unlock_read(entry->object.share_map);
                   2656: 
                   2657:        /*
                   2658:         *      Unlock the main-level map
                   2659:         */
                   2660: 
                   2661:        vm_map_unlock_read(map);
                   2662: }
                   2663: #endif USE_VERSIONS
                   2664: 
                   2665: /*
                   2666:  *     Routine:        vm_map_machine_attribute
                   2667:  *     Purpose:
                   2668:  *             Provide machine-specific attributes to mappings,
                   2669:  *             such as cachability etc. for machines that provide
                   2670:  *             them.  NUMA architectures and machines with big/strange
                   2671:  *             caches will use this.
                   2672:  *     Note:
                   2673:  *             Responsibilities for locking and checking are handled here,
                   2674:  *             everything else in the pmap module. If any non-volatile
                   2675:  *             information must be kept, the pmap module should handle
                   2676:  *             it itself. [This assumes that attributes do not
                   2677:  *             need to be inherited, which seems ok to me]
                   2678:  */
                   2679: kern_return_t vm_map_machine_attribute(map, address, size, attribute, value)
                   2680:        vm_map_t        map;
                   2681:        vm_offset_t     address;
                   2682:        vm_size_t       size;
                   2683:        vm_machine_attribute_t  attribute;
                   2684:        vm_machine_attribute_val_t* value;              /* IN/OUT */
                   2685: {
                   2686:        kern_return_t   ret;
                   2687: 
                   2688:        if (address < vm_map_min(map) ||
                   2689:            (address + size) > vm_map_max(map))
                   2690:                return KERN_INVALID_ARGUMENT;
                   2691: 
                   2692:        vm_map_lock(map);
                   2693: 
                   2694:        ret = pmap_attribute(map->pmap, address, size, attribute, value);
                   2695: 
                   2696:        vm_map_unlock(map);
                   2697: 
                   2698:        return ret;
                   2699: }
                   2700: 
                   2701: #if    DEBUG
                   2702: /*
                   2703:  *     vm_map_print:   [ debug ]
                   2704:  */
                   2705: #if    1
                   2706: /*
                   2707:  * vm_map_print() is way out of date...
                   2708:  */
                   2709: void vm_map_print(vm_map_t map)
                   2710: {
                   2711: 
                   2712: }
                   2713: #else  1
                   2714: void vm_map_print(map)
                   2715:        register vm_map_t       map;
                   2716: {
                   2717:        register vm_map_entry_t entry;
                   2718:        extern int indent;
                   2719: 
                   2720:        iprintf("%s map 0x%x: pmap=0x%x,ref=%d,nentries=%d,version=%d\n",
                   2721:                (map->is_main_map ? "Task" : "Share"),
                   2722:                (int) map, (int) (map->pmap), map->ref_count, map->nentries,
                   2723:                map->timestamp);
                   2724:        indent += 2;
                   2725:        for (entry = map->header.next; entry != &map->header;
                   2726:                                entry = entry->next) {
                   2727:                iprintf("map entry 0x%x: start=0x%x, end=0x%x, ",
                   2728:                        (int) entry, (int) entry->start, (int) entry->end);
                   2729:                if (map->is_main_map) {
                   2730:                        static char *inheritance_name[4] =
                   2731:                                { "share", "copy", "none", "donate_copy"};
                   2732:                        printf("prot=%x/%x/%s, ",
                   2733:                                entry->protection,
                   2734:                                entry->max_protection,
                   2735:                                inheritance_name[entry->inheritance]);
                   2736:                        if (entry->wired_count != 0)
                   2737:                                printf("wired, ");
                   2738:                }
                   2739: 
                   2740:                if (entry->is_a_map) {
                   2741:                        printf("share=0x%x, offset=0x%x\n",
                   2742:                                (int) entry->object.share_map,
                   2743:                                (int) entry->offset);
                   2744:                        if ((entry->prev == &map->header) || (!entry->prev->is_a_map) ||
                   2745:                            (entry->prev->object.share_map != entry->object.share_map)) {
                   2746:                                indent += 2;
                   2747:                                vm_map_print(entry->object.share_map);
                   2748:                                indent -= 2;
                   2749:                        }
                   2750:                                
                   2751:                }
                   2752:                else {
                   2753:                        printf("object=0x%x, offset=0x%x",
                   2754:                                (int) entry->object.vm_object,
                   2755:                                (int) entry->offset);
                   2756:                        if (entry->copy_on_write)
                   2757:                                printf(", copy (%s)", entry->needs_copy ? "needed" : "done");
                   2758:                        printf("\n");
                   2759: 
                   2760:                        if ((entry->prev == &map->header) || (entry->prev->is_a_map) ||
                   2761:                            (entry->prev->object.vm_object != entry->object.vm_object)) {
                   2762:                                indent += 2;
                   2763:                                vm_object_print(entry->object.vm_object);
                   2764:                                indent -= 2;
                   2765:                        }
                   2766:                }
                   2767:        }
                   2768:        indent -= 2;
                   2769: }
                   2770: #endif 1
                   2771: #endif DEBUG
                   2772: 
                   2773: kern_return_t  vm_region(map, address, size,
                   2774:                                protection, max_protection,
                   2775:                                inheritance, is_shared,
                   2776:                                object_name, offset_in_object)
                   2777:        vm_map_t        map;
                   2778:        vm_offset_t     *address;               /* IN/OUT */
                   2779:        vm_size_t       *size;                  /* OUT */
                   2780:        vm_prot_t       *protection;            /* OUT */
                   2781:        vm_prot_t       *max_protection;        /* OUT */
                   2782:        vm_inherit_t    *inheritance;           /* OUT */
                   2783:        boolean_t       *is_shared;             /* OUT */
                   2784:        port_t          *object_name;           /* OUT */
                   2785:        vm_offset_t     *offset_in_object;      /* OUT */
                   2786: {
                   2787:        vm_map_entry_t  tmp_entry;
                   2788:        register
                   2789:        vm_map_entry_t  entry;
                   2790:        register
                   2791:        vm_offset_t     tmp_offset;
                   2792:        vm_offset_t     start, inaddress = *address;
                   2793: 
                   2794:        if (map == VM_MAP_NULL)
                   2795:                return(KERN_INVALID_ARGUMENT);
                   2796: 
                   2797: again_after_submap:    
                   2798:        start = *address;
                   2799: 
                   2800:        vm_map_lock_read(map);
                   2801:        if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   2802:                if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
                   2803:                        vm_map_unlock_read(map);
                   2804:                        return(KERN_NO_SPACE);
                   2805:                }
                   2806:        } else {
                   2807:                entry = tmp_entry;
                   2808:        }
                   2809: 
                   2810:        start = entry->vme_start;
                   2811:        *protection = entry->protection;
                   2812:        *max_protection = entry->max_protection;
                   2813:        *inheritance = entry->inheritance;
                   2814:        *address = start;
                   2815:        *size = (entry->vme_end - start);
                   2816: 
                   2817:        tmp_offset = entry->offset;
                   2818: #define VM_OBJECT_NAME(object)         \
                   2819:        vm_object_name((map == kernel_map) ? object : VM_OBJECT_NULL)
                   2820: 
                   2821:        if (entry->is_a_map) {
                   2822:                register
                   2823:                vm_map_t        share_map;
                   2824:                vm_size_t       share_size;
                   2825: 
                   2826:                share_map = entry->object.share_map;
                   2827: 
                   2828:                vm_map_lock_read(share_map);
                   2829:                (void) vm_map_lookup_entry(share_map, tmp_offset, &tmp_entry);
                   2830: 
                   2831:                if ((share_size = (tmp_entry->vme_end - tmp_offset)) < *size)
                   2832:                        *size = share_size;
                   2833: 
                   2834:                *object_name = VM_OBJECT_NAME(tmp_entry->object.vm_object);
                   2835:                *offset_in_object = tmp_entry->offset +
                   2836:                                        (tmp_offset - tmp_entry->vme_start);
                   2837: 
                   2838:                *is_shared = (share_map->ref_count != 1);
                   2839:                vm_map_unlock_read(share_map);
                   2840:        } else if (entry->is_sub_map) {
                   2841:                vm_map_t        sub_map;
                   2842:                vm_offset_t     oldstart = start;
                   2843: 
                   2844:                sub_map = entry->object.sub_map;
                   2845:                vm_map_reference(sub_map);
                   2846:                vm_map_unlock_read(map);
                   2847: 
                   2848:                vm_map_lock_read(sub_map);
                   2849: 
                   2850:                if (!vm_map_lookup_entry(sub_map, inaddress, &tmp_entry)) {
                   2851:                        if ((entry = tmp_entry->vme_next) ==
                   2852:                                        vm_map_to_entry(sub_map)) {
                   2853:                                vm_map_unlock_read(sub_map);
                   2854:                                vm_map_deallocate(sub_map);
                   2855:                                inaddress = *address = oldstart + *size;
                   2856:                                goto again_after_submap;
                   2857:                        }
                   2858:                }
                   2859:                else
                   2860:                        entry = tmp_entry;
                   2861: 
                   2862:                start = entry->vme_start;
                   2863:                *protection = entry->protection;
                   2864:                *max_protection = entry->max_protection;
                   2865:                *inheritance = entry->inheritance;
                   2866:                *address = start;
                   2867:                *size = (entry->vme_end - start);
                   2868: 
                   2869:                *is_shared = sub_map->hdr.entries_pageable;
                   2870:                *object_name = VM_OBJECT_NAME(entry->object.vm_object);
                   2871:                *offset_in_object = entry->offset;
                   2872: 
                   2873:                vm_map_unlock_read(sub_map);
                   2874: 
                   2875:                vm_map_deallocate(sub_map);
                   2876: 
                   2877:                return(KERN_SUCCESS);
                   2878:        } else {
                   2879:                *is_shared = FALSE;
                   2880:                *object_name = VM_OBJECT_NAME(entry->object.vm_object);
                   2881:                *offset_in_object = tmp_offset;
                   2882:        }
                   2883: #undef VM_OBJECT_NAME
                   2884: 
                   2885:        vm_map_unlock_read(map);
                   2886: 
                   2887:        return(KERN_SUCCESS);
                   2888: }
                   2889: 
                   2890: #if    MACH_DEBUG
                   2891: #include <kern/host.h>
                   2892: 
                   2893: kern_return_t  host_vm_region(
                   2894:        host_t          host,
                   2895:        vm_offset_t     *address,               /* IN/OUT */
                   2896:        vm_size_t       *size,                  /* OUT */
                   2897:        vm_prot_t       *protection,            /* OUT */
                   2898:        vm_prot_t       *max_protection,        /* OUT */
                   2899:        vm_inherit_t    *inheritance,           /* OUT */
                   2900:        boolean_t       *is_pageable,           /* OUT */
                   2901:        port_t          *object_name,           /* OUT */
                   2902:        vm_offset_t     *offset_in_object       /* OUT */
                   2903: )
                   2904: {
                   2905:        if (host == HOST_NULL)
                   2906:                return(KERN_INVALID_ARGUMENT);
                   2907: 
                   2908:        return vm_region(kernel_map, address, size,
                   2909:                         protection, max_protection,
                   2910:                         inheritance, is_pageable,
                   2911:                         object_name, offset_in_object);
                   2912: }
                   2913: #endif /* MACH_DEBUG */
                   2914: 
                   2915: /*
                   2916:  *     vm_move:
                   2917:  *
                   2918:  *     Move memory from source to destination map, possibly deallocating
                   2919:  *     the source map reference to the memory.
                   2920:  *
                   2921:  *     Parameters are as follows:
                   2922:  *
                   2923:  *     src_map         Source address map
                   2924:  *     src_addr        Address within source map
                   2925:  *     dst_map         Destination address map
                   2926:  *     num_bytes       Amount of data (in bytes) to copy/move
                   2927:  *     src_dealloc     Should source be removed after copy?
                   2928:  *
                   2929:  *     Assumes the src and dst maps are not already locked.
                   2930:  *
                   2931:  *     If successful, returns destination address in dst_addr.
                   2932:  */
                   2933: kern_return_t vm_move(src_map,src_addr,dst_map,num_bytes,src_dealloc,dst_addr)
                   2934:        vm_map_t                src_map;
                   2935:        register vm_offset_t    src_addr;
                   2936:        register vm_map_t       dst_map;
                   2937:        vm_offset_t             num_bytes;
                   2938:        boolean_t               src_dealloc;
                   2939:        vm_offset_t             *dst_addr;
                   2940: {
                   2941:        register vm_offset_t    src_start;      /* Beginning of region */
                   2942:        register vm_size_t      src_size;       /* Size of rounded region */
                   2943:        vm_offset_t             dst_start;      /* destination address */
                   2944:        register kern_return_t  result;
                   2945: 
                   2946:        if (num_bytes == 0) {
                   2947:                *dst_addr = 0;
                   2948:                return KERN_SUCCESS;
                   2949:        }
                   2950: 
                   2951:        /*
                   2952:         *      Page-align the source region
                   2953:         */
                   2954: 
                   2955:        src_start = trunc_page(src_addr);
                   2956:        src_size = round_page(src_addr + num_bytes) - src_start;
                   2957: 
                   2958:        /*
                   2959:         *      Allocate a place to put the copy
                   2960:         */
                   2961: 
                   2962:        dst_start = (vm_offset_t) 0;
                   2963:        result = vm_allocate(dst_map, &dst_start, src_size, TRUE);
                   2964:        if (result == KERN_SUCCESS) {
                   2965:                /*
                   2966:                 *      Perform the copy, asking for deallocation if desired
                   2967:                 */
                   2968:                result = vm_map_copy(dst_map, src_map, dst_start, src_size,
                   2969:                                     src_start, FALSE, src_dealloc);
                   2970: 
                   2971:                /*
                   2972:                 *      Return the destination address corresponding to
                   2973:                 *      the source address given (rather than the front
                   2974:                 *      of the newly-allocated page).
                   2975:                 */
                   2976: 
                   2977:                if (result == KERN_SUCCESS)
                   2978:                        *dst_addr = dst_start + (src_addr - src_start);
                   2979:                else
                   2980:                        (void) vm_deallocate(dst_map, dst_start, src_size);
                   2981:        }
                   2982: 
                   2983:        return(result);
                   2984: }
                   2985: 
                   2986: pmap_t
                   2987: vm_map_pmap_EXTERNAL(
                   2988:        vm_map_t                map
                   2989: )
                   2990: {
                   2991:        return (vm_map_pmap(map));
                   2992: }

unix.superglobalmegacorp.com

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