Annotation of XNU/osfmk/vm/vm_map.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988,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:  */
                     52: /*
                     53:  *     File:   vm/vm_map.c
                     54:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     55:  *     Date:   1985
                     56:  *
                     57:  *     Virtual memory mapping module.
                     58:  */
                     59: 
                     60: #include <cpus.h>
                     61: #include <task_swapper.h>
                     62: #include <mach_assert.h>
                     63: #include <dipc.h>
                     64: 
                     65: #include <mach/kern_return.h>
                     66: #include <mach/port.h>
                     67: #include <mach/vm_attributes.h>
                     68: #include <mach/vm_param.h>
                     69: #include <mach/vm_behavior.h>
                     70: #include <kern/assert.h>
                     71: #include <kern/counters.h>
                     72: #include <kern/zalloc.h>
                     73: #include <vm/vm_init.h>
                     74: #include <vm/vm_fault.h>
                     75: #include <vm/vm_map.h>
                     76: #include <vm/vm_object.h>
                     77: #include <vm/vm_page.h>
                     78: #include <vm/vm_kern.h>
                     79: #include <ipc/ipc_port.h>
                     80: #include <kern/sched_prim.h>
                     81: #include <kern/misc_protos.h>
                     82: #include <mach/vm_task_server.h>
                     83: #include <mach/mach_host_server.h>
                     84: #include <ddb/tr.h>
                     85: #include <kern/xpr.h>
                     86: 
                     87: /* Internal prototypes
                     88:  */
                     89: extern boolean_t vm_map_range_check(
                     90:                                vm_map_t        map,
                     91:                                vm_offset_t     start,
                     92:                                vm_offset_t     end,
                     93:                                vm_map_entry_t  *entry);
                     94: 
                     95: extern vm_map_entry_t  _vm_map_entry_create(
                     96:                                struct vm_map_header    *map_header);
                     97: 
                     98: extern void            _vm_map_entry_dispose(
                     99:                                struct vm_map_header    *map_header,
                    100:                                vm_map_entry_t          entry);
                    101: 
                    102: extern void            vm_map_pmap_enter(
                    103:                                vm_map_t        map,
                    104:                                vm_offset_t     addr,
                    105:                                vm_offset_t     end_addr,
                    106:                                vm_object_t     object,
                    107:                                vm_offset_t     offset,
                    108:                                vm_prot_t       protection);
                    109: 
                    110: extern void            _vm_map_clip_end(
                    111:                                struct vm_map_header    *map_header,
                    112:                                vm_map_entry_t          entry,
                    113:                                vm_offset_t             end);
                    114: 
                    115: extern void            vm_map_entry_delete(
                    116:                                vm_map_t        map,
                    117:                                vm_map_entry_t  entry);
                    118: 
                    119: extern kern_return_t   vm_map_delete(
                    120:                                vm_map_t        map,
                    121:                                vm_offset_t     start,
                    122:                                vm_offset_t     end,
                    123:                                int             flags);
                    124: 
                    125: extern void            vm_map_copy_steal_pages(
                    126:                                vm_map_copy_t   copy);
                    127: 
                    128: extern kern_return_t   vm_map_copy_overwrite_unaligned(
                    129:                                vm_map_t        dst_map,
                    130:                                vm_map_entry_t  entry,
                    131:                                vm_map_copy_t   copy,
                    132:                                vm_offset_t     start);
                    133: 
                    134: extern kern_return_t   vm_map_copy_overwrite_aligned(
                    135:                                vm_map_t        dst_map,
                    136:                                vm_map_entry_t  tmp_entry,
                    137:                                vm_map_copy_t   copy,
                    138:                                vm_offset_t     start);
                    139: 
                    140: extern kern_return_t   vm_map_copyout_kernel_buffer(
                    141:                                vm_map_t        map,
                    142:                                vm_offset_t     *addr,  /* IN/OUT */
                    143:                                vm_map_copy_t   copy,
                    144:                                boolean_t       overwrite);
                    145: 
                    146: extern kern_return_t   vm_map_copyin_page_list_cont(
                    147:                                vm_map_copyin_args_t    cont_args,
                    148:                                vm_map_copy_t           *copy_result); /* OUT */
                    149: 
                    150: extern void            vm_map_fork_share(
                    151:                                vm_map_t        old_map,
                    152:                                vm_map_entry_t  old_entry,
                    153:                                vm_map_t        new_map);
                    154: 
                    155: extern boolean_t       vm_map_fork_copy(
                    156:                                vm_map_t        old_map,
                    157:                                vm_map_entry_t  *old_entry_p,
                    158:                                vm_map_t        new_map);
                    159: 
                    160: extern kern_return_t   vm_remap_range_allocate(
                    161:                                vm_map_t        map,
                    162:                                vm_offset_t     *address,       /* IN/OUT */
                    163:                                vm_size_t       size,
                    164:                                vm_offset_t     mask,
                    165:                                boolean_t       anywhere,
                    166:                                vm_map_entry_t  *map_entry);    /* OUT */
                    167: 
                    168: extern void            _vm_map_clip_start(
                    169:                                struct vm_map_header    *map_header,
                    170:                                vm_map_entry_t          entry,
                    171:                                vm_offset_t             start);
                    172: 
                    173: /*
                    174:  * Macros to copy a vm_map_entry. We must be careful to correctly
                    175:  * manage the wired page count. vm_map_entry_copy() creates a new
                    176:  * map entry to the same memory - the wired count in the new entry
                    177:  * must be set to zero. vm_map_entry_copy_full() creates a new
                    178:  * entry that is identical to the old entry.  This preserves the
                    179:  * wire count; it's used for map splitting and zone changing in
                    180:  * vm_map_copyout.
                    181:  */
                    182: #define vm_map_entry_copy(NEW,OLD) \
                    183: MACRO_BEGIN                                     \
                    184:                 *(NEW) = *(OLD);                \
                    185:                 (NEW)->is_shared = FALSE;      \
                    186:                 (NEW)->needs_wakeup = FALSE;    \
                    187:                 (NEW)->in_transition = FALSE;   \
                    188:                 (NEW)->wired_count = 0;         \
                    189:                 (NEW)->user_wired_count = 0;    \
                    190: MACRO_END
                    191: 
                    192: #define vm_map_entry_copy_full(NEW,OLD)        (*(NEW) = *(OLD))
                    193: 
                    194: /*
                    195:  *     Virtual memory maps provide for the mapping, protection,
                    196:  *     and sharing of virtual memory objects.  In addition,
                    197:  *     this module provides for an efficient virtual copy of
                    198:  *     memory from one map to another.
                    199:  *
                    200:  *     Synchronization is required prior to most operations.
                    201:  *
                    202:  *     Maps consist of an ordered doubly-linked list of simple
                    203:  *     entries; a single hint is used to speed up lookups.
                    204:  *
                    205:  *     Sharing maps have been deleted from this version of Mach.
                    206:  *     All shared objects are now mapped directly into the respective
                    207:  *     maps.  This requires a change in the copy on write strategy;
                    208:  *     the asymmetric (delayed) strategy is used for shared temporary
                    209:  *     objects instead of the symmetric (shadow) strategy.  All maps
                    210:  *     are now "top level" maps (either task map, kernel map or submap
                    211:  *     of the kernel map).  
                    212:  *
                    213:  *     Since portions of maps are specified by start/end addreses,
                    214:  *     which may not align with existing map entries, all
                    215:  *     routines merely "clip" entries to these start/end values.
                    216:  *     [That is, an entry is split into two, bordering at a
                    217:  *     start or end value.]  Note that these clippings may not
                    218:  *     always be necessary (as the two resulting entries are then
                    219:  *     not changed); however, the clipping is done for convenience.
                    220:  *     No attempt is currently made to "glue back together" two
                    221:  *     abutting entries.
                    222:  *
                    223:  *     The symmetric (shadow) copy strategy implements virtual copy
                    224:  *     by copying VM object references from one map to
                    225:  *     another, and then marking both regions as copy-on-write.
                    226:  *     It is important to note that only one writeable reference
                    227:  *     to a VM object region exists in any map when this strategy
                    228:  *     is used -- this means that shadow object creation can be
                    229:  *     delayed until a write operation occurs.  The symmetric (delayed)
                    230:  *     strategy allows multiple maps to have writeable references to
                    231:  *     the same region of a vm object, and hence cannot delay creating
                    232:  *     its copy objects.  See vm_object_copy_quickly() in vm_object.c.
                    233:  *     Copying of permanent objects is completely different; see
                    234:  *     vm_object_copy_strategically() in vm_object.c.
                    235:  */
                    236: 
                    237: zone_t         vm_map_zone;            /* zone for vm_map structures */
                    238: zone_t         vm_map_entry_zone;      /* zone for vm_map_entry structures */
                    239: zone_t         vm_map_kentry_zone;     /* zone for kernel entry structures */
                    240: zone_t         vm_map_copy_zone;       /* zone for vm_map_copy structures */
                    241: 
                    242: 
                    243: /*
                    244:  *     Placeholder object for submap operations.  This object is dropped
                    245:  *     into the range by a call to vm_map_find, and removed when
                    246:  *     vm_map_submap creates the submap.
                    247:  */
                    248: 
                    249: vm_object_t    vm_submap_object;
                    250: 
                    251: /*
                    252:  *     vm_map_init:
                    253:  *
                    254:  *     Initialize the vm_map module.  Must be called before
                    255:  *     any other vm_map routines.
                    256:  *
                    257:  *     Map and entry structures are allocated from zones -- we must
                    258:  *     initialize those zones.
                    259:  *
                    260:  *     There are three zones of interest:
                    261:  *
                    262:  *     vm_map_zone:            used to allocate maps.
                    263:  *     vm_map_entry_zone:      used to allocate map entries.
                    264:  *     vm_map_kentry_zone:     used to allocate map entries for the kernel.
                    265:  *
                    266:  *     The kernel allocates map entries from a special zone that is initially
                    267:  *     "crammed" with memory.  It would be difficult (perhaps impossible) for
                    268:  *     the kernel to allocate more memory to a entry zone when it became
                    269:  *     empty since the very act of allocating memory implies the creation
                    270:  *     of a new entry.
                    271:  */
                    272: 
                    273: vm_offset_t    map_data;
                    274: vm_size_t      map_data_size;
                    275: vm_offset_t    kentry_data;
                    276: vm_size_t      kentry_data_size;
                    277: int            kentry_count = 2048;            /* to init kentry_data_size */
                    278: 
                    279: /*
                    280:  *     Threshold for aggressive (eager) page map entering for vm copyout
                    281:  *     operations.  Any copyout larger will NOT be aggressively entered.
                    282:  */
                    283: vm_size_t vm_map_aggressive_enter_max;         /* set by bootstrap */
                    284: 
                    285: void
                    286: vm_map_init(
                    287:        void)
                    288: {
                    289:        vm_map_zone = zinit((vm_size_t) sizeof(struct vm_map), 40*1024,
                    290:                                        PAGE_SIZE, "maps");
                    291: 
                    292:        vm_map_entry_zone = zinit((vm_size_t) sizeof(struct vm_map_entry),
                    293:                                        1024*1024, PAGE_SIZE*5,
                    294:                                        "non-kernel map entries");
                    295: 
                    296:        vm_map_kentry_zone = zinit((vm_size_t) sizeof(struct vm_map_entry),
                    297:                                        kentry_data_size, kentry_data_size,
                    298:                                        "kernel map entries");
                    299: 
                    300:        vm_map_copy_zone = zinit((vm_size_t) sizeof(struct vm_map_copy),
                    301:                                        16*1024, PAGE_SIZE, "map copies");
                    302: 
                    303:        /*
                    304:         *      Cram the map and kentry zones with initial data.
                    305:         *      Set kentry_zone non-collectible to aid zone_gc().
                    306:         */
                    307:        zone_change(vm_map_zone, Z_COLLECT, FALSE);
                    308:        zone_change(vm_map_kentry_zone, Z_COLLECT, FALSE);
                    309:        zone_change(vm_map_kentry_zone, Z_EXPAND, FALSE);
                    310:        zcram(vm_map_zone, map_data, map_data_size);
                    311:        zcram(vm_map_kentry_zone, kentry_data, kentry_data_size);
                    312: }
                    313: 
                    314: void
                    315: vm_map_steal_memory(
                    316:        void)
                    317: {
                    318:        map_data_size = round_page(10 * sizeof(struct vm_map));
                    319:        map_data = pmap_steal_memory(map_data_size);
                    320: 
                    321:        /*
                    322:         * Limiting worst case: vm_map_kentry_zone needs to map each "available"
                    323:         * physical page (i.e. that beyond the kernel image and page tables) 
                    324:         * individually; we fudge this slightly and guess at most one entry per
                    325:         * two pages. This works out to roughly .4 of 1% of physical memory,
                    326:         * or roughly 1800 entries (56K) for a 16M machine with 4K pages.
                    327:         */
                    328: 
                    329:        kentry_count = pmap_free_pages() / 2;
                    330: 
                    331:        kentry_data_size =
                    332:                round_page(kentry_count * sizeof(struct vm_map_entry));
                    333:        kentry_data = pmap_steal_memory(kentry_data_size);
                    334: }
                    335: 
                    336: /*
                    337:  *     vm_map_create:
                    338:  *
                    339:  *     Creates and returns a new empty VM map with
                    340:  *     the given physical map structure, and having
                    341:  *     the given lower and upper address bounds.
                    342:  */
                    343: vm_map_t
                    344: vm_map_create(
                    345:        pmap_t          pmap,
                    346:        vm_offset_t     min,
                    347:        vm_offset_t     max,
                    348:        boolean_t       pageable)
                    349: {
                    350:        register vm_map_t       result;
                    351: 
                    352:        result = (vm_map_t) zalloc(vm_map_zone);
                    353:        if (result == VM_MAP_NULL)
                    354:                panic("vm_map_create");
                    355: 
                    356:        vm_map_first_entry(result) = vm_map_to_entry(result);
                    357:        vm_map_last_entry(result)  = vm_map_to_entry(result);
                    358:        result->hdr.nentries = 0;
                    359:        result->hdr.entries_pageable = pageable;
                    360: 
                    361:        result->size = 0;
                    362:        result->ref_count = 1;
                    363: #if    TASK_SWAPPER
                    364:        result->res_count = 1;
                    365:        result->sw_state = MAP_SW_IN;
                    366: #endif /* TASK_SWAPPER */
                    367:        result->pmap = pmap;
                    368:        result->min_offset = min;
                    369:        result->max_offset = max;
                    370:        result->wiring_required = FALSE;
                    371:        result->no_zero_fill = FALSE;
                    372:        result->wait_for_space = FALSE;
                    373:        result->first_free = vm_map_to_entry(result);
                    374:        result->hint = vm_map_to_entry(result);
                    375:        vm_map_lock_init(result);
                    376:        mutex_init(&result->s_lock, ETAP_VM_RESULT);
                    377: 
                    378:        return(result);
                    379: }
                    380: 
                    381: /*
                    382:  *     vm_map_entry_create:    [ internal use only ]
                    383:  *
                    384:  *     Allocates a VM map entry for insertion in the
                    385:  *     given map (or map copy).  No fields are filled.
                    386:  */
                    387: #define        vm_map_entry_create(map) \
                    388:            _vm_map_entry_create(&(map)->hdr)
                    389: 
                    390: #define        vm_map_copy_entry_create(copy) \
                    391:            _vm_map_entry_create(&(copy)->cpy_hdr)
                    392: 
                    393: vm_map_entry_t
                    394: _vm_map_entry_create(
                    395:        register struct vm_map_header   *map_header)
                    396: {
                    397:        register zone_t zone;
                    398:        register vm_map_entry_t entry;
                    399: 
                    400:        if (map_header->entries_pageable)
                    401:            zone = vm_map_entry_zone;
                    402:        else
                    403:            zone = vm_map_kentry_zone;
                    404: 
                    405:        entry = (vm_map_entry_t) zalloc(zone);
                    406:        if (entry == VM_MAP_ENTRY_NULL)
                    407:                panic("vm_map_entry_create");
                    408: 
                    409:        return(entry);
                    410: }
                    411: 
                    412: /*
                    413:  *     vm_map_entry_dispose:   [ internal use only ]
                    414:  *
                    415:  *     Inverse of vm_map_entry_create.
                    416:  */
                    417: #define        vm_map_entry_dispose(map, entry)                \
                    418: MACRO_BEGIN                                            \
                    419:        assert((entry) != (map)->first_free &&          \
                    420:               (entry) != (map)->hint);                 \
                    421:        _vm_map_entry_dispose(&(map)->hdr, (entry));    \
                    422: MACRO_END
                    423: 
                    424: #define        vm_map_copy_entry_dispose(map, entry) \
                    425:        _vm_map_entry_dispose(&(copy)->cpy_hdr, (entry))
                    426: 
                    427: void
                    428: _vm_map_entry_dispose(
                    429:        register struct vm_map_header   *map_header,
                    430:        register vm_map_entry_t         entry)
                    431: {
                    432:        register zone_t         zone;
                    433: 
                    434:        if (map_header->entries_pageable)
                    435:            zone = vm_map_entry_zone;
                    436:        else
                    437:            zone = vm_map_kentry_zone;
                    438: 
                    439:        zfree(zone, (vm_offset_t) entry);
                    440: }
                    441: 
                    442: boolean_t first_free_is_valid(vm_map_t map);   /* forward */
                    443: boolean_t first_free_check = FALSE;
                    444: boolean_t
                    445: first_free_is_valid(
                    446:        vm_map_t        map)
                    447: {
                    448:        vm_map_entry_t  entry, next;
                    449: 
                    450:        if (!first_free_check)
                    451:                return TRUE;
                    452:                
                    453:        entry = vm_map_to_entry(map);
                    454:        next = entry->vme_next;
                    455:        while (trunc_page(next->vme_start) == trunc_page(entry->vme_end) ||
                    456:               (trunc_page(next->vme_start) == trunc_page(entry->vme_start) &&
                    457:                next != vm_map_to_entry(map))) {
                    458:                entry = next;
                    459:                next = entry->vme_next;
                    460:                if (entry == vm_map_to_entry(map))
                    461:                        break;
                    462:        }
                    463:        if (map->first_free != entry) {
                    464:                printf("Bad first_free for map 0x%x: 0x%x should be 0x%x\n",
                    465:                       map, map->first_free, entry);
                    466:                return FALSE;
                    467:        }
                    468:        return TRUE;
                    469: }
                    470: 
                    471: /*
                    472:  *     UPDATE_FIRST_FREE:
                    473:  *
                    474:  *     Updates the map->first_free pointer to the
                    475:  *     entry immediately before the first hole in the map.
                    476:  *     The map should be locked.
                    477:  */
                    478: #define UPDATE_FIRST_FREE(map, new_first_free)                                 \
                    479: MACRO_BEGIN                                                            \
                    480:        vm_map_t        UFF_map;                                        \
                    481:        vm_map_entry_t  UFF_first_free;                                 \
                    482:        vm_map_entry_t  UFF_next_entry;                                 \
                    483:        UFF_map = (map);                                                \
                    484:        UFF_first_free = (new_first_free);                              \
                    485:        UFF_next_entry = UFF_first_free->vme_next;                      \
                    486:        while (trunc_page(UFF_next_entry->vme_start) ==                 \
                    487:               trunc_page(UFF_first_free->vme_end) ||                   \
                    488:               (trunc_page(UFF_next_entry->vme_start) ==                \
                    489:                trunc_page(UFF_first_free->vme_start) &&                \
                    490:                UFF_next_entry != vm_map_to_entry(UFF_map))) {          \
                    491:                UFF_first_free = UFF_next_entry;                        \
                    492:                UFF_next_entry = UFF_first_free->vme_next;              \
                    493:                if (UFF_first_free == vm_map_to_entry(UFF_map))         \
                    494:                        break;                                          \
                    495:        }                                                               \
                    496:        UFF_map->first_free = UFF_first_free;                           \
                    497:        assert(first_free_is_valid(UFF_map));                           \
                    498: MACRO_END
                    499: 
                    500: /*
                    501:  *     vm_map_entry_{un,}link:
                    502:  *
                    503:  *     Insert/remove entries from maps (or map copies).
                    504:  */
                    505: #define vm_map_entry_link(map, after_where, entry)                     \
                    506: MACRO_BEGIN                                                            \
                    507:        vm_map_t VMEL_map;                                              \
                    508:        vm_map_entry_t VMEL_entry;                                      \
                    509:        VMEL_map = (map);                                               \
                    510:        VMEL_entry = (entry);                                           \
                    511:        _vm_map_entry_link(&VMEL_map->hdr, after_where, VMEL_entry);    \
                    512:        UPDATE_FIRST_FREE(VMEL_map, VMEL_map->first_free);              \
                    513: MACRO_END
                    514: 
                    515: 
                    516: #define vm_map_copy_entry_link(copy, after_where, entry)               \
                    517:        _vm_map_entry_link(&(copy)->cpy_hdr, after_where, (entry))
                    518: 
                    519: #define _vm_map_entry_link(hdr, after_where, entry)                    \
                    520:        MACRO_BEGIN                                                     \
                    521:        (hdr)->nentries++;                                              \
                    522:        (entry)->vme_prev = (after_where);                              \
                    523:        (entry)->vme_next = (after_where)->vme_next;                    \
                    524:        (entry)->vme_prev->vme_next = (entry)->vme_next->vme_prev = (entry); \
                    525:        MACRO_END
                    526: 
                    527: #define vm_map_entry_unlink(map, entry)                                        \
                    528: MACRO_BEGIN                                                            \
                    529:        vm_map_t VMEU_map;                                              \
                    530:        vm_map_entry_t VMEU_entry;                                      \
                    531:        vm_map_entry_t VMEU_first_free;                                 \
                    532:        VMEU_map = (map);                                               \
                    533:        VMEU_entry = (entry);                                           \
                    534:        if (VMEU_entry->vme_start <= VMEU_map->first_free->vme_start)   \
                    535:                VMEU_first_free = VMEU_entry->vme_prev;                 \
                    536:        else                                                            \
                    537:                VMEU_first_free = VMEU_map->first_free;                 \
                    538:        _vm_map_entry_unlink(&VMEU_map->hdr, VMEU_entry);               \
                    539:        UPDATE_FIRST_FREE(VMEU_map, VMEU_first_free);                   \
                    540: MACRO_END
                    541: 
                    542: #define vm_map_copy_entry_unlink(copy, entry)                          \
                    543:        _vm_map_entry_unlink(&(copy)->cpy_hdr, (entry))
                    544: 
                    545: #define _vm_map_entry_unlink(hdr, entry)                               \
                    546:        MACRO_BEGIN                                                     \
                    547:        (hdr)->nentries--;                                              \
                    548:        (entry)->vme_next->vme_prev = (entry)->vme_prev;                \
                    549:        (entry)->vme_prev->vme_next = (entry)->vme_next;                \
                    550:        MACRO_END
                    551: 
                    552: #if    MACH_ASSERT && TASK_SWAPPER
                    553: /*
                    554:  *     vm_map_reference:
                    555:  *
                    556:  *     Adds valid reference and residence counts to the given map.
                    557:  *     The map must be in memory (i.e. non-zero residence count).
                    558:  *
                    559:  */
                    560: void
                    561: vm_map_reference(
                    562:        register vm_map_t       map)
                    563: {
                    564:        if (map == VM_MAP_NULL)
                    565:                return;
                    566: 
                    567:        mutex_lock(&map->s_lock);
                    568:        assert(map->res_count > 0);
                    569:        assert(map->ref_count >= map->res_count);
                    570:        map->ref_count++;
                    571:        map->res_count++;
                    572:        mutex_unlock(&map->s_lock);
                    573: }
                    574: 
                    575: /*
                    576:  *     vm_map_res_reference:
                    577:  *
                    578:  *     Adds another valid residence count to the given map.
                    579:  *
                    580:  *     Map is locked so this function can be called from
                    581:  *     vm_map_swapin.
                    582:  *
                    583:  */
                    584: void vm_map_res_reference(register vm_map_t map)
                    585: {
                    586:        /* assert map is locked */
                    587:        assert(map->res_count >= 0);
                    588:        assert(map->ref_count >= map->res_count);
                    589:        if (map->res_count == 0) {
                    590:                mutex_unlock(&map->s_lock);
                    591:                vm_map_lock(map);
                    592:                vm_map_swapin(map);
                    593:                mutex_lock(&map->s_lock);
                    594:                ++map->res_count;
                    595:                vm_map_unlock(map);
                    596:        } else
                    597:                ++map->res_count;
                    598: }
                    599: 
                    600: /*
                    601:  *     vm_map_reference_swap:
                    602:  *
                    603:  *     Adds valid reference and residence counts to the given map.
                    604:  *
                    605:  *     The map may not be in memory (i.e. zero residence count).
                    606:  *
                    607:  */
                    608: void vm_map_reference_swap(register vm_map_t map)
                    609: {
                    610:        assert(map != VM_MAP_NULL);
                    611:        mutex_lock(&map->s_lock);
                    612:        assert(map->res_count >= 0);
                    613:        assert(map->ref_count >= map->res_count);
                    614:        map->ref_count++;
                    615:        vm_map_res_reference(map);
                    616:        mutex_unlock(&map->s_lock);
                    617: }
                    618: 
                    619: /*
                    620:  *     vm_map_res_deallocate:
                    621:  *
                    622:  *     Decrement residence count on a map; possibly causing swapout.
                    623:  *
                    624:  *     The map must be in memory (i.e. non-zero residence count).
                    625:  *
                    626:  *     The map is locked, so this function is callable from vm_map_deallocate.
                    627:  *
                    628:  */
                    629: void vm_map_res_deallocate(register vm_map_t map)
                    630: {
                    631:        assert(map->res_count > 0);
                    632:        if (--map->res_count == 0) {
                    633:                mutex_unlock(&map->s_lock);
                    634:                vm_map_lock(map);
                    635:                vm_map_swapout(map);
                    636:                vm_map_unlock(map);
                    637:                mutex_lock(&map->s_lock);
                    638:        }
                    639:        assert(map->ref_count >= map->res_count);
                    640: }
                    641: #endif /* MACH_ASSERT && TASK_SWAPPER */
                    642: 
                    643: /*
                    644:  *     vm_map_deallocate:
                    645:  *
                    646:  *     Removes a reference from the specified map,
                    647:  *     destroying it if no references remain.
                    648:  *     The map should not be locked.
                    649:  */
                    650: void
                    651: vm_map_deallocate(
                    652:        register vm_map_t       map)
                    653: {
                    654:        unsigned int            ref;
                    655: 
                    656:        if (map == VM_MAP_NULL)
                    657:                return;
                    658: 
                    659:        mutex_lock(&map->s_lock);
                    660:        ref = --map->ref_count;
                    661:        if (ref > 0) {
                    662:                vm_map_res_deallocate(map);
                    663:                mutex_unlock(&map->s_lock);
                    664:                /*
                    665:                 * Someone may be waiting in task_halt_wait. They
                    666:                 * wait there for the map reference count to reach
                    667:                 * two (one for the task and one for their act).  Wake
                    668:                 * them up if need be.
                    669:                 */
                    670:                if (ref == 2)
                    671:                        thread_wakeup(&map->ref_count);
                    672:                return;
                    673:        }
                    674:        assert(map->ref_count == 0);
                    675:        mutex_unlock(&map->s_lock);
                    676: 
                    677: #if    TASK_SWAPPER
                    678:        /*
                    679:         * The map residence count isn't decremented here because
                    680:         * the vm_map_delete below will traverse the entire map, 
                    681:         * deleting entries, and the residence counts on objects
                    682:         * and sharing maps will go away then.
                    683:         */
                    684: #endif
                    685: 
                    686:        vm_map_destroy(map);
                    687: }
                    688: 
                    689: /*
                    690:  *     vm_map_destroy:
                    691:  *
                    692:  *     Actually destroy a map.
                    693:  */
                    694: void
                    695: vm_map_destroy(
                    696:        register vm_map_t       map)
                    697: {
                    698:        vm_map_lock(map);
                    699:        (void) vm_map_delete(map, map->min_offset,
                    700:                             map->max_offset, VM_MAP_NO_FLAGS);
                    701:        vm_map_unlock(map);
                    702: 
                    703:        pmap_destroy(map->pmap);
                    704: 
                    705:        zfree(vm_map_zone, (vm_offset_t) map);
                    706: }
                    707: 
                    708: #if    TASK_SWAPPER
                    709: /*
                    710:  * vm_map_swapin/vm_map_swapout
                    711:  *
                    712:  * Swap a map in and out, either referencing or releasing its resources.  
                    713:  * These functions are internal use only; however, they must be exported
                    714:  * because they may be called from macros, which are exported.
                    715:  *
                    716:  * In the case of swapout, there could be races on the residence count, 
                    717:  * so if the residence count is up, we return, assuming that a 
                    718:  * vm_map_deallocate() call in the near future will bring us back.
                    719:  *
                    720:  * Locking:
                    721:  *     -- We use the map write lock for synchronization among races.
                    722:  *     -- The map write lock, and not the simple s_lock, protects the
                    723:  *        swap state of the map.
                    724:  *     -- If a map entry is a share map, then we hold both locks, in
                    725:  *        hierarchical order.
                    726:  *
                    727:  * Synchronization Notes:
                    728:  *     1) If a vm_map_swapin() call happens while swapout in progress, it
                    729:  *     will block on the map lock and proceed when swapout is through.
                    730:  *     2) A vm_map_reference() call at this time is illegal, and will
                    731:  *     cause a panic.  vm_map_reference() is only allowed on resident
                    732:  *     maps, since it refuses to block.
                    733:  *     3) A vm_map_swapin() call during a swapin will block, and 
                    734:  *     proceeed when the first swapin is done, turning into a nop.
                    735:  *     This is the reason the res_count is not incremented until
                    736:  *     after the swapin is complete.
                    737:  *     4) There is a timing hole after the checks of the res_count, before
                    738:  *     the map lock is taken, during which a swapin may get the lock
                    739:  *     before a swapout about to happen.  If this happens, the swapin
                    740:  *     will detect the state and increment the reference count, causing
                    741:  *     the swapout to be a nop, thereby delaying it until a later 
                    742:  *     vm_map_deallocate.  If the swapout gets the lock first, then 
                    743:  *     the swapin will simply block until the swapout is done, and 
                    744:  *     then proceed.
                    745:  *
                    746:  * Because vm_map_swapin() is potentially an expensive operation, it
                    747:  * should be used with caution.
                    748:  *
                    749:  * Invariants:
                    750:  *     1) A map with a residence count of zero is either swapped, or
                    751:  *        being swapped.
                    752:  *     2) A map with a non-zero residence count is either resident,
                    753:  *        or being swapped in.
                    754:  */
                    755: 
                    756: int vm_map_swap_enable = 1;
                    757: 
                    758: void vm_map_swapin (vm_map_t map)
                    759: {
                    760:        register vm_map_entry_t entry;
                    761:        
                    762:        if (!vm_map_swap_enable)        /* debug */
                    763:                return;
                    764: 
                    765:        /*
                    766:         * Map is locked
                    767:         * First deal with various races.
                    768:         */
                    769:        if (map->sw_state == MAP_SW_IN)
                    770:                /* 
                    771:                 * we raced with swapout and won.  Returning will incr.
                    772:                 * the res_count, turning the swapout into a nop.
                    773:                 */
                    774:                return;
                    775: 
                    776:        /*
                    777:         * The residence count must be zero.  If we raced with another
                    778:         * swapin, the state would have been IN; if we raced with a
                    779:         * swapout (after another competing swapin), we must have lost
                    780:         * the race to get here (see above comment), in which case
                    781:         * res_count is still 0.
                    782:         */
                    783:        assert(map->res_count == 0);
                    784: 
                    785:        /*
                    786:         * There are no intermediate states of a map going out or
                    787:         * coming in, since the map is locked during the transition.
                    788:         */
                    789:        assert(map->sw_state == MAP_SW_OUT);
                    790: 
                    791:        /*
                    792:         * We now operate upon each map entry.  If the entry is a sub- 
                    793:         * or share-map, we call vm_map_res_reference upon it.
                    794:         * If the entry is an object, we call vm_object_res_reference
                    795:         * (this may iterate through the shadow chain).
                    796:         * Note that we hold the map locked the entire time,
                    797:         * even if we get back here via a recursive call in
                    798:         * vm_map_res_reference.
                    799:         */
                    800:        entry = vm_map_first_entry(map);
                    801: 
                    802:        while (entry != vm_map_to_entry(map)) {
                    803:                if (entry->object.vm_object != VM_OBJECT_NULL) {
                    804:                        if (entry->is_sub_map) {
                    805:                                vm_map_t lmap = entry->object.sub_map;
                    806:                                mutex_lock(&lmap->s_lock);
                    807:                                vm_map_res_reference(lmap);
                    808:                                mutex_unlock(&lmap->s_lock);
                    809:                        } else {
                    810:                                vm_object_t object = entry->object.vm_object;
                    811:                                vm_object_lock(object);
                    812:                                /*
                    813:                                 * This call may iterate through the
                    814:                                 * shadow chain.
                    815:                                 */
                    816:                                vm_object_res_reference(object);
                    817:                                vm_object_unlock(object);
                    818:                        }
                    819:                }
                    820:                entry = entry->vme_next;
                    821:        }
                    822:        assert(map->sw_state == MAP_SW_OUT);
                    823:        map->sw_state = MAP_SW_IN;
                    824: }
                    825: 
                    826: void vm_map_swapout(vm_map_t map)
                    827: {
                    828:        register vm_map_entry_t entry;
                    829:        
                    830:        /*
                    831:         * Map is locked
                    832:         * First deal with various races.
                    833:         * If we raced with a swapin and lost, the residence count
                    834:         * will have been incremented to 1, and we simply return.
                    835:         */
                    836:        mutex_lock(&map->s_lock);
                    837:        if (map->res_count != 0) {
                    838:                mutex_unlock(&map->s_lock);
                    839:                return;
                    840:        }
                    841:        mutex_unlock(&map->s_lock);
                    842: 
                    843:        /*
                    844:         * There are no intermediate states of a map going out or
                    845:         * coming in, since the map is locked during the transition.
                    846:         */
                    847:        assert(map->sw_state == MAP_SW_IN);
                    848: 
                    849:        if (!vm_map_swap_enable)
                    850:                return;
                    851: 
                    852:        /*
                    853:         * We now operate upon each map entry.  If the entry is a sub- 
                    854:         * or share-map, we call vm_map_res_deallocate upon it.
                    855:         * If the entry is an object, we call vm_object_res_deallocate
                    856:         * (this may iterate through the shadow chain).
                    857:         * Note that we hold the map locked the entire time,
                    858:         * even if we get back here via a recursive call in
                    859:         * vm_map_res_deallocate.
                    860:         */
                    861:        entry = vm_map_first_entry(map);
                    862: 
                    863:        while (entry != vm_map_to_entry(map)) {
                    864:                if (entry->object.vm_object != VM_OBJECT_NULL) {
                    865:                        if (entry->is_sub_map) {
                    866:                                vm_map_t lmap = entry->object.sub_map;
                    867:                                mutex_lock(&lmap->s_lock);
                    868:                                vm_map_res_deallocate(lmap);
                    869:                                mutex_unlock(&lmap->s_lock);
                    870:                        } else {
                    871:                                vm_object_t object = entry->object.vm_object;
                    872:                                vm_object_lock(object);
                    873:                                /*
                    874:                                 * This call may take a long time, 
                    875:                                 * since it could actively push 
                    876:                                 * out pages (if we implement it 
                    877:                                 * that way).
                    878:                                 */
                    879:                                vm_object_res_deallocate(object);
                    880:                                vm_object_unlock(object);
                    881:                        }
                    882:                }
                    883:                entry = entry->vme_next;
                    884:        }
                    885:        assert(map->sw_state == MAP_SW_IN);
                    886:        map->sw_state = MAP_SW_OUT;
                    887: }
                    888: 
                    889: #endif /* TASK_SWAPPER */
                    890: 
                    891: 
                    892: /*
                    893:  *     SAVE_HINT:
                    894:  *
                    895:  *     Saves the specified entry as the hint for
                    896:  *     future lookups.  Performs necessary interlocks.
                    897:  */
                    898: #define        SAVE_HINT(map,value) \
                    899:                mutex_lock(&(map)->s_lock); \
                    900:                (map)->hint = (value); \
                    901:                mutex_unlock(&(map)->s_lock);
                    902: 
                    903: /*
                    904:  *     vm_map_lookup_entry:    [ internal use only ]
                    905:  *
                    906:  *     Finds the map entry containing (or
                    907:  *     immediately preceding) the specified address
                    908:  *     in the given map; the entry is returned
                    909:  *     in the "entry" parameter.  The boolean
                    910:  *     result indicates whether the address is
                    911:  *     actually contained in the map.
                    912:  */
                    913: boolean_t
                    914: vm_map_lookup_entry(
                    915:        register vm_map_t       map,
                    916:        register vm_offset_t    address,
                    917:        vm_map_entry_t          *entry)         /* OUT */
                    918: {
                    919:        register vm_map_entry_t         cur;
                    920:        register vm_map_entry_t         last;
                    921: 
                    922:        /*
                    923:         *      Start looking either from the head of the
                    924:         *      list, or from the hint.
                    925:         */
                    926: 
                    927:        mutex_lock(&map->s_lock);
                    928:        cur = map->hint;
                    929:        mutex_unlock(&map->s_lock);
                    930: 
                    931:        if (cur == vm_map_to_entry(map))
                    932:                cur = cur->vme_next;
                    933: 
                    934:        if (address >= cur->vme_start) {
                    935:                /*
                    936:                 *      Go from hint to end of list.
                    937:                 *
                    938:                 *      But first, make a quick check to see if
                    939:                 *      we are already looking at the entry we
                    940:                 *      want (which is usually the case).
                    941:                 *      Note also that we don't need to save the hint
                    942:                 *      here... it is the same hint (unless we are
                    943:                 *      at the header, in which case the hint didn't
                    944:                 *      buy us anything anyway).
                    945:                 */
                    946:                last = vm_map_to_entry(map);
                    947:                if ((cur != last) && (cur->vme_end > address)) {
                    948:                        *entry = cur;
                    949:                        return(TRUE);
                    950:                }
                    951:        }
                    952:        else {
                    953:                /*
                    954:                 *      Go from start to hint, *inclusively*
                    955:                 */
                    956:                last = cur->vme_next;
                    957:                cur = vm_map_first_entry(map);
                    958:        }
                    959: 
                    960:        /*
                    961:         *      Search linearly
                    962:         */
                    963: 
                    964:        while (cur != last) {
                    965:                if (cur->vme_end > address) {
                    966:                        if (address >= cur->vme_start) {
                    967:                                /*
                    968:                                 *      Save this lookup for future
                    969:                                 *      hints, and return
                    970:                                 */
                    971: 
                    972:                                *entry = cur;
                    973:                                SAVE_HINT(map, cur);
                    974:                                return(TRUE);
                    975:                        }
                    976:                        break;
                    977:                }
                    978:                cur = cur->vme_next;
                    979:        }
                    980:        *entry = cur->vme_prev;
                    981:        SAVE_HINT(map, *entry);
                    982:        return(FALSE);
                    983: }
                    984: 
                    985: /*
                    986:  *     Routine:        vm_map_find_space
                    987:  *     Purpose:
                    988:  *             Allocate a range in the specified virtual address map,
                    989:  *             returning the entry allocated for that range.
                    990:  *             Used by kmem_alloc, etc.
                    991:  *
                    992:  *             The map must be NOT be locked. It will be returned locked
                    993:  *             on KERN_SUCCESS, unlocked on failure.
                    994:  *
                    995:  *             If an entry is allocated, the object/offset fields
                    996:  *             are initialized to zero.
                    997:  */
                    998: kern_return_t
                    999: vm_map_find_space(
                   1000:        register vm_map_t       map,
                   1001:        vm_offset_t             *address,       /* OUT */
                   1002:        vm_size_t               size,
                   1003:        vm_offset_t             mask,
                   1004:        vm_map_entry_t          *o_entry)       /* OUT */
                   1005: {
                   1006:        register vm_map_entry_t entry, new_entry;
                   1007:        register vm_offset_t    start;
                   1008:        register vm_offset_t    end;
                   1009: 
                   1010:        new_entry = vm_map_entry_create(map);
                   1011: 
                   1012:        /*
                   1013:         *      Look for the first possible address; if there's already
                   1014:         *      something at this address, we have to start after it.
                   1015:         */
                   1016: 
                   1017:        vm_map_lock(map);
                   1018: 
                   1019:        assert(first_free_is_valid(map));
                   1020:        if ((entry = map->first_free) == vm_map_to_entry(map))
                   1021:                start = map->min_offset;
                   1022:        else
                   1023:                start = entry->vme_end;
                   1024: 
                   1025:        /*
                   1026:         *      In any case, the "entry" always precedes
                   1027:         *      the proposed new region throughout the loop:
                   1028:         */
                   1029: 
                   1030:        while (TRUE) {
                   1031:                register vm_map_entry_t next;
                   1032: 
                   1033:                /*
                   1034:                 *      Find the end of the proposed new region.
                   1035:                 *      Be sure we didn't go beyond the end, or
                   1036:                 *      wrap around the address.
                   1037:                 */
                   1038: 
                   1039:                end = ((start + mask) & ~mask);
                   1040:                if (end < start) {
                   1041:                        vm_map_entry_dispose(map, new_entry);
                   1042:                        vm_map_unlock(map);
                   1043:                        return(KERN_NO_SPACE);
                   1044:                }
                   1045:                start = end;
                   1046:                end += size;
                   1047: 
                   1048:                if ((end > map->max_offset) || (end < start)) {
                   1049:                        vm_map_entry_dispose(map, new_entry);
                   1050:                        vm_map_unlock(map);
                   1051:                        return(KERN_NO_SPACE);
                   1052:                }
                   1053: 
                   1054:                /*
                   1055:                 *      If there are no more entries, we must win.
                   1056:                 */
                   1057: 
                   1058:                next = entry->vme_next;
                   1059:                if (next == vm_map_to_entry(map))
                   1060:                        break;
                   1061: 
                   1062:                /*
                   1063:                 *      If there is another entry, it must be
                   1064:                 *      after the end of the potential new region.
                   1065:                 */
                   1066: 
                   1067:                if (next->vme_start >= end)
                   1068:                        break;
                   1069: 
                   1070:                /*
                   1071:                 *      Didn't fit -- move to the next entry.
                   1072:                 */
                   1073: 
                   1074:                entry = next;
                   1075:                start = entry->vme_end;
                   1076:        }
                   1077: 
                   1078:        /*
                   1079:         *      At this point,
                   1080:         *              "start" and "end" should define the endpoints of the
                   1081:         *                      available new range, and
                   1082:         *              "entry" should refer to the region before the new
                   1083:         *                      range, and
                   1084:         *
                   1085:         *              the map should be locked.
                   1086:         */
                   1087: 
                   1088:        *address = start;
                   1089: 
                   1090:        new_entry->vme_start = start;
                   1091:        new_entry->vme_end = end;
                   1092:        assert(page_aligned(new_entry->vme_start));
                   1093:        assert(page_aligned(new_entry->vme_end));
                   1094: 
                   1095:        new_entry->is_shared = FALSE;
                   1096:        new_entry->is_sub_map = FALSE;
                   1097:        new_entry->object.vm_object = VM_OBJECT_NULL;
                   1098:        new_entry->offset = (vm_offset_t) 0;
                   1099: 
                   1100:        new_entry->needs_copy = FALSE;
                   1101: 
                   1102:        new_entry->inheritance = VM_INHERIT_DEFAULT;
                   1103:        new_entry->protection = VM_PROT_DEFAULT;
                   1104:        new_entry->max_protection = VM_PROT_ALL;
                   1105:        new_entry->behavior = VM_BEHAVIOR_DEFAULT;
                   1106:        new_entry->wired_count = 0;
                   1107:        new_entry->user_wired_count = 0;
                   1108: 
                   1109:        new_entry->in_transition = FALSE;
                   1110:        new_entry->needs_wakeup = FALSE;
                   1111: 
                   1112:        /*
                   1113:         *      Insert the new entry into the list
                   1114:         */
                   1115: 
                   1116:        vm_map_entry_link(map, entry, new_entry);
                   1117: 
                   1118:        map->size += size;
                   1119: 
                   1120:        /*
                   1121:         *      Update the lookup hint
                   1122:         */
                   1123:        SAVE_HINT(map, new_entry);
                   1124: 
                   1125:        *o_entry = new_entry;
                   1126:        return(KERN_SUCCESS);
                   1127: }
                   1128: 
                   1129: int vm_map_pmap_enter_print = FALSE;
                   1130: int vm_map_pmap_enter_enable = FALSE;
                   1131: 
                   1132: /*
                   1133:  *     Routine:        vm_map_pmap_enter
                   1134:  *
                   1135:  *     Description:
                   1136:  *             Force pages from the specified object to be entered into
                   1137:  *             the pmap at the specified address if they are present.
                   1138:  *             As soon as a page not found in the object the scan ends.
                   1139:  *
                   1140:  *     Returns:
                   1141:  *             Nothing.  
                   1142:  *
                   1143:  *     In/out conditions:
                   1144:  *             The source map should not be locked on entry.
                   1145:  */
                   1146: void
                   1147: vm_map_pmap_enter(
                   1148:        vm_map_t                map,
                   1149:        register vm_offset_t    addr,
                   1150:        register vm_offset_t    end_addr,
                   1151:        register vm_object_t    object,
                   1152:        vm_offset_t             offset,
                   1153:        vm_prot_t               protection)
                   1154: {
                   1155:        while (addr < end_addr) {
                   1156:                register vm_page_t      m;
                   1157: 
                   1158:                vm_object_lock(object);
                   1159:                vm_object_paging_begin(object);
                   1160: 
                   1161:                m = vm_page_lookup(object, offset);
                   1162:                if (m == VM_PAGE_NULL || m->busy ||
                   1163:                    (m->unusual && ( m->error || m->restart || m->absent ||
                   1164:                                    protection & m->page_lock))) {
                   1165: 
                   1166:                        vm_object_paging_end(object);
                   1167:                        vm_object_unlock(object);
                   1168:                        return;
                   1169:                }
                   1170: 
                   1171:                assert(!m->fictitious); /* XXX is this possible ??? */
                   1172: 
                   1173:                if (vm_map_pmap_enter_print) {
                   1174:                        printf("vm_map_pmap_enter:");
                   1175:                        printf("map: %x, addr: %x, object: %x, offset: %x\n",
                   1176:                                map, addr, object, offset);
                   1177:                }
                   1178: 
                   1179:                m->busy = TRUE;
                   1180:                vm_object_unlock(object);
                   1181: 
                   1182:                PMAP_ENTER(map->pmap, addr, m,
                   1183:                           protection, FALSE);
                   1184: 
                   1185:                vm_object_lock(object);
                   1186:                PAGE_WAKEUP_DONE(m);
                   1187:                vm_page_lock_queues();
                   1188:                if (!m->active && !m->inactive)
                   1189:                    vm_page_activate(m);
                   1190:                vm_page_unlock_queues();
                   1191:                vm_object_paging_end(object);
                   1192:                vm_object_unlock(object);
                   1193: 
                   1194:                offset += PAGE_SIZE;
                   1195:                addr += PAGE_SIZE;
                   1196:        }
                   1197: }
                   1198: 
                   1199: /*
                   1200:  *     Routine:        vm_map_enter
                   1201:  *
                   1202:  *     Description:
                   1203:  *             Allocate a range in the specified virtual address map.
                   1204:  *             The resulting range will refer to memory defined by
                   1205:  *             the given memory object and offset into that object.
                   1206:  *
                   1207:  *             Arguments are as defined in the vm_map call.
                   1208:  */
                   1209: kern_return_t
                   1210: vm_map_enter(
                   1211:        register vm_map_t       map,
                   1212:        vm_offset_t             *address,       /* IN/OUT */
                   1213:        vm_size_t               size,
                   1214:        vm_offset_t             mask,
                   1215:        int                     flags,
                   1216:        vm_object_t             object,
                   1217:        vm_offset_t             offset,
                   1218:        boolean_t               needs_copy,
                   1219:        vm_prot_t               cur_protection,
                   1220:        vm_prot_t               max_protection,
                   1221:        vm_inherit_t            inheritance)
                   1222: {
                   1223:        vm_map_entry_t          entry;
                   1224:        register vm_offset_t    start;
                   1225:        register vm_offset_t    end;
                   1226:        kern_return_t           result = KERN_SUCCESS;
                   1227: 
                   1228:        boolean_t               anywhere = VM_FLAGS_ANYWHERE & flags;
                   1229:        char                    alias;
                   1230: 
                   1231:        VM_GET_FLAGS_ALIAS(flags, alias);
                   1232: 
                   1233: #define        RETURN(value)   { result = value; goto BailOut; }
                   1234: 
                   1235:        assert(page_aligned(*address));
                   1236:        assert(page_aligned(size));
                   1237:  StartAgain: ;
                   1238: 
                   1239:        start = *address;
                   1240: 
                   1241:        if (anywhere) {
                   1242:                vm_map_lock(map);
                   1243: 
                   1244:                /*
                   1245:                 *      Calculate the first possible address.
                   1246:                 */
                   1247: 
                   1248:                if (start < map->min_offset)
                   1249:                        start = map->min_offset;
                   1250:                if (start > map->max_offset)
                   1251:                        RETURN(KERN_NO_SPACE);
                   1252: 
                   1253:                /*
                   1254:                 *      Look for the first possible address;
                   1255:                 *      if there's already something at this
                   1256:                 *      address, we have to start after it.
                   1257:                 */
                   1258: 
                   1259:                assert(first_free_is_valid(map));
                   1260:                if (start == map->min_offset) {
                   1261:                        if ((entry = map->first_free) != vm_map_to_entry(map))
                   1262:                                start = entry->vme_end;
                   1263:                } else {
                   1264:                        vm_map_entry_t  tmp_entry;
                   1265:                        if (vm_map_lookup_entry(map, start, &tmp_entry))
                   1266:                                start = tmp_entry->vme_end;
                   1267:                        entry = tmp_entry;
                   1268:                }
                   1269: 
                   1270:                /*
                   1271:                 *      In any case, the "entry" always precedes
                   1272:                 *      the proposed new region throughout the
                   1273:                 *      loop:
                   1274:                 */
                   1275: 
                   1276:                while (TRUE) {
                   1277:                        register vm_map_entry_t next;
                   1278: 
                   1279:                        /*
                   1280:                         *      Find the end of the proposed new region.
                   1281:                         *      Be sure we didn't go beyond the end, or
                   1282:                         *      wrap around the address.
                   1283:                         */
                   1284: 
                   1285:                        end = ((start + mask) & ~mask);
                   1286:                        if (end < start)
                   1287:                                RETURN(KERN_NO_SPACE);
                   1288:                        start = end;
                   1289:                        end += size;
                   1290: 
                   1291:                        if ((end > map->max_offset) || (end < start)) {
                   1292:                                if (map->wait_for_space) {
                   1293:                                        if (size <= (map->max_offset -
                   1294:                                                     map->min_offset)) {
                   1295:                                                assert_wait((event_t)map,
                   1296:                                                            THREAD_ABORTSAFE);
                   1297:                                                vm_map_unlock(map);
                   1298:                                                thread_block((void (*)(void))0);
                   1299:                                                goto StartAgain;
                   1300:                                        }
                   1301:                                }
                   1302:                                RETURN(KERN_NO_SPACE);
                   1303:                        }
                   1304: 
                   1305:                        /*
                   1306:                         *      If there are no more entries, we must win.
                   1307:                         */
                   1308: 
                   1309:                        next = entry->vme_next;
                   1310:                        if (next == vm_map_to_entry(map))
                   1311:                                break;
                   1312: 
                   1313:                        /*
                   1314:                         *      If there is another entry, it must be
                   1315:                         *      after the end of the potential new region.
                   1316:                         */
                   1317: 
                   1318:                        if (next->vme_start >= end)
                   1319:                                break;
                   1320: 
                   1321:                        /*
                   1322:                         *      Didn't fit -- move to the next entry.
                   1323:                         */
                   1324: 
                   1325:                        entry = next;
                   1326:                        start = entry->vme_end;
                   1327:                }
                   1328:                *address = start;
                   1329:        } else {
                   1330:                vm_map_entry_t          temp_entry;
                   1331: 
                   1332:                /*
                   1333:                 *      Verify that:
                   1334:                 *              the address doesn't itself violate
                   1335:                 *              the mask requirement.
                   1336:                 */
                   1337: 
                   1338:                vm_map_lock(map);
                   1339:                if ((start & mask) != 0)
                   1340:                        RETURN(KERN_NO_SPACE);
                   1341: 
                   1342:                /*
                   1343:                 *      ...     the address is within bounds
                   1344:                 */
                   1345: 
                   1346:                end = start + size;
                   1347: 
                   1348:                if ((start < map->min_offset) ||
                   1349:                    (end > map->max_offset) ||
                   1350:                    (start >= end)) {
                   1351:                        RETURN(KERN_INVALID_ADDRESS);
                   1352:                }
                   1353: 
                   1354:                /*
                   1355:                 *      ...     the starting address isn't allocated
                   1356:                 */
                   1357: 
                   1358:                if (vm_map_lookup_entry(map, start, &temp_entry))
                   1359:                        RETURN(KERN_NO_SPACE);
                   1360: 
                   1361:                entry = temp_entry;
                   1362: 
                   1363:                /*
                   1364:                 *      ...     the next region doesn't overlap the
                   1365:                 *              end point.
                   1366:                 */
                   1367: 
                   1368:                if ((entry->vme_next != vm_map_to_entry(map)) &&
                   1369:                    (entry->vme_next->vme_start < end))
                   1370:                        RETURN(KERN_NO_SPACE);
                   1371:        }
                   1372: 
                   1373:        /*
                   1374:         *      At this point,
                   1375:         *              "start" and "end" should define the endpoints of the
                   1376:         *                      available new range, and
                   1377:         *              "entry" should refer to the region before the new
                   1378:         *                      range, and
                   1379:         *
                   1380:         *              the map should be locked.
                   1381:         */
                   1382: 
                   1383:        /*
                   1384:         *      See whether we can avoid creating a new entry (and object) by
                   1385:         *      extending one of our neighbors.  [So far, we only attempt to
                   1386:         *      extend from below.]
                   1387:         */
                   1388: 
                   1389:        if ((object == VM_OBJECT_NULL) &&
                   1390:            (entry != vm_map_to_entry(map)) &&
                   1391:            (entry->vme_end == start) &&
                   1392:            (!entry->is_shared) &&
                   1393:            (!entry->is_sub_map) &&
                   1394:            (entry->alias == alias) &&
                   1395:            (entry->inheritance == inheritance) &&
                   1396:            (entry->protection == cur_protection) &&
                   1397:            (entry->max_protection == max_protection) &&
                   1398:            (entry->behavior == VM_BEHAVIOR_DEFAULT) &&
                   1399:            (entry->in_transition == 0) &&
                   1400:            (entry->wired_count == 0)) { /* implies user_wired_count == 0 */
                   1401:                if (vm_object_coalesce(entry->object.vm_object,
                   1402:                                VM_OBJECT_NULL,
                   1403:                                entry->offset,
                   1404:                                (vm_offset_t) 0,
                   1405:                                (vm_size_t)(entry->vme_end - entry->vme_start),
                   1406:                                (vm_size_t)(end - entry->vme_end))) {
                   1407: 
                   1408:                        /*
                   1409:                         *      Coalesced the two objects - can extend
                   1410:                         *      the previous map entry to include the
                   1411:                         *      new range.
                   1412:                         */
                   1413:                        map->size += (end - entry->vme_end);
                   1414:                        entry->vme_end = end;
                   1415:                        UPDATE_FIRST_FREE(map, map->first_free);
                   1416:                        RETURN(KERN_SUCCESS);
                   1417:                }
                   1418:        }
                   1419: 
                   1420:        /*
                   1421:         *      Create a new entry
                   1422:         */
                   1423: 
                   1424:        { /**/
                   1425:        register vm_map_entry_t new_entry;
                   1426: 
                   1427:        new_entry = vm_map_entry_insert(map, entry, start, end, object,
                   1428:                                        offset, needs_copy, FALSE, FALSE,
                   1429:                                        cur_protection, max_protection,
                   1430:                                        VM_BEHAVIOR_DEFAULT, inheritance, 0);
                   1431:        new_entry->alias = alias;
                   1432:        vm_map_unlock(map);
                   1433: 
                   1434:        /*      Wire down the new entry if the user
                   1435:         *      requested all new map entries be wired.
                   1436:         */
                   1437:        if (map->wiring_required) {
                   1438:                result = vm_map_wire(map, start, end,
                   1439:                                    new_entry->protection, TRUE);
                   1440:                return(result);
                   1441:        }
                   1442: 
                   1443:        if ((object != VM_OBJECT_NULL) &&
                   1444:            (vm_map_pmap_enter_enable) &&
                   1445:            (!anywhere)  &&
                   1446:            (!needs_copy) && 
                   1447:            (size < (128*1024))) {
                   1448:                vm_map_pmap_enter(map, start, end, 
                   1449:                                  object, offset, cur_protection);
                   1450:        }
                   1451: 
                   1452:        return(result);
                   1453:        } /**/
                   1454: 
                   1455:  BailOut: ;
                   1456:        vm_map_unlock(map);
                   1457:        return(result);
                   1458: 
                   1459: #undef RETURN
                   1460: }
                   1461: 
                   1462: /*
                   1463:  *     vm_map_clip_start:      [ internal use only ]
                   1464:  *
                   1465:  *     Asserts that the given entry begins at or after
                   1466:  *     the specified address; if necessary,
                   1467:  *     it splits the entry into two.
                   1468:  */
                   1469: #define vm_map_clip_start(map, entry, startaddr)                       \
                   1470: MACRO_BEGIN                                                            \
                   1471:        vm_map_t VMCS_map;                                              \
                   1472:        vm_map_entry_t VMCS_entry;                                      \
                   1473:        vm_offset_t VMCS_startaddr;                                     \
                   1474:        VMCS_map = (map);                                               \
                   1475:        VMCS_entry = (entry);                                           \
                   1476:        VMCS_startaddr = (startaddr);                                   \
                   1477:        if (VMCS_startaddr > VMCS_entry->vme_start)                     \
                   1478:                _vm_map_clip_start(&VMCS_map->hdr,VMCS_entry,VMCS_startaddr);\
                   1479:        UPDATE_FIRST_FREE(VMCS_map, VMCS_map->first_free);              \
                   1480: MACRO_END
                   1481: 
                   1482: #define vm_map_copy_clip_start(copy, entry, startaddr) \
                   1483:        MACRO_BEGIN \
                   1484:        if ((startaddr) > (entry)->vme_start) \
                   1485:                _vm_map_clip_start(&(copy)->cpy_hdr,(entry),(startaddr)); \
                   1486:        MACRO_END
                   1487: 
                   1488: /*
                   1489:  *     This routine is called only when it is known that
                   1490:  *     the entry must be split.
                   1491:  */
                   1492: void
                   1493: _vm_map_clip_start(
                   1494:        register struct vm_map_header   *map_header,
                   1495:        register vm_map_entry_t         entry,
                   1496:        register vm_offset_t            start)
                   1497: {
                   1498:        register vm_map_entry_t new_entry;
                   1499: 
                   1500:        /*
                   1501:         *      Split off the front portion --
                   1502:         *      note that we must insert the new
                   1503:         *      entry BEFORE this one, so that
                   1504:         *      this entry has the specified starting
                   1505:         *      address.
                   1506:         */
                   1507: 
                   1508:        new_entry = _vm_map_entry_create(map_header);
                   1509:        vm_map_entry_copy_full(new_entry, entry);
                   1510: 
                   1511:        new_entry->vme_end = start;
                   1512:        entry->offset += (start - entry->vme_start);
                   1513:        entry->vme_start = start;
                   1514: 
                   1515:        _vm_map_entry_link(map_header, entry->vme_prev, new_entry);
                   1516: 
                   1517:        if (entry->is_sub_map)
                   1518:                vm_map_reference(new_entry->object.sub_map);
                   1519:        else
                   1520:                vm_object_reference(new_entry->object.vm_object);
                   1521: }
                   1522: 
                   1523: /*
                   1524:  *     vm_map_clip_end:        [ internal use only ]
                   1525:  *
                   1526:  *     Asserts that the given entry ends at or before
                   1527:  *     the specified address; if necessary,
                   1528:  *     it splits the entry into two.
                   1529:  */
                   1530: #define vm_map_clip_end(map, entry, endaddr)                           \
                   1531: MACRO_BEGIN                                                            \
                   1532:        vm_map_t VMCE_map;                                              \
                   1533:        vm_map_entry_t VMCE_entry;                                      \
                   1534:        vm_offset_t VMCE_endaddr;                                       \
                   1535:        VMCE_map = (map);                                               \
                   1536:        VMCE_entry = (entry);                                           \
                   1537:        VMCE_endaddr = (endaddr);                                       \
                   1538:        if (VMCE_endaddr < VMCE_entry->vme_end)                         \
                   1539:                _vm_map_clip_end(&VMCE_map->hdr,VMCE_entry,VMCE_endaddr); \
                   1540:        UPDATE_FIRST_FREE(VMCE_map, VMCE_map->first_free);              \
                   1541: MACRO_END
                   1542: 
                   1543: #define vm_map_copy_clip_end(copy, entry, endaddr) \
                   1544:        MACRO_BEGIN \
                   1545:        if ((endaddr) < (entry)->vme_end) \
                   1546:                _vm_map_clip_end(&(copy)->cpy_hdr,(entry),(endaddr)); \
                   1547:        MACRO_END
                   1548: 
                   1549: /*
                   1550:  *     This routine is called only when it is known that
                   1551:  *     the entry must be split.
                   1552:  */
                   1553: void
                   1554: _vm_map_clip_end(
                   1555:        register struct vm_map_header   *map_header,
                   1556:        register vm_map_entry_t         entry,
                   1557:        register vm_offset_t            end)
                   1558: {
                   1559:        register vm_map_entry_t new_entry;
                   1560: 
                   1561:        /*
                   1562:         *      Create a new entry and insert it
                   1563:         *      AFTER the specified entry
                   1564:         */
                   1565: 
                   1566:        new_entry = _vm_map_entry_create(map_header);
                   1567:        vm_map_entry_copy_full(new_entry, entry);
                   1568: 
                   1569:        new_entry->vme_start = entry->vme_end = end;
                   1570:        new_entry->offset += (end - entry->vme_start);
                   1571: 
                   1572:        _vm_map_entry_link(map_header, entry, new_entry);
                   1573: 
                   1574:        if (entry->is_sub_map)
                   1575:                vm_map_reference(new_entry->object.sub_map);
                   1576:        else
                   1577:                vm_object_reference(new_entry->object.vm_object);
                   1578: }
                   1579: 
                   1580: 
                   1581: /*
                   1582:  *     VM_MAP_RANGE_CHECK:     [ internal use only ]
                   1583:  *
                   1584:  *     Asserts that the starting and ending region
                   1585:  *     addresses fall within the valid range of the map.
                   1586:  */
                   1587: #define        VM_MAP_RANGE_CHECK(map, start, end)             \
                   1588:                {                                       \
                   1589:                if (start < vm_map_min(map))            \
                   1590:                        start = vm_map_min(map);        \
                   1591:                if (end > vm_map_max(map))              \
                   1592:                        end = vm_map_max(map);          \
                   1593:                if (start > end)                        \
                   1594:                        start = end;                    \
                   1595:                }
                   1596: 
                   1597: /*
                   1598:  *     vm_map_range_check:     [ internal use only ]
                   1599:  *     
                   1600:  *     Check that the region defined by the specified start and
                   1601:  *     end addresses are wholly contained within a single map
                   1602:  *     entry or set of adjacent map entries of the spacified map,
                   1603:  *     i.e. the specified region contains no unmapped space.
                   1604:  *     If any or all of the region is unmapped, FALSE is returned.
                   1605:  *     Otherwise, TRUE is returned and if the output argument 'entry'
                   1606:  *     is not NULL it points to the map entry containing the start
                   1607:  *     of the region.
                   1608:  *
                   1609:  *     The map is locked for reading on entry and is left locked.
                   1610:  */
                   1611: boolean_t
                   1612: vm_map_range_check(
                   1613:        register vm_map_t       map,
                   1614:        register vm_offset_t    start,
                   1615:        register vm_offset_t    end,
                   1616:        vm_map_entry_t          *entry)
                   1617: {
                   1618:        vm_map_entry_t          cur;
                   1619:        register vm_offset_t    prev;
                   1620: 
                   1621:        /*
                   1622:         *      Basic sanity checks first
                   1623:         */
                   1624:        if (start < vm_map_min(map) || end > vm_map_max(map) || start > end)
                   1625:                return (FALSE);
                   1626: 
                   1627:        /*
                   1628:         *      Check first if the region starts within a valid
                   1629:         *      mapping for the map.
                   1630:         */
                   1631:        if (!vm_map_lookup_entry(map, start, &cur))
                   1632:                return (FALSE);
                   1633: 
                   1634:        /*
                   1635:         *      Optimize for the case that the region is contained 
                   1636:         *      in a single map entry.
                   1637:         */
                   1638:        if (entry != (vm_map_entry_t *) NULL)
                   1639:                *entry = cur;
                   1640:        if (end <= cur->vme_end)
                   1641:                return (TRUE);
                   1642: 
                   1643:        /*
                   1644:         *      If the region is not wholly contained within a
                   1645:         *      single entry, walk the entries looking for holes.
                   1646:         */
                   1647:        prev = cur->vme_end;
                   1648:        cur = cur->vme_next;
                   1649:        while ((cur != vm_map_to_entry(map)) && (prev == cur->vme_start)) {
                   1650:                if (end <= cur->vme_end)
                   1651:                        return (TRUE);
                   1652:                prev = cur->vme_end;
                   1653:                cur = cur->vme_next;
                   1654:        }
                   1655:        return (FALSE);
                   1656: }
                   1657: 
                   1658: /*
                   1659:  *     vm_map_submap:          [ kernel use only ]
                   1660:  *
                   1661:  *     Mark the given range as handled by a subordinate map.
                   1662:  *
                   1663:  *     This range must have been created with vm_map_find using
                   1664:  *     the vm_submap_object, and no other operations may have been
                   1665:  *     performed on this range prior to calling vm_map_submap.
                   1666:  *
                   1667:  *     Only a limited number of operations can be performed
                   1668:  *     within this rage after calling vm_map_submap:
                   1669:  *             vm_fault
                   1670:  *     [Don't try vm_map_copyin!]
                   1671:  *
                   1672:  *     To remove a submapping, one must first remove the
                   1673:  *     range from the superior map, and then destroy the
                   1674:  *     submap (if desired).  [Better yet, don't try it.]
                   1675:  */
                   1676: kern_return_t
                   1677: vm_map_submap(
                   1678:        register vm_map_t       map,
                   1679:        register vm_offset_t    start,
                   1680:        register vm_offset_t    end,
                   1681:        vm_map_t                submap,
                   1682:        vm_offset_t             offset)
                   1683: {
                   1684:        vm_map_entry_t          entry;
                   1685:        register kern_return_t  result = KERN_INVALID_ARGUMENT;
                   1686:        register vm_object_t    object;
                   1687: 
                   1688:        vm_map_lock(map);
                   1689: 
                   1690:        VM_MAP_RANGE_CHECK(map, start, end);
                   1691: 
                   1692:        if (vm_map_lookup_entry(map, start, &entry)) {
                   1693:                vm_map_clip_start(map, entry, start);
                   1694:        }
                   1695:         else
                   1696:                entry = entry->vme_next;
                   1697: 
                   1698:        vm_map_clip_end(map, entry, end);
                   1699: 
                   1700:        if ((entry->vme_start == start) && (entry->vme_end == end) &&
                   1701:            (!entry->is_sub_map) &&
                   1702:            ((object = entry->object.vm_object) == vm_submap_object) &&
                   1703:            (object->resident_page_count == 0) &&
                   1704:            (object->copy == VM_OBJECT_NULL) &&
                   1705:            (object->shadow == VM_OBJECT_NULL) &&
                   1706:            (!object->pager_created)) {
                   1707:                entry->offset = offset;
                   1708:                entry->object.vm_object = VM_OBJECT_NULL;
                   1709:                vm_object_deallocate(object);
                   1710:                entry->is_sub_map = TRUE;
                   1711:                vm_map_reference(entry->object.sub_map = submap);
                   1712:                result = KERN_SUCCESS;
                   1713:        }
                   1714:        vm_map_unlock(map);
                   1715: 
                   1716:        return(result);
                   1717: }
                   1718: 
                   1719: /*
                   1720:  *     vm_map_protect:
                   1721:  *
                   1722:  *     Sets the protection of the specified address
                   1723:  *     region in the target map.  If "set_max" is
                   1724:  *     specified, the maximum protection is to be set;
                   1725:  *     otherwise, only the current protection is affected.
                   1726:  */
                   1727: kern_return_t
                   1728: vm_map_protect(
                   1729:        register vm_map_t       map,
                   1730:        register vm_offset_t    start,
                   1731:        register vm_offset_t    end,
                   1732:        register vm_prot_t      new_prot,
                   1733:        register boolean_t      set_max)
                   1734: {
                   1735:        register vm_map_entry_t         current;
                   1736:        register vm_offset_t            prev;
                   1737:        vm_map_entry_t                  entry;
                   1738:        vm_prot_t                       new_max;
                   1739:        boolean_t                       clip;
                   1740: 
                   1741:        XPR(XPR_VM_MAP,
                   1742:                "vm_map_protect, 0x%X start 0x%X end 0x%X, new 0x%X %d",
                   1743:                (integer_t)map, start, end, new_prot, set_max);
                   1744: 
                   1745:        vm_map_lock(map);
                   1746: 
                   1747:        /*
                   1748:         *      Lookup the entry.  If it doesn't start in a valid
                   1749:         *      entry, return an error.  Remember if we need to
                   1750:         *      clip the entry.  We don't do it here because we don't
                   1751:         *      want to make any changes until we've scanned the 
                   1752:         *      entire range below for address and protection
                   1753:         *      violations.
                   1754:         */
                   1755:        if (!(clip = vm_map_lookup_entry(map, start, &entry))) {
                   1756:                vm_map_unlock(map);
                   1757:                return(KERN_INVALID_ADDRESS);
                   1758:        }
                   1759: 
                   1760:        /*
                   1761:         *      Make a first pass to check for protection and address
                   1762:         *      violations.
                   1763:         */
                   1764: 
                   1765:        current = entry;
                   1766:        prev = current->vme_start;
                   1767:        while ((current != vm_map_to_entry(map)) &&
                   1768:               (current->vme_start < end)) {
                   1769: 
                   1770:                /*
                   1771:                 * If there is a hole, return an error.
                   1772:                 */
                   1773:                if (current->vme_start != prev) {
                   1774:                        vm_map_unlock(map);
                   1775:                        return(KERN_INVALID_ADDRESS);
                   1776:                }
                   1777: 
                   1778:                new_max = current->max_protection;
                   1779:                if(new_prot & VM_PROT_COPY) {
                   1780:                        new_max |= VM_PROT_WRITE;
                   1781:                }
                   1782:                if ((new_prot & new_max) != new_prot) {
                   1783:                        vm_map_unlock(map);
                   1784:                        return(KERN_PROTECTION_FAILURE);
                   1785:                }
                   1786: 
                   1787:                prev = current->vme_end;
                   1788:                current = current->vme_next;
                   1789:        }
                   1790:        if (end > prev) {
                   1791:                vm_map_unlock(map);
                   1792:                return(KERN_INVALID_ADDRESS);
                   1793:        }
                   1794: 
                   1795:        /*
                   1796:         *      Go back and fix up protections.
                   1797:         *      Clip to start here if the range starts within
                   1798:         *      the entry.
                   1799:         */
                   1800: 
                   1801:        current = entry;
                   1802:        if (clip) {
                   1803:                vm_map_clip_start(map, entry, start);
                   1804:        }
                   1805:        while ((current != vm_map_to_entry(map)) &&
                   1806:               (current->vme_start < end)) {
                   1807: 
                   1808:                vm_prot_t       old_prot;
                   1809: 
                   1810:                vm_map_clip_end(map, current, end);
                   1811: 
                   1812:                old_prot = current->protection;
                   1813: 
                   1814:                if(new_prot & VM_PROT_COPY) {
                   1815:                        /* caller is asking specifically to copy the      */
                   1816:                        /* mapped data, this implies that max protection  */
                   1817:                        /* will include write.  Caller must be prepared   */
                   1818:                        /* for loss of shared memory communication in the */
                   1819:                        /* target area after taking this step */
                   1820:                        current->needs_copy = TRUE;
                   1821:                        current->max_protection |= VM_PROT_WRITE;
                   1822:                }
                   1823: 
                   1824:                if (set_max)
                   1825:                        current->protection =
                   1826:                                (current->max_protection = new_prot) &
                   1827:                                        old_prot;
                   1828:                else
                   1829:                        current->protection = new_prot;
                   1830: 
                   1831:                /*
                   1832:                 *      Update physical map if necessary.
                   1833:                 *      If the request is to turn off write protection, 
                   1834:                 *      we won't do it for real (in pmap). This is because 
                   1835:                 *      it would cause copy-on-write to fail.  We've already 
                   1836:                 *      set, the new protection in the map, so if a 
                   1837:                 *      write-protect fault occurred, it will be fixed up 
                   1838:                 *      properly, COW or not.
                   1839:                 */
                   1840: 
                   1841:                if ((current->protection != old_prot) && !(current->protection & VM_PROT_WRITE)) {
                   1842:                        pmap_protect(map->pmap, current->vme_start,
                   1843:                                        current->vme_end,
                   1844:                                        current->protection);
                   1845:                }
                   1846:                current = current->vme_next;
                   1847:        }
                   1848: 
                   1849:        vm_map_unlock(map);
                   1850:        return(KERN_SUCCESS);
                   1851: }
                   1852: 
                   1853: 
                   1854: /*
                   1855:  *     vm_map_inherit:
                   1856:  *
                   1857:  *     Sets the inheritance of the specified address
                   1858:  *     range in the target map.  Inheritance
                   1859:  *     affects how the map will be shared with
                   1860:  *     child maps at the time of vm_map_fork.
                   1861:  */
                   1862: kern_return_t
                   1863: vm_map_inherit(
                   1864:        register vm_map_t       map,
                   1865:        register vm_offset_t    start,
                   1866:        register vm_offset_t    end,
                   1867:        register vm_inherit_t   new_inheritance)
                   1868: {
                   1869:        register vm_map_entry_t entry;
                   1870:        vm_map_entry_t  temp_entry;
                   1871: 
                   1872:        vm_map_lock(map);
                   1873: 
                   1874:        VM_MAP_RANGE_CHECK(map, start, end);
                   1875: 
                   1876:        if (vm_map_lookup_entry(map, start, &temp_entry)) {
                   1877:                entry = temp_entry;
                   1878:                vm_map_clip_start(map, entry, start);
                   1879:        }
                   1880:        else {
                   1881:                temp_entry = temp_entry->vme_next;
                   1882:                entry = temp_entry;
                   1883:        }
                   1884: 
                   1885:        /* first check entire range for submaps which can't support the */
                   1886:        /* given inheritance. */
                   1887:        while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
                   1888:                if(entry->is_sub_map) {
                   1889:                        if(new_inheritance == VM_INHERIT_COPY)
                   1890:                                return(KERN_INVALID_ARGUMENT);
                   1891:                }
                   1892: 
                   1893:                entry = entry->vme_next;
                   1894:        }
                   1895: 
                   1896:        entry = temp_entry;
                   1897: 
                   1898:        while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
                   1899:                vm_map_clip_end(map, entry, end);
                   1900: 
                   1901:                entry->inheritance = new_inheritance;
                   1902: 
                   1903:                entry = entry->vme_next;
                   1904:        }
                   1905: 
                   1906:        vm_map_unlock(map);
                   1907:        return(KERN_SUCCESS);
                   1908: }
                   1909: 
                   1910: /*
                   1911:  *     vm_map_wire:
                   1912:  *
                   1913:  *     Sets the pageability of the specified address range in the
                   1914:  *     target map as wired.  Regions specified as not pageable require
                   1915:  *     locked-down physical memory and physical page maps.  The
                   1916:  *     access_type variable indicates types of accesses that must not
                   1917:  *     generate page faults.  This is checked against protection of
                   1918:  *     memory being locked-down.
                   1919:  *
                   1920:  *     The map must not be locked, but a reference must remain to the
                   1921:  *     map throughout the call.
                   1922:  */
                   1923: kern_return_t
                   1924: vm_map_wire(
                   1925:        register vm_map_t       map,
                   1926:        register vm_offset_t    start,
                   1927:        register vm_offset_t    end,
                   1928:        register vm_prot_t      access_type,
                   1929:        boolean_t               user_wire)
                   1930: {
                   1931:        register vm_map_entry_t entry;
                   1932:        struct vm_map_entry     *first_entry, tmp_entry;
                   1933:        register vm_offset_t    s,e;
                   1934:        kern_return_t           rc;
                   1935:        boolean_t               need_wakeup;
                   1936:        unsigned int            last_timestamp;
                   1937:        vm_size_t               size;
                   1938: 
                   1939:        vm_map_lock(map);
                   1940:        last_timestamp = map->timestamp;
                   1941: 
                   1942:        VM_MAP_RANGE_CHECK(map, start, end);
                   1943:        assert(page_aligned(start));
                   1944:        assert(page_aligned(end));
                   1945: 
                   1946:        if (vm_map_lookup_entry(map, start, &first_entry)) {
                   1947:                entry = first_entry;
                   1948:                /* vm_map_clip_start will be done later. */
                   1949:        } else {
                   1950:                /* Start address is not in map */
                   1951:                vm_map_unlock(map);
                   1952:                return(KERN_INVALID_ADDRESS);
                   1953:        }
                   1954: 
                   1955:        s=start;
                   1956:        need_wakeup = FALSE;
                   1957:        while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
                   1958:                if(entry->is_sub_map) {
                   1959:                        vm_offset_t     sub_start;
                   1960:                        vm_offset_t     sub_end;
                   1961:                        vm_offset_t     local_end;
                   1962:                        
                   1963:                        if(entry->vme_start < start)
                   1964:                                sub_start = start;
                   1965:                        else
                   1966:                                sub_start = entry->vme_start;
                   1967:                        sub_start -= entry->vme_start;
                   1968:                        sub_start += entry->offset;
                   1969:                        
                   1970:                        if(entry->vme_end < end)
                   1971:                                sub_end = entry->vme_end;
                   1972:                        else
                   1973:                                sub_end = end;
                   1974:                        sub_end -= entry->vme_start;
                   1975:                        sub_end += entry->offset;
                   1976:                        local_end = entry->vme_end;
                   1977:                        vm_map_unlock(map);
                   1978:                        if (vm_map_wire(entry->object.sub_map, 
                   1979:                                                sub_start, sub_end,
                   1980:                                                 access_type, user_wire)
                   1981:                                                != KERN_SUCCESS) {
                   1982:                                vm_map_unwire(map, start, s, user_wire);
                   1983:                                return(KERN_FAILURE);
                   1984:                        }
                   1985:                        vm_map_lock(map);
                   1986:                        if (last_timestamp+1 != map->timestamp) {
                   1987:                        /*
                   1988:                         * Find the entry again.  It could have been clipped
                   1989:                         * after we unlocked the map.
                   1990:                         */
                   1991:                                if (!vm_map_lookup_entry(map, local_end,
                   1992:                                                         &first_entry))
                   1993:                                        panic("vm_map_wire: re-lookup failed");
                   1994: 
                   1995:                                entry = first_entry;
                   1996:                        } else
                   1997:                                entry = entry->vme_next;
                   1998: 
                   1999:                        last_timestamp = map->timestamp;
                   2000:                        continue;
                   2001:                }
                   2002: 
                   2003:                /*
                   2004:                 * If another thread is wiring/unwiring this entry then
                   2005:                 * block after informing other thread to wake us up.
                   2006:                 */
                   2007:                if (entry->in_transition) {
                   2008:                        /*
                   2009:                         * We have not clipped the entry.  Make sure that
                   2010:                         * the start address is in range so that the lookup
                   2011:                         * below will succeed.
                   2012:                         */
                   2013:                        s = entry->vme_start < start? start: entry->vme_start;
                   2014: 
                   2015:                        entry->needs_wakeup = TRUE;
                   2016: 
                   2017:                        /*
                   2018:                         * wake up anybody waiting on entries that we have
                   2019:                         * already wired.
                   2020:                         */
                   2021:                        if (need_wakeup) {
                   2022:                                vm_map_entry_wakeup(map);
                   2023:                                need_wakeup = FALSE;
                   2024:                        }
                   2025:                        /*
                   2026:                         * User wiring is interruptible
                   2027:                         */
                   2028:                        vm_map_entry_wait(map, 
                   2029:                                          (user_wire) ? THREAD_ABORTSAFE :
                   2030:                                                        THREAD_UNINT);
                   2031:                        if (user_wire && current_thread()->wait_result ==
                   2032:                                                        THREAD_INTERRUPTED) {
                   2033:                                /*
                   2034:                                 * undo the wirings we have done so far
                   2035:                                 * We do not clear the needs_wakeup flag,
                   2036:                                 * because we cannot tell if we were the
                   2037:                                 * only one waiting.
                   2038:                                 */
                   2039:                                vm_map_unwire(map, start, s, user_wire);
                   2040:                                return(KERN_FAILURE);
                   2041:                        }
                   2042: 
                   2043:                        vm_map_lock(map);
                   2044:                        /*
                   2045:                         * Cannot avoid a lookup here. reset timestamp.
                   2046:                         */
                   2047:                        last_timestamp = map->timestamp;
                   2048: 
                   2049:                        /*
                   2050:                         * The entry could have been clipped, look it up again.
                   2051:                         * Worse that can happen is, it may not exist anymore.
                   2052:                         */
                   2053:                        if (!vm_map_lookup_entry(map, s, &first_entry)) {
                   2054:                                if (!user_wire)
                   2055:                                        panic("vm_map_wire: re-lookup failed");
                   2056: 
                   2057:                                /*
                   2058:                                 * User: undo everything upto the previous
                   2059:                                 * entry.  let vm_map_unwire worry about
                   2060:                                 * checking the validity of the range.
                   2061:                                 */
                   2062:                                vm_map_unlock(map);
                   2063:                                vm_map_unwire(map, start, s, user_wire);
                   2064:                                return(KERN_FAILURE);
                   2065:                        }
                   2066:                        entry = first_entry;
                   2067:                        continue;
                   2068:                }
                   2069:                
                   2070:                /*
                   2071:                 * If this entry is already wired then increment
                   2072:                 * the appropriate wire reference count.
                   2073:                 */
                   2074:                if (entry->wired_count) {
                   2075:                        /* sanity check: wired_count is a short */
                   2076:                        if (entry->wired_count >= MAX_WIRE_COUNT)
                   2077:                                panic("vm_map_wire: too many wirings");
                   2078: 
                   2079:                        if (user_wire &&
                   2080:                            entry->user_wired_count >= MAX_WIRE_COUNT) {
                   2081:                                vm_map_unlock(map);
                   2082:                                vm_map_unwire(map, start,
                   2083:                                                entry->vme_start, user_wire);
                   2084:                                return(KERN_FAILURE);
                   2085:                        }
                   2086:                        /*
                   2087:                         * entry is already wired down, get our reference
                   2088:                         * after clipping to our range.
                   2089:                         */
                   2090:                        vm_map_clip_start(map, entry, start);
                   2091:                        vm_map_clip_end(map, entry, end);
                   2092:                        if (!user_wire || (entry->user_wired_count++ == 0))
                   2093:                                entry->wired_count++;
                   2094: 
                   2095:                        entry = entry->vme_next;
                   2096:                        continue;
                   2097:                }
                   2098: 
                   2099:                /*
                   2100:                 * Unwired entry
                   2101:                 */
                   2102: 
                   2103: 
                   2104:                /*
                   2105:                 * Perform actions of vm_map_lookup that need the write
                   2106:                 * lock on the map: create a shadow object for a
                   2107:                 * copy-on-write region, or an object for a zero-fill
                   2108:                 * region.
                   2109:                 */
                   2110:                size = entry->vme_end - entry->vme_start;
                   2111:                /*
                   2112:                 * If wiring a copy-on-write page, we need to copy it now
                   2113:                 * even if we're only (currently) requesting read access.
                   2114:                 * This is aggressive, but once it's wired we can't move it.
                   2115:                 */
                   2116:                if (entry->needs_copy) {
                   2117:                        vm_object_shadow(&entry->object.vm_object,
                   2118:                                         &entry->offset, size);
                   2119:                        entry->needs_copy = FALSE;
                   2120:                } else if (entry->object.vm_object == VM_OBJECT_NULL) {
                   2121:                        entry->object.vm_object = vm_object_allocate(size);
                   2122:                        entry->offset = (vm_offset_t)0;
                   2123:                }
                   2124: 
                   2125:                vm_map_clip_start(map, entry, start);
                   2126:                vm_map_clip_end(map, entry, end);
                   2127: 
                   2128:                s = entry->vme_start;
                   2129:                e = entry->vme_end;
                   2130: 
                   2131:                /*
                   2132:                 * Check for holes and protection mismatch.
                   2133:                 * Holes: Next entry should be contiguous unless this
                   2134:                 *        is the end of the region.
                   2135:                 * Protection: Access requested must be allowed, unless
                   2136:                 *      wiring is by protection class
                   2137:                 */
                   2138:                if ((((entry->vme_end < end) &&
                   2139:                     ((entry->vme_next == vm_map_to_entry(map)) ||
                   2140:                      (entry->vme_next->vme_start > entry->vme_end))) ||
                   2141:                     ((entry->protection & access_type) != access_type))) {
                   2142:                        /*
                   2143:                         * Found a hole or protection problem.
                   2144:                         * Unwire the region we wired so far.
                   2145:                         */
                   2146:                        if (start != entry->vme_start) {
                   2147:                                vm_map_unlock(map);
                   2148:                                vm_map_unwire(map, start, s, user_wire);
                   2149:                        } else {
                   2150:                                vm_map_unlock(map);
                   2151:                        }
                   2152:                        return((entry->protection&access_type) != access_type?
                   2153:                                KERN_PROTECTION_FAILURE: KERN_INVALID_ADDRESS);
                   2154:                }
                   2155: 
                   2156:                assert(entry->wired_count == 0 && entry->user_wired_count == 0);
                   2157: 
                   2158:                if (user_wire)
                   2159:                        entry->user_wired_count++;
                   2160:                entry->wired_count++;
                   2161: 
                   2162:                entry->in_transition = TRUE;
                   2163: 
                   2164:                /*
                   2165:                 * This entry might get split once we unlock the map.
                   2166:                 * In vm_fault_wire(), we need the current range as
                   2167:                 * defined by this entry.  In order for this to work
                   2168:                 * along with a simultaneous clip operation, we make a
                   2169:                 * temporary copy of this entry and use that for the
                   2170:                 * wiring.  Note that the underlying objects do not
                   2171:                 * change during a clip.
                   2172:                 */
                   2173:                tmp_entry = *entry;
                   2174: 
                   2175:                /*
                   2176:                 * The in_transition state guarentees that the entry
                   2177:                 * (or entries for this range, if split occured) will be
                   2178:                 * there when the map lock is acquired for the second time.
                   2179:                 */
                   2180:                vm_map_unlock(map);
                   2181:                rc = vm_fault_wire(map, &tmp_entry);
                   2182:                vm_map_lock(map);
                   2183: 
                   2184:                if (last_timestamp+1 != map->timestamp) {
                   2185:                        /*
                   2186:                         * Find the entry again.  It could have been clipped
                   2187:                         * after we unlocked the map.
                   2188:                         */
                   2189:                        if (!vm_map_lookup_entry(map, tmp_entry.vme_start,
                   2190:                                                                &first_entry))
                   2191:                                panic("vm_map_wire: re-lookup failed");
                   2192: 
                   2193:                        entry = first_entry;
                   2194:                }
                   2195: 
                   2196:                last_timestamp = map->timestamp;
                   2197: 
                   2198:                while ((entry != vm_map_to_entry(map)) &&
                   2199:                       (entry->vme_start < tmp_entry.vme_end)) {
                   2200:                        assert(entry->in_transition);
                   2201:                        entry->in_transition = FALSE;
                   2202:                        if (entry->needs_wakeup) {
                   2203:                                entry->needs_wakeup = FALSE;
                   2204:                                need_wakeup = TRUE;
                   2205:                        }
                   2206:                        if (rc != KERN_SUCCESS) {       /* from vm_*_wire */
                   2207:                                if (user_wire)
                   2208:                                        entry->user_wired_count--;
                   2209:                                entry->wired_count--;
                   2210:                        }
                   2211:                        entry = entry->vme_next;
                   2212:                }
                   2213: 
                   2214:                if (rc != KERN_SUCCESS) {               /* from vm_*_wire */
                   2215:                        vm_map_unlock(map);
                   2216:                        if (need_wakeup)
                   2217:                                vm_map_entry_wakeup(map);
                   2218:                        /*
                   2219:                         * undo everything upto the previous entry.
                   2220:                         */
                   2221:                        (void)vm_map_unwire(map, start, s, user_wire);
                   2222:                        return rc;
                   2223:                }
                   2224:        } /* end while loop through map entries */
                   2225:        vm_map_unlock(map);
                   2226: 
                   2227:        /*
                   2228:         * wake up anybody waiting on entries we wired.
                   2229:         */
                   2230:        if (need_wakeup)
                   2231:                vm_map_entry_wakeup(map);
                   2232: 
                   2233:        return(KERN_SUCCESS);
                   2234: 
                   2235: }
                   2236: 
                   2237: 
                   2238: /*
                   2239:  *     vm_map_unwire:
                   2240:  *
                   2241:  *     Sets the pageability of the specified address range in the target
                   2242:  *     as pageable.  Regions specified must have been wired previously.
                   2243:  *
                   2244:  *     The map must not be locked, but a reference must remain to the map
                   2245:  *     throughout the call.
                   2246:  *
                   2247:  *     Kernel will panic on failures.  User unwire ignores holes and
                   2248:  *     unwired and intransition entries to avoid losing memory by leaving
                   2249:  *     it unwired.
                   2250:  */
                   2251: kern_return_t
                   2252: vm_map_unwire(
                   2253:        register vm_map_t       map,
                   2254:        register vm_offset_t    start,
                   2255:        register vm_offset_t    end,
                   2256:        boolean_t               user_wire)
                   2257: {
                   2258:        register vm_map_entry_t entry;
                   2259:        struct vm_map_entry     *first_entry, tmp_entry;
                   2260:        boolean_t               need_wakeup;
                   2261:        unsigned int            last_timestamp;
                   2262: 
                   2263:        vm_map_lock(map);
                   2264:        last_timestamp = map->timestamp;
                   2265: 
                   2266:        VM_MAP_RANGE_CHECK(map, start, end);
                   2267:        assert(page_aligned(start));
                   2268:        assert(page_aligned(end));
                   2269: 
                   2270:        if (vm_map_lookup_entry(map, start, &first_entry)) {
                   2271:                entry = first_entry;
                   2272:                /*      vm_map_clip_start will be done later. */
                   2273:        }
                   2274:        else {
                   2275:                /*      Start address is not in map. */
                   2276:                vm_map_unlock(map);
                   2277:                return(KERN_INVALID_ADDRESS);
                   2278:        }
                   2279: 
                   2280:        need_wakeup = FALSE;
                   2281:        while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
                   2282:                if(entry->is_sub_map) {
                   2283:                        vm_offset_t     sub_start;
                   2284:                        vm_offset_t     sub_end;
                   2285:                        vm_offset_t     local_end;
                   2286:                        
                   2287:                        if(entry->vme_start < start)
                   2288:                                sub_start = start;
                   2289:                        else
                   2290:                                sub_start = entry->vme_start;
                   2291:                        sub_start -= entry->vme_start;
                   2292:                        sub_start += entry->offset;
                   2293:                        
                   2294:                        if(entry->vme_end < end)
                   2295:                                sub_end = entry->vme_end;
                   2296:                        else
                   2297:                                sub_end = end;
                   2298:                        sub_end -= entry->vme_start;
                   2299:                        sub_end += entry->offset;
                   2300:                        local_end = entry->vme_end;
                   2301:                        vm_map_unlock(map);
                   2302:                        vm_map_unwire(entry->object.sub_map, 
                   2303:                                                sub_start, sub_end,
                   2304:                                                user_wire);
                   2305:                        
                   2306:                        vm_map_lock(map);
                   2307:                        if (last_timestamp+1 != map->timestamp) {
                   2308:                        /*
                   2309:                         * Find the entry again.  It could have been clipped
                   2310:                         * after we unlocked the map.
                   2311:                         */
                   2312:                                if (!vm_map_lookup_entry(map, local_end,
                   2313:                                                         &first_entry))
                   2314:                                   panic("vm_map_unwire: re-lookup failed");
                   2315: 
                   2316:                                entry = first_entry;
                   2317:                        } else
                   2318:                                entry = entry->vme_next;
                   2319: 
                   2320:                        last_timestamp = map->timestamp;
                   2321:                        continue;
                   2322:                }
                   2323: 
                   2324: 
                   2325:                if (entry->in_transition) {
                   2326:                        /*
                   2327:                         * 1)
                   2328:                         * Another thread is wiring down this entry. Note
                   2329:                         * that if it is not for the other thread we would
                   2330:                         * be unwiring an unwired entry.  This is not
                   2331:                         * permitted.  If we wait, we will be unwiring memory
                   2332:                         * we did not wire.
                   2333:                         *
                   2334:                         * 2)
                   2335:                         * Another thread is unwiring this entry.  We did not
                   2336:                         * have a reference to it, because if we did, this
                   2337:                         * entry will not be getting unwired now.
                   2338:                         */
                   2339:                        if (!user_wire)
                   2340:                                panic("vm_map_unwire: in_transition entry");
                   2341: 
                   2342:                        entry = entry->vme_next;
                   2343:                        continue;
                   2344:                }
                   2345: 
                   2346:                if (entry->wired_count == 0 ||
                   2347:                   (user_wire && entry->user_wired_count == 0)) {
                   2348:                        if (!user_wire)
                   2349:                                panic("vm_map_unwire: entry is unwired");
                   2350: 
                   2351:                        entry = entry->vme_next;
                   2352:                        continue;
                   2353:                }
                   2354:                
                   2355:                assert(entry->wired_count > 0 &&
                   2356:                        (!user_wire || entry->user_wired_count > 0));
                   2357: 
                   2358:                vm_map_clip_start(map, entry, start);
                   2359:                vm_map_clip_end(map, entry, end);
                   2360: 
                   2361:                /*
                   2362:                 * Check for holes
                   2363:                 * Holes: Next entry should be contiguous unless
                   2364:                 *        this is the end of the region.
                   2365:                 */
                   2366:                if (((entry->vme_end < end) && 
                   2367:                    ((entry->vme_next == vm_map_to_entry(map)) ||
                   2368:                     (entry->vme_next->vme_start > entry->vme_end)))) {
                   2369: 
                   2370:                        if (!user_wire)
                   2371:                                panic("vm_map_unwire: non-contiguous region");
                   2372:                        entry = entry->vme_next;
                   2373:                        continue;
                   2374:                }
                   2375: 
                   2376:                if (!user_wire || (--entry->user_wired_count == 0))
                   2377:                        entry->wired_count--;
                   2378: 
                   2379:                if (entry->wired_count != 0) {
                   2380:                        entry = entry->vme_next;
                   2381:                        continue;
                   2382:                }
                   2383: 
                   2384:                entry->in_transition = TRUE;
                   2385:                tmp_entry = *entry;     /* see comment in vm_map_wire() */
                   2386: 
                   2387:                /*
                   2388:                 * We can unlock the map now. The in_transition state
                   2389:                 * guarantees existance of the entry.
                   2390:                 */
                   2391:                vm_map_unlock(map);
                   2392:                vm_fault_unwire(map, &tmp_entry, FALSE);
                   2393:                vm_map_lock(map);
                   2394: 
                   2395:                if (last_timestamp+1 != map->timestamp) {
                   2396:                        /*
                   2397:                         * Find the entry again.  It could have been clipped
                   2398:                         * or deleted after we unlocked the map.
                   2399:                         */
                   2400:                        if (!vm_map_lookup_entry(map, tmp_entry.vme_start,
                   2401:                                                                &first_entry)) {
                   2402:                                if (!user_wire)
                   2403:                                       panic("vm_map_unwire: re-lookup failed");
                   2404:                                entry = first_entry->vme_next;
                   2405:                        } else
                   2406:                                entry = first_entry;
                   2407:                }
                   2408:                last_timestamp = map->timestamp;
                   2409: 
                   2410:                /*
                   2411:                 * clear transition bit for all constituent entries that
                   2412:                 * were in the original entry (saved in tmp_entry).  Also
                   2413:                 * check for waiters.
                   2414:                 */
                   2415:                while ((entry != vm_map_to_entry(map)) &&
                   2416:                       (entry->vme_start < tmp_entry.vme_end)) {
                   2417:                        assert(entry->in_transition);
                   2418:                        entry->in_transition = FALSE;
                   2419:                        if (entry->needs_wakeup) {
                   2420:                                entry->needs_wakeup = FALSE;
                   2421:                                need_wakeup = TRUE;
                   2422:                        }
                   2423:                        entry = entry->vme_next;
                   2424:                }
                   2425:        }
                   2426:        vm_map_unlock(map);
                   2427:        /*
                   2428:         * wake up anybody waiting on entries that we have unwired.
                   2429:         */
                   2430:        if (need_wakeup)
                   2431:                vm_map_entry_wakeup(map);
                   2432:        return(KERN_SUCCESS);
                   2433: 
                   2434: }
                   2435: 
                   2436: /*
                   2437:  *     vm_map_entry_delete:    [ internal use only ]
                   2438:  *
                   2439:  *     Deallocate the given entry from the target map.
                   2440:  */            
                   2441: void
                   2442: vm_map_entry_delete(
                   2443:        register vm_map_t       map,
                   2444:        register vm_map_entry_t entry)
                   2445: {
                   2446:        register vm_offset_t    s, e;
                   2447:        register vm_object_t    object;
                   2448:        extern vm_object_t      kernel_object;
                   2449: 
                   2450:        s = entry->vme_start;
                   2451:        e = entry->vme_end;
                   2452:        assert(page_aligned(s));
                   2453:        assert(page_aligned(e));
                   2454:        assert(entry->wired_count == 0);
                   2455:        assert(entry->user_wired_count == 0);
                   2456: 
                   2457: 
                   2458:        /*
                   2459:         *      Deallocate the object only after removing all
                   2460:         *      pmap entries pointing to its pages.
                   2461:         */
                   2462:        if (entry->is_sub_map)
                   2463:                vm_map_deallocate(entry->object.sub_map);
                   2464:        else
                   2465:                vm_object_deallocate(entry->object.vm_object);
                   2466: 
                   2467:        vm_map_entry_unlink(map, entry);
                   2468:        map->size -= e - s;
                   2469: 
                   2470:        vm_map_entry_dispose(map, entry);
                   2471: }
                   2472: 
                   2473: 
                   2474: /*
                   2475:  *     vm_map_delete:  [ internal use only ]
                   2476:  *
                   2477:  *     Deallocates the given address range from the target map.
                   2478:  *     Removes all user wirings. Unwires one kernel wiring if
                   2479:  *     VM_MAP_REMOVE_KUNWIRE is set.  Waits for kernel wirings to go
                   2480:  *     away if VM_MAP_REMOVE_WAIT_FOR_KWIRE is set.  Sleeps
                   2481:  *     interruptibly if VM_MAP_REMOVE_INTERRUPTIBLE is set.
                   2482:  *
                   2483:  *     This routine is called with map locked and leaves map locked.
                   2484:  */
                   2485: kern_return_t
                   2486: vm_map_delete(
                   2487:        register vm_map_t       map,
                   2488:        vm_offset_t             start,
                   2489:        register vm_offset_t    end,
                   2490:        int                     flags)
                   2491: {
                   2492:        register vm_map_entry_t entry, next;
                   2493:        struct   vm_map_entry   *first_entry, tmp_entry;
                   2494:        register vm_offset_t    s, e;
                   2495:        register vm_object_t    object;
                   2496:        boolean_t               need_wakeup;
                   2497:        unsigned int            last_timestamp = ~0; /* unlikely value */
                   2498:        int                     interruptible;
                   2499:        extern vm_map_t         kernel_map;
                   2500: 
                   2501:        interruptible = (flags & VM_MAP_REMOVE_INTERRUPTIBLE) ? 
                   2502:                        THREAD_ABORTSAFE : THREAD_UNINT;
                   2503: 
                   2504:        /*
                   2505:         *      Find the start of the region, and clip it
                   2506:         */
                   2507:        if (vm_map_lookup_entry(map, start, &first_entry)) {
                   2508:                entry = first_entry;
                   2509:                vm_map_clip_start(map, entry, start);
                   2510: 
                   2511:                /*
                   2512:                 *      Fix the lookup hint now, rather than each
                   2513:                 *      time through the loop.
                   2514:                 */
                   2515:                SAVE_HINT(map, entry->vme_prev);
                   2516:        } else {
                   2517:                entry = first_entry->vme_next;
                   2518:        }
                   2519: 
                   2520:        need_wakeup = FALSE;
                   2521:        /*
                   2522:         *      Step through all entries in this region
                   2523:         */
                   2524:        while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
                   2525: 
                   2526:                vm_map_clip_end(map, entry, end);
                   2527: retry_entry:
                   2528:                if (entry->in_transition) {
                   2529:                        /*
                   2530:                         * Another thread is wiring/unwiring this entry.
                   2531:                         * Let the other thread know we are waiting.
                   2532:                         */
                   2533:                        s = entry->vme_start;
                   2534:                        entry->needs_wakeup = TRUE;
                   2535: 
                   2536:                        /*
                   2537:                         * wake up anybody waiting on entries that we have
                   2538:                         * already unwired/deleted.
                   2539:                         */
                   2540:                        if (need_wakeup) {
                   2541:                                vm_map_entry_wakeup(map);
                   2542:                                need_wakeup = FALSE;
                   2543:                        }
                   2544: 
                   2545:                        vm_map_entry_wait(map, interruptible);
                   2546: 
                   2547:                        if (interruptible &&
                   2548:                           current_thread()->wait_result == THREAD_INTERRUPTED)
                   2549:                                /*
                   2550:                                 * We do not clear the needs_wakeup flag,
                   2551:                                 * since we cannot tell if we were the only one.
                   2552:                                 */
                   2553:                                return KERN_ABORTED;
                   2554: 
                   2555:                        vm_map_lock(map);
                   2556:                        /*
                   2557:                         * Cannot avoid a lookup here. reset timestamp.
                   2558:                         */
                   2559:                        last_timestamp = map->timestamp;
                   2560: 
                   2561:                        /*
                   2562:                         * The entry could have been clipped or it
                   2563:                         * may not exist anymore.  Look it up again.
                   2564:                         */
                   2565:                        if (!vm_map_lookup_entry(map, s, &first_entry)) {
                   2566:                                assert((map != kernel_map) && 
                   2567:                                       (!entry->is_sub_map));
                   2568:                                /*
                   2569:                                 * User: use the next entry
                   2570:                                 */
                   2571:                                entry = first_entry->vme_next;
                   2572:                        } else {
                   2573:                                entry = first_entry;
                   2574:                                SAVE_HINT(map, entry->vme_prev);
                   2575:                        }
                   2576:                        goto retry_entry;
                   2577:                } /* end in_transition */
                   2578: 
                   2579:                if (entry->wired_count) {
                   2580:                        /*
                   2581:                         *      Remove a kernel wiring if requested or if
                   2582:                         *      there are user wirings.
                   2583:                         */
                   2584:                        if ((flags & VM_MAP_REMOVE_KUNWIRE) || 
                   2585:                           (entry->user_wired_count > 0))
                   2586:                                entry->wired_count--;
                   2587: 
                   2588:                        /* remove all user wire references */
                   2589:                        entry->user_wired_count = 0;
                   2590: 
                   2591:                        if (entry->wired_count != 0) {
                   2592:                                assert((map != kernel_map) && 
                   2593:                                       (!entry->is_sub_map));
                   2594:                                /*
                   2595:                                 * Cannot continue.  Typical case is when
                   2596:                                 * a user thread has physical io pending on
                   2597:                                 * on this page.  Either wait for the
                   2598:                                 * kernel wiring to go away or return an
                   2599:                                 * error.
                   2600:                                 */
                   2601:                                if (flags & VM_MAP_REMOVE_WAIT_FOR_KWIRE) {
                   2602: 
                   2603:                                        s = entry->vme_start;
                   2604:                                        entry->needs_wakeup = TRUE;
                   2605:                                        vm_map_entry_wait(map, interruptible);
                   2606: 
                   2607:                                        if (interruptible &&
                   2608:                                            current_thread()->wait_result == 
                   2609:                                                        THREAD_INTERRUPTED)
                   2610:                                                /*
                   2611:                                                 * We do not clear the 
                   2612:                                                 * needs_wakeup flag, since we 
                   2613:                                                 * cannot tell if we were the 
                   2614:                                                 * only one.
                   2615:                                                 */
                   2616:                                                return KERN_ABORTED;
                   2617: 
                   2618:                                        vm_map_lock(map);
                   2619:                                        /*
                   2620:                                         * Cannot avoid a lookup here. reset 
                   2621:                                         * timestamp.
                   2622:                                         */
                   2623:                                        last_timestamp = map->timestamp;
                   2624: 
                   2625:                                        /*
                   2626:                                         * The entry could have been clipped or
                   2627:                                         * it may not exist anymore.  Look it
                   2628:                                         * up again.
                   2629:                                         */
                   2630:                                        if (!vm_map_lookup_entry(map, s, 
                   2631:                                                                &first_entry)) {
                   2632:                                                assert((map != kernel_map) && 
                   2633:                                                (!entry->is_sub_map));
                   2634:                                                /*
                   2635:                                                 * User: use the next entry
                   2636:                                                 */
                   2637:                                                entry = first_entry->vme_next;
                   2638:                                        } else {
                   2639:                                                entry = first_entry;
                   2640:                                                SAVE_HINT(map, entry->vme_prev);
                   2641:                                        }
                   2642:                                        goto retry_entry;
                   2643:                                }
                   2644:                                else {
                   2645:                                        return KERN_FAILURE;
                   2646:                                }
                   2647:                        }
                   2648: 
                   2649:                        entry->in_transition = TRUE;
                   2650:                        /*
                   2651:                         * copy current entry.  see comment in vm_map_wire()
                   2652:                         */
                   2653:                        tmp_entry = *entry;
                   2654:                        s = entry->vme_start;
                   2655:                        e = entry->vme_end;
                   2656: 
                   2657:                        /*
                   2658:                         * We can unlock the map now. The in_transition
                   2659:                         * state guarentees existance of the entry.
                   2660:                         */
                   2661:                        vm_map_unlock(map);
                   2662:                        vm_fault_unwire(map, &tmp_entry,
                   2663:                                tmp_entry.object.vm_object == kernel_object);
                   2664:                        vm_map_lock(map);
                   2665: 
                   2666:                        if (last_timestamp+1 != map->timestamp) {
                   2667:                                /*
                   2668:                                 * Find the entry again.  It could have
                   2669:                                 * been clipped after we unlocked the map.
                   2670:                                 */
                   2671:                                if (!vm_map_lookup_entry(map, s, &first_entry)){
                   2672:                                        assert((map != kernel_map) && 
                   2673:                                               (!entry->is_sub_map));
                   2674:                                        first_entry = first_entry->vme_next;
                   2675:                                } else {
                   2676:                                        SAVE_HINT(map, entry->vme_prev);
                   2677:                                }
                   2678:                        } else {
                   2679:                                SAVE_HINT(map, entry->vme_prev);
                   2680:                                first_entry = entry;
                   2681:                        }
                   2682: 
                   2683:                        last_timestamp = map->timestamp;
                   2684: 
                   2685:                        entry = first_entry;
                   2686:                        while ((entry != vm_map_to_entry(map)) &&
                   2687:                               (entry->vme_start < tmp_entry.vme_end)) {
                   2688:                                assert(entry->in_transition);
                   2689:                                entry->in_transition = FALSE;
                   2690:                                if (entry->needs_wakeup) {
                   2691:                                        entry->needs_wakeup = FALSE;
                   2692:                                        need_wakeup = TRUE;
                   2693:                                }
                   2694:                                entry = entry->vme_next;
                   2695:                        }
                   2696:                        /*
                   2697:                         * We have unwired the entry(s).  Go back and
                   2698:                         * delete them.
                   2699:                         */
                   2700:                        entry = first_entry;
                   2701:                        goto retry_entry;
                   2702:                }
                   2703: 
                   2704:                /* entry is unwired */
                   2705:                assert(entry->wired_count == 0);
                   2706:                assert(entry->user_wired_count == 0);
                   2707: 
                   2708:                if ((!entry->is_sub_map &&
                   2709:                    entry->object.vm_object != kernel_object) ||
                   2710:                    entry->is_sub_map) {
                   2711:                        pmap_remove(map->pmap,
                   2712:                                    entry->vme_start, entry->vme_end);
                   2713:                }
                   2714: 
                   2715:                next = entry->vme_next;
                   2716:                vm_map_entry_delete(map, entry);
                   2717:                entry = next;
                   2718:        }
                   2719: 
                   2720:        if (map->wait_for_space)
                   2721:                thread_wakeup((event_t) map);
                   2722:        /*
                   2723:         * wake up anybody waiting on entries that we have already deleted.
                   2724:         */
                   2725:        if (need_wakeup)
                   2726:                vm_map_entry_wakeup(map);
                   2727: 
                   2728:        return KERN_SUCCESS;
                   2729: }
                   2730: 
                   2731: /*
                   2732:  *     vm_map_remove:
                   2733:  *
                   2734:  *     Remove the given address range from the target map.
                   2735:  *     This is the exported form of vm_map_delete.
                   2736:  */
                   2737: kern_return_t
                   2738: vm_map_remove(
                   2739:        register vm_map_t       map,
                   2740:        register vm_offset_t    start,
                   2741:        register vm_offset_t    end,
                   2742:        register boolean_t      flags)
                   2743: {
                   2744:        register kern_return_t  result;
                   2745: 
                   2746:        vm_map_lock(map);
                   2747:        VM_MAP_RANGE_CHECK(map, start, end);
                   2748:        result = vm_map_delete(map, start, end, flags);
                   2749:        vm_map_unlock(map);
                   2750: 
                   2751:        return(result);
                   2752: }
                   2753: 
                   2754: 
                   2755: /*
                   2756:  *     vm_map_copy_steal_pages:
                   2757:  *
                   2758:  *     Steal all the pages from a vm_map_copy page_list by copying ones
                   2759:  *     that have not already been stolen.
                   2760:  */
                   2761: void
                   2762: vm_map_copy_steal_pages(
                   2763:        vm_map_copy_t   copy)
                   2764: {
                   2765:        register vm_page_t      m, new_m;
                   2766:        register int            i;
                   2767:        vm_object_t             object;
                   2768: 
                   2769:        assert(copy->type == VM_MAP_COPY_PAGE_LIST);
                   2770:        for (i = 0; i < copy->cpy_npages; i++) {
                   2771: 
                   2772:                /*
                   2773:                 *      If the page is not tabled, then it's already stolen.
                   2774:                 */
                   2775:                m = copy->cpy_page_list[i];
                   2776:                if (!m->tabled)
                   2777:                        continue;
                   2778: 
                   2779:                /*
                   2780:                 *      Page was not stolen,  get a new
                   2781:                 *      one and do the copy now.
                   2782:                 */
                   2783:                while ((new_m = vm_page_grab()) == VM_PAGE_NULL) {
                   2784:                        VM_PAGE_WAIT();
                   2785:                }
                   2786: 
                   2787:                vm_page_gobble(new_m); /* mark as consumed internally */
                   2788:                vm_page_copy(m, new_m);
                   2789: 
                   2790:                object = m->object;
                   2791:                vm_object_lock(object);
                   2792:                vm_page_lock_queues();
                   2793:                if (!m->active && !m->inactive)
                   2794:                        vm_page_activate(m);
                   2795:                vm_page_unlock_queues();
                   2796:                PAGE_WAKEUP_DONE(m);
                   2797:                vm_object_paging_end(object);
                   2798:                vm_object_unlock(object);
                   2799: 
                   2800:                copy->cpy_page_list[i] = new_m;
                   2801:        }
                   2802:        copy->cpy_page_loose = TRUE;
                   2803: }
                   2804: 
                   2805: /*
                   2806:  *     vm_map_copy_page_discard:
                   2807:  *
                   2808:  *     Get rid of the pages in a page_list copy.  If the pages are
                   2809:  *     stolen, they are freed.  If the pages are not stolen, they
                   2810:  *     are unbusied, and associated state is cleaned up.
                   2811:  */
                   2812: void
                   2813: vm_map_copy_page_discard(
                   2814:        vm_map_copy_t   copy)
                   2815: {
                   2816:        assert(copy->type == VM_MAP_COPY_PAGE_LIST);
                   2817:        while (copy->cpy_npages > 0) {
                   2818:                vm_page_t       m;
                   2819: 
                   2820:                if ((m = copy->cpy_page_list[--(copy->cpy_npages)]) !=
                   2821:                    VM_PAGE_NULL) {
                   2822: 
                   2823:                        /*
                   2824:                         *      If it's not in the table, then it's
                   2825:                         *      a stolen page that goes back
                   2826:                         *      to the free list.  Else it belongs
                   2827:                         *      to some object, and we hold a
                   2828:                         *      paging reference on that object.
                   2829:                         */
                   2830:                        if (!m->tabled) {
                   2831:                                VM_PAGE_FREE(m);
                   2832:                        }
                   2833:                        else {
                   2834:                                vm_object_t     object;
                   2835: 
                   2836:                                object = m->object;
                   2837: 
                   2838:                                vm_object_lock(object);
                   2839:                                vm_page_lock_queues();
                   2840:                                if (!m->active && !m->inactive)
                   2841:                                        vm_page_activate(m);
                   2842:                                vm_page_unlock_queues();
                   2843: 
                   2844:                                if ((!m->busy)) {
                   2845:                                    kern_return_t kr;
                   2846:                                    kr = vm_page_unpin(m);
                   2847:                                    assert(kr == KERN_SUCCESS);
                   2848:                                } else {
                   2849:                                    PAGE_WAKEUP_DONE(m);
                   2850:                                }
                   2851:                                vm_object_paging_end(object);
                   2852:                                vm_object_unlock(object);
                   2853:                        }
                   2854:                }
                   2855:        }
                   2856: }
                   2857: 
                   2858: /*
                   2859:  *     Routine:        vm_map_copy_discard
                   2860:  *
                   2861:  *     Description:
                   2862:  *             Dispose of a map copy object (returned by
                   2863:  *             vm_map_copyin).
                   2864:  */
                   2865: void
                   2866: vm_map_copy_discard(
                   2867:        vm_map_copy_t   copy)
                   2868: {
                   2869:        TR_DECL("vm_map_copy_discard");
                   2870: 
                   2871: /*     tr3("enter: copy 0x%x type %d", copy, copy->type);*/
                   2872: free_next_copy:
                   2873:        if (copy == VM_MAP_COPY_NULL)
                   2874:                return;
                   2875: 
                   2876:        switch (copy->type) {
                   2877:        case VM_MAP_COPY_ENTRY_LIST:
                   2878:                while (vm_map_copy_first_entry(copy) !=
                   2879:                                        vm_map_copy_to_entry(copy)) {
                   2880:                        vm_map_entry_t  entry = vm_map_copy_first_entry(copy);
                   2881: 
                   2882:                        vm_map_copy_entry_unlink(copy, entry);
                   2883:                        vm_object_deallocate(entry->object.vm_object);
                   2884:                        vm_map_copy_entry_dispose(copy, entry);
                   2885:                }
                   2886:                break;
                   2887:         case VM_MAP_COPY_OBJECT:
                   2888:                vm_object_deallocate(copy->cpy_object);
                   2889:                break;
                   2890:        case VM_MAP_COPY_PAGE_LIST:
                   2891: 
                   2892:                /*
                   2893:                 *      To clean this up, we have to unbusy all the pages
                   2894:                 *      and release the paging references in their objects.
                   2895:                 */
                   2896:                if (copy->cpy_npages > 0)
                   2897:                        vm_map_copy_page_discard(copy);
                   2898: 
                   2899:                /*
                   2900:                 *      If there's a continuation, abort it.  The
                   2901:                 *      abort routine releases any storage.
                   2902:                 */
                   2903:                if (vm_map_copy_has_cont(copy)) {
                   2904: 
                   2905:                        assert(vm_map_copy_cont_is_valid(copy));
                   2906:                        /*
                   2907:                         *      Special case: recognize
                   2908:                         *      vm_map_copy_discard_cont and optimize
                   2909:                         *      here to avoid tail recursion.
                   2910:                         */
                   2911:                        if (copy->cpy_cont == vm_map_copy_discard_cont) {
                   2912:                                register vm_map_copy_t  new_copy;
                   2913: 
                   2914:                                new_copy = (vm_map_copy_t) copy->cpy_cont_args;
                   2915:                                zfree(vm_map_copy_zone, (vm_offset_t) copy);
                   2916:                                copy = new_copy;
                   2917:                                goto free_next_copy;
                   2918:                        } else {
                   2919:                                vm_map_copy_abort_cont(copy);
                   2920:                        }
                   2921:                }
                   2922: 
                   2923:                break;
                   2924: 
                   2925:        case VM_MAP_COPY_KERNEL_BUFFER:
                   2926: 
                   2927:                /*
                   2928:                 * The vm_map_copy_t and possibly the data buffer were
                   2929:                 * allocated by a single call to kalloc(), i.e. the
                   2930:                 * vm_map_copy_t was not allocated out of the zone.
                   2931:                 */
                   2932:                kfree((vm_offset_t) copy, copy->cpy_kalloc_size);
                   2933:                return;
                   2934:        }
                   2935:        zfree(vm_map_copy_zone, (vm_offset_t) copy);
                   2936: }
                   2937: 
                   2938: /*
                   2939:  *     Routine:        vm_map_copy_copy
                   2940:  *
                   2941:  *     Description:
                   2942:  *                     Move the information in a map copy object to
                   2943:  *                     a new map copy object, leaving the old one
                   2944:  *                     empty.
                   2945:  *
                   2946:  *                     This is used by kernel routines that need
                   2947:  *                     to look at out-of-line data (in copyin form)
                   2948:  *                     before deciding whether to return SUCCESS.
                   2949:  *                     If the routine returns FAILURE, the original
                   2950:  *                     copy object will be deallocated; therefore,
                   2951:  *                     these routines must make a copy of the copy
                   2952:  *                     object and leave the original empty so that
                   2953:  *                     deallocation will not fail.
                   2954:  */
                   2955: vm_map_copy_t
                   2956: vm_map_copy_copy(
                   2957:        vm_map_copy_t   copy)
                   2958: {
                   2959:        vm_map_copy_t   new_copy;
                   2960: 
                   2961:        if (copy == VM_MAP_COPY_NULL)
                   2962:                return VM_MAP_COPY_NULL;
                   2963: 
                   2964:        /*
                   2965:         * Allocate a new copy object, and copy the information
                   2966:         * from the old one into it.
                   2967:         */
                   2968: 
                   2969:        new_copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
                   2970:        *new_copy = *copy;
                   2971: 
                   2972:        if (copy->type == VM_MAP_COPY_ENTRY_LIST) {
                   2973:                /*
                   2974:                 * The links in the entry chain must be
                   2975:                 * changed to point to the new copy object.
                   2976:                 */
                   2977:                vm_map_copy_first_entry(copy)->vme_prev
                   2978:                        = vm_map_copy_to_entry(new_copy);
                   2979:                vm_map_copy_last_entry(copy)->vme_next
                   2980:                        = vm_map_copy_to_entry(new_copy);
                   2981:        }
                   2982: 
                   2983:        /*
                   2984:         * Change the old copy object into one that contains
                   2985:         * nothing to be deallocated.
                   2986:         */
                   2987:        copy->type = VM_MAP_COPY_OBJECT;
                   2988:        copy->cpy_object = VM_OBJECT_NULL;
                   2989: 
                   2990:        /*
                   2991:         * Return the new object.
                   2992:         */
                   2993:        return new_copy;
                   2994: }
                   2995: 
                   2996: /*
                   2997:  *     Routine:        vm_map_copy_discard_cont
                   2998:  *
                   2999:  *     Description:
                   3000:  *             A version of vm_map_copy_discard that can be called
                   3001:  *             as a continuation from a vm_map_copy page list.
                   3002:  */
                   3003: kern_return_t
                   3004: vm_map_copy_discard_cont(
                   3005:        vm_map_copyin_args_t    cont_args,
                   3006:        vm_map_copy_t           *copy_result)   /* OUT */
                   3007: {
                   3008:        vm_map_copy_discard((vm_map_copy_t) cont_args);
                   3009:        if (copy_result != (vm_map_copy_t *)0)
                   3010:                *copy_result = VM_MAP_COPY_NULL;
                   3011:        return(KERN_SUCCESS);
                   3012: }
                   3013: 
                   3014: kern_return_t
                   3015: vm_map_overwrite_submap_recurse(
                   3016:        vm_map_t        dst_map,
                   3017:        vm_offset_t     dst_addr,
                   3018:        vm_size_t       dst_size)
                   3019: {
                   3020:        vm_offset_t     dst_end;
                   3021:        vm_map_entry_t  tmp_entry;
                   3022:        vm_map_entry_t  entry;
                   3023:        kern_return_t   result;
                   3024:        boolean_t       encountered_sub_map = FALSE;
                   3025: 
                   3026: 
                   3027: 
                   3028:        /*
                   3029:         *      Verify that the destination is all writeable
                   3030:         *      initially.  We have to trunc the destination
                   3031:         *      address and round the copy size or we'll end up
                   3032:         *      splitting entries in strange ways.
                   3033:         */
                   3034: 
                   3035:        dst_end = round_page(dst_addr + dst_size);
                   3036: 
                   3037: start_pass_1:
                   3038:        vm_map_lock(dst_map);
                   3039:        if (!vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry)) {
                   3040:                vm_map_unlock(dst_map);
                   3041:                return(KERN_INVALID_ADDRESS);
                   3042:        }
                   3043: 
                   3044:        vm_map_clip_start(dst_map, tmp_entry, trunc_page(dst_addr));
                   3045: 
                   3046:        for (entry = tmp_entry;;) {
                   3047:                vm_map_entry_t  next;
                   3048: 
                   3049:                next = entry->vme_next;
                   3050:                while(entry->is_sub_map) {
                   3051:                        vm_offset_t     sub_start;
                   3052:                        vm_offset_t     sub_end;
                   3053:                        vm_offset_t     local_end;
                   3054: 
                   3055:                        if (entry->in_transition) {
                   3056:                         /*
                   3057:                          * Say that we are waiting, and wait for entry.
                   3058:                          */
                   3059:                                entry->needs_wakeup = TRUE;
                   3060:                                vm_map_entry_wait(dst_map, THREAD_UNINT);
                   3061: 
                   3062:                                goto start_pass_1;
                   3063:                        }
                   3064: 
                   3065:                        encountered_sub_map = TRUE;
                   3066:                        sub_start = entry->offset;
                   3067: 
                   3068:                        if(entry->vme_end < dst_end)
                   3069:                                sub_end = entry->vme_end;
                   3070:                        else 
                   3071:                                sub_end = dst_end;
                   3072:                        sub_end -= entry->vme_start;
                   3073:                        sub_end += entry->offset;
                   3074:                        local_end = entry->vme_end;
                   3075:                        vm_map_unlock(dst_map);
                   3076:                        
                   3077:                        result = vm_map_overwrite_submap_recurse(
                   3078:                                        entry->object.sub_map,
                   3079:                                        sub_start,
                   3080:                                        sub_end - sub_start);
                   3081: 
                   3082:                        if(result != KERN_SUCCESS)
                   3083:                                return result;
                   3084:                        if (dst_end <= entry->vme_end)
                   3085:                                return KERN_SUCCESS;
                   3086:                        vm_map_lock(dst_map);
                   3087:                        if(!vm_map_lookup_entry(dst_map, local_end, 
                   3088:                                                &tmp_entry)) {
                   3089:                                vm_map_unlock(dst_map);
                   3090:                                return(KERN_INVALID_ADDRESS);
                   3091:                        }
                   3092:                        entry = tmp_entry;
                   3093:                        next = entry->vme_next;
                   3094:                }
                   3095: 
                   3096:                if ( ! (entry->protection & VM_PROT_WRITE)) {
                   3097:                        vm_map_unlock(dst_map);
                   3098:                        return(KERN_PROTECTION_FAILURE);
                   3099:                }
                   3100: 
                   3101:                /*
                   3102:                 *      If the entry is in transition, we must wait
                   3103:                 *      for it to exit that state.  Anything could happen
                   3104:                 *      when we unlock the map, so start over.
                   3105:                 */
                   3106:                 if (entry->in_transition) {
                   3107: 
                   3108:                         /*
                   3109:                          * Say that we are waiting, and wait for entry.
                   3110:                          */
                   3111:                         entry->needs_wakeup = TRUE;
                   3112:                         vm_map_entry_wait(dst_map, THREAD_UNINT);
                   3113: 
                   3114:                        goto start_pass_1;
                   3115:                }
                   3116: 
                   3117: /*
                   3118:  *             our range is contained completely within this map entry
                   3119:  */
                   3120:                if (dst_end <= entry->vme_end) {
                   3121:                        vm_map_unlock(dst_map);
                   3122:                        return KERN_SUCCESS;
                   3123:                }
                   3124: /*
                   3125:  *             check that range specified is contiguous region
                   3126:  */
                   3127:                if ((next == vm_map_to_entry(dst_map)) ||
                   3128:                    (next->vme_start != entry->vme_end)) {
                   3129:                        vm_map_unlock(dst_map);
                   3130:                        return(KERN_INVALID_ADDRESS);
                   3131:                }
                   3132: 
                   3133:                /*
                   3134:                 *      Check for permanent objects in the destination.
                   3135:                 */
                   3136:                if ((entry->object.vm_object != VM_OBJECT_NULL) &&
                   3137:                           ((!entry->object.vm_object->internal) ||
                   3138:                           (entry->object.vm_object->true_share))) {
                   3139:                        if(encountered_sub_map) {
                   3140:                                vm_map_unlock(dst_map);
                   3141:                                return(KERN_FAILURE);
                   3142:                        }
                   3143:                }
                   3144: 
                   3145: 
                   3146:                entry = next;
                   3147:        }/* for */
                   3148:        vm_map_unlock(dst_map);
                   3149:        return(KERN_SUCCESS);
                   3150: }
                   3151: 
                   3152: /*
                   3153:  *     Routine:        vm_map_copy_overwrite
                   3154:  *
                   3155:  *     Description:
                   3156:  *             Copy the memory described by the map copy
                   3157:  *             object (copy; returned by vm_map_copyin) onto
                   3158:  *             the specified destination region (dst_map, dst_addr).
                   3159:  *             The destination must be writeable.
                   3160:  *
                   3161:  *             Unlike vm_map_copyout, this routine actually
                   3162:  *             writes over previously-mapped memory.  If the
                   3163:  *             previous mapping was to a permanent (user-supplied)
                   3164:  *             memory object, it is preserved.
                   3165:  *
                   3166:  *             The attributes (protection and inheritance) of the
                   3167:  *             destination region are preserved.
                   3168:  *
                   3169:  *             If successful, consumes the copy object.
                   3170:  *             Otherwise, the caller is responsible for it.
                   3171:  *
                   3172:  *     Implementation notes:
                   3173:  *             To overwrite aligned temporary virtual memory, it is
                   3174:  *             sufficient to remove the previous mapping and insert
                   3175:  *             the new copy.  This replacement is done either on
                   3176:  *             the whole region (if no permanent virtual memory
                   3177:  *             objects are embedded in the destination region) or
                   3178:  *             in individual map entries.
                   3179:  *
                   3180:  *             To overwrite permanent virtual memory , it is necessary
                   3181:  *             to copy each page, as the external memory management
                   3182:  *             interface currently does not provide any optimizations.
                   3183:  *
                   3184:  *             Unaligned memory also has to be copied.  It is possible
                   3185:  *             to use 'vm_trickery' to copy the aligned data.  This is
                   3186:  *             not done but not hard to implement.
                   3187:  *
                   3188:  *             Once a page of permanent memory has been overwritten,
                   3189:  *             it is impossible to interrupt this function; otherwise,
                   3190:  *             the call would be neither atomic nor location-independent.
                   3191:  *             The kernel-state portion of a user thread must be
                   3192:  *             interruptible.
                   3193:  *
                   3194:  *             It may be expensive to forward all requests that might
                   3195:  *             overwrite permanent memory (vm_write, vm_copy) to
                   3196:  *             uninterruptible kernel threads.  This routine may be
                   3197:  *             called by interruptible threads; however, success is
                   3198:  *             not guaranteed -- if the request cannot be performed
                   3199:  *             atomically and interruptibly, an error indication is
                   3200:  *             returned.
                   3201:  */
                   3202: 
                   3203: kern_return_t
                   3204: vm_map_copy_overwrite(
                   3205:        vm_map_t        dst_map,
                   3206:        vm_offset_t     dst_addr,
                   3207:        vm_map_copy_t   copy,
                   3208:        boolean_t       interruptible)
                   3209: {
                   3210:        vm_offset_t     dst_end;
                   3211:        vm_map_entry_t  tmp_entry;
                   3212:        vm_map_entry_t  entry;
                   3213:        kern_return_t   kr;
                   3214:        boolean_t       aligned = TRUE;
                   3215:        boolean_t       contains_permanent_objects = FALSE;
                   3216:        boolean_t       encountered_sub_map = FALSE;
                   3217:        vm_offset_t     base_addr;
                   3218:        vm_size_t       copy_size;
                   3219:        vm_size_t       total_size;
                   3220: 
                   3221: 
                   3222:        /*
                   3223:         *      Check for null copy object.
                   3224:         */
                   3225: 
                   3226:        if (copy == VM_MAP_COPY_NULL)
                   3227:                return(KERN_SUCCESS);
                   3228: 
                   3229:        /*
                   3230:         *      Check for special kernel buffer allocated
                   3231:         *      by new_ipc_kmsg_copyin.
                   3232:         */
                   3233: 
                   3234:        if (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {
                   3235:                return(vm_map_copyout_kernel_buffer(dst_map, &dst_addr, 
                   3236:                                                    copy, TRUE));
                   3237:        }
                   3238: 
                   3239:        /*
                   3240:         *      Only works for entry lists at the moment.  Will
                   3241:         *      support page lists later.
                   3242:         */
                   3243: 
                   3244:        assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
                   3245: 
                   3246:        if (copy->size == 0) {
                   3247:                vm_map_copy_discard(copy);
                   3248:                return(KERN_SUCCESS);
                   3249:        }
                   3250: 
                   3251:        /*
                   3252:         *      Verify that the destination is all writeable
                   3253:         *      initially.  We have to trunc the destination
                   3254:         *      address and round the copy size or we'll end up
                   3255:         *      splitting entries in strange ways.
                   3256:         */
                   3257: 
                   3258:        if (!page_aligned(copy->size) ||
                   3259:                !page_aligned (copy->offset) ||
                   3260:                !page_aligned (dst_addr))
                   3261:        {
                   3262:                aligned = FALSE;
                   3263:                dst_end = round_page(dst_addr + copy->size);
                   3264:        } else {
                   3265:                dst_end = dst_addr + copy->size;
                   3266:        }
                   3267: 
                   3268: start_pass_1:
                   3269:        vm_map_lock(dst_map);
                   3270:        if (!vm_map_lookup_entry(dst_map, dst_addr, &tmp_entry)) {
                   3271:                vm_map_unlock(dst_map);
                   3272:                return(KERN_INVALID_ADDRESS);
                   3273:        }
                   3274:        vm_map_clip_start(dst_map, tmp_entry, trunc_page(dst_addr));
                   3275:        for (entry = tmp_entry;;) {
                   3276:                vm_map_entry_t  next = entry->vme_next;
                   3277: 
                   3278:                while(entry->is_sub_map) {
                   3279:                        vm_offset_t     sub_start;
                   3280:                        vm_offset_t     sub_end;
                   3281:                        vm_offset_t     local_end;
                   3282: 
                   3283:                        if (entry->in_transition) {
                   3284: 
                   3285:                         /*
                   3286:                          * Say that we are waiting, and wait for entry.
                   3287:                          */
                   3288:                                entry->needs_wakeup = TRUE;
                   3289:                                vm_map_entry_wait(dst_map, THREAD_UNINT);
                   3290: 
                   3291:                                goto start_pass_1;
                   3292:                        }
                   3293: 
                   3294:                        local_end = entry->vme_end;
                   3295:                        if (!(entry->needs_copy)) {
                   3296:                                /* if needs_copy we are a COW submap */
                   3297:                                /* in such a case we just replace so */
                   3298:                                /* there is no need for the follow-  */
                   3299:                                /* ing check.                        */
                   3300:                                encountered_sub_map = TRUE;
                   3301:                                sub_start = entry->offset;
                   3302: 
                   3303:                                if(entry->vme_end < dst_end)
                   3304:                                        sub_end = entry->vme_end;
                   3305:                                else 
                   3306:                                        sub_end = dst_end;
                   3307:                                sub_end -= entry->vme_start;
                   3308:                                sub_end += entry->offset;
                   3309:                                vm_map_unlock(dst_map);
                   3310:                        
                   3311:                                kr = vm_map_overwrite_submap_recurse(
                   3312:                                        entry->object.sub_map,
                   3313:                                        sub_start,
                   3314:                                        sub_end - sub_start);
                   3315:                                if(kr != KERN_SUCCESS)
                   3316:                                        return kr;
                   3317:                                vm_map_lock(dst_map);
                   3318:                        }
                   3319: 
                   3320:                        if (dst_end <= entry->vme_end)
                   3321:                                goto start_overwrite;
                   3322:                        if(!vm_map_lookup_entry(dst_map, local_end, 
                   3323:                                                &entry)) {
                   3324:                                vm_map_unlock(dst_map);
                   3325:                                return(KERN_INVALID_ADDRESS);
                   3326:                        }
                   3327:                        next = entry->vme_next;
                   3328:                }
                   3329: 
                   3330:                if ( ! (entry->protection & VM_PROT_WRITE)) {
                   3331:                        vm_map_unlock(dst_map);
                   3332:                        return(KERN_PROTECTION_FAILURE);
                   3333:                }
                   3334: 
                   3335:                /*
                   3336:                 *      If the entry is in transition, we must wait
                   3337:                 *      for it to exit that state.  Anything could happen
                   3338:                 *      when we unlock the map, so start over.
                   3339:                 */
                   3340:                 if (entry->in_transition) {
                   3341: 
                   3342:                         /*
                   3343:                          * Say that we are waiting, and wait for entry.
                   3344:                          */
                   3345:                         entry->needs_wakeup = TRUE;
                   3346:                         vm_map_entry_wait(dst_map, THREAD_UNINT);
                   3347: 
                   3348:                        goto start_pass_1;
                   3349:                }
                   3350: 
                   3351: /*
                   3352:  *             our range is contained completely within this map entry
                   3353:  */
                   3354:                if (dst_end <= entry->vme_end)
                   3355:                        break;
                   3356: /*
                   3357:  *             check that range specified is contiguous region
                   3358:  */
                   3359:                if ((next == vm_map_to_entry(dst_map)) ||
                   3360:                    (next->vme_start != entry->vme_end)) {
                   3361:                        vm_map_unlock(dst_map);
                   3362:                        return(KERN_INVALID_ADDRESS);
                   3363:                }
                   3364: 
                   3365: 
                   3366:                /*
                   3367:                 *      Check for permanent objects in the destination.
                   3368:                 */
                   3369:                if ((entry->object.vm_object != VM_OBJECT_NULL) &&
                   3370:                           ((!entry->object.vm_object->internal) ||
                   3371:                           (entry->object.vm_object->true_share))) {
                   3372:                        if(encountered_sub_map) {
                   3373:                                vm_map_unlock(dst_map);
                   3374:                                return(KERN_INVALID_ADDRESS);
                   3375:                        }
                   3376:                        contains_permanent_objects = TRUE;
                   3377:                }
                   3378: 
                   3379:                entry = next;
                   3380:        }/* for */
                   3381: 
                   3382: start_overwrite:
                   3383:        /*
                   3384:         *      If there are permanent objects in the destination, then
                   3385:         *      the copy cannot be interrupted.
                   3386:         */
                   3387: 
                   3388:        if (interruptible && contains_permanent_objects) {
                   3389:                vm_map_unlock(dst_map);
                   3390:                return(KERN_FAILURE);   /* XXX */
                   3391:        }
                   3392: 
                   3393:        /*
                   3394:         *
                   3395:         *      Make a second pass, overwriting the data
                   3396:         *      At the beginning of each loop iteration,
                   3397:         *      the next entry to be overwritten is "tmp_entry"
                   3398:         *      (initially, the value returned from the lookup above),
                   3399:         *      and the starting address expected in that entry
                   3400:         *      is "start".
                   3401:         */
                   3402: 
                   3403:        total_size = copy->size;
                   3404:        if(encountered_sub_map) {
                   3405:                copy_size = 0;
                   3406:                /* re-calculate tmp_entry since we've had the map */
                   3407:                /* unlocked */
                   3408:                if (!vm_map_lookup_entry( dst_map, dst_addr, &tmp_entry)) {
                   3409:                        vm_map_unlock(dst_map);
                   3410:                        return(KERN_INVALID_ADDRESS);
                   3411:                }
                   3412:        } else {
                   3413:                copy_size = copy->size;
                   3414:        }
                   3415:        
                   3416:        base_addr = dst_addr;
                   3417:        while(TRUE) {
                   3418:                /* deconstruct the copy object and do in parts */
                   3419:                /* only in sub_map, interruptable case */
                   3420:                vm_map_entry_t  copy_entry;
                   3421:                vm_map_entry_t  previous_prev;
                   3422:                vm_map_entry_t  next_copy;
                   3423:                int             nentries;
                   3424:                int             remaining_entries;
                   3425:                int             new_offset;
                   3426:        
                   3427:                for (entry = tmp_entry; copy_size == 0;) {
                   3428:                        vm_map_entry_t  next;
                   3429: 
                   3430:                        next = entry->vme_next;
                   3431: 
                   3432:                        /* tmp_entry and base address are moved along */
                   3433:                        /* each time we encounter a sub-map.  Otherwise */
                   3434:                        /* entry can outpase tmp_entry, and the copy_size */
                   3435:                        /* may reflect the distance between them */
                   3436:                        /* if the current entry is found to be in transition */
                   3437:                        /* we will start over at the beginning or the last */
                   3438:                        /* encounter of a submap as dictated by base_addr */
                   3439:                        /* we will zero copy_size accordingly. */
                   3440:                        if (entry->in_transition) {
                   3441:                                        /*
                   3442:                                         * Say that we are waiting, and wait for entry.
                   3443:                                         */
                   3444:                                        entry->needs_wakeup = TRUE;
                   3445:                                        vm_map_entry_wait(dst_map, THREAD_UNINT);
                   3446: 
                   3447:                                vm_map_lock(dst_map);
                   3448:                                if(!vm_map_lookup_entry(dst_map, base_addr, 
                   3449:                                                                &tmp_entry)) {
                   3450:                                        vm_map_unlock(dst_map);
                   3451:                                        return(KERN_INVALID_ADDRESS);
                   3452:                                }
                   3453:                                copy_size = 0;
                   3454:                                entry = tmp_entry;
                   3455:                                continue;
                   3456:                        }
                   3457:                        if(entry->is_sub_map) {
                   3458:                                vm_offset_t     sub_start;
                   3459:                                vm_offset_t     sub_end;
                   3460:                                vm_offset_t     local_end;
                   3461: 
                   3462:                                if (entry->needs_copy) {
                   3463:                                        /* if this is a COW submap */
                   3464:                                        /* just back the range with a */
                   3465:                                        /* anonymous entry */
                   3466:                                        if(entry->vme_end < dst_end)
                   3467:                                                sub_end = entry->vme_end;
                   3468:                                        else 
                   3469:                                                sub_end = dst_end;
                   3470:                                        if(entry->vme_start < base_addr)
                   3471:                                                sub_start = base_addr;
                   3472:                                        else 
                   3473:                                                sub_start = entry->vme_start;
                   3474:                                        vm_map_clip_end(
                   3475:                                                dst_map, entry, sub_end);
                   3476:                                        vm_map_clip_start(
                   3477:                                                dst_map, entry, sub_start);
                   3478:                                        entry->is_sub_map = FALSE;
                   3479:                                        vm_map_deallocate(
                   3480:                                                entry->object.sub_map);
                   3481:                                        entry->object.sub_map = NULL;
                   3482:                                        entry->is_shared = FALSE;
                   3483:                                        entry->needs_copy = FALSE;
                   3484:                                        entry->offset = 0;
                   3485:                                        entry->protection = VM_PROT_ALL;
                   3486:                                        entry->max_protection = VM_PROT_ALL;
                   3487:                                        entry->wired_count = 0;
                   3488:                                        entry->user_wired_count = 0;
                   3489:                                        if(entry->inheritance 
                   3490:                                                        == VM_INHERIT_SHARE) 
                   3491:                                           entry->inheritance = VM_INHERIT_COPY;
                   3492:                                        continue;
                   3493:                                }
                   3494:                                /* first take care of any non-sub_map */
                   3495:                                /* entries to send */
                   3496:                                if(base_addr < entry->vme_start) {
                   3497:                                        /* stuff to send */
                   3498:                                        copy_size = 
                   3499:                                                entry->vme_start - base_addr;
                   3500:                                        break;
                   3501:                                }
                   3502:                                sub_start = entry->offset;
                   3503: 
                   3504:                                if(entry->vme_end < dst_end)
                   3505:                                        sub_end = entry->vme_end;
                   3506:                                else 
                   3507:                                        sub_end = dst_end;
                   3508:                                sub_end -= entry->vme_start;
                   3509:                                sub_end += entry->offset;
                   3510:                                local_end = entry->vme_end;
                   3511:                                vm_map_unlock(dst_map);
                   3512:                                copy_size = sub_end - sub_start;
                   3513: 
                   3514:                                /* adjust the copy object */
                   3515:                                if (total_size > copy_size) {
                   3516:                                        vm_size_t       local_size = 0;
                   3517:                                        vm_size_t       entry_size;
                   3518: 
                   3519:                                   nentries = 1;
                   3520:                                   new_offset = copy->offset;
                   3521:                                   copy_entry = vm_map_copy_first_entry(copy);
                   3522:                                   while(copy_entry != 
                   3523:                                                 vm_map_copy_to_entry(copy)){
                   3524:                                       entry_size = copy_entry->vme_end - 
                   3525:                                                      copy_entry->vme_start;
                   3526:                                       if((local_size < copy_size) &&
                   3527:                                                ((local_size + entry_size) 
                   3528:                                                 >= copy_size)) {
                   3529:                                          vm_map_copy_clip_end(copy, 
                   3530:                                                 copy_entry, 
                   3531:                                                 copy_entry->vme_start +
                   3532:                                                 (copy_size - local_size));
                   3533:                                          entry_size = copy_entry->vme_end - 
                   3534:                                                         copy_entry->vme_start;
                   3535:                                          local_size += entry_size;
                   3536:                                          new_offset += entry_size;
                   3537:                                       }
                   3538:                                       if(local_size >= copy_size) {
                   3539:                                          next_copy = copy_entry->vme_next;
                   3540:                                          copy_entry->vme_next = 
                   3541:                                                    vm_map_copy_to_entry(copy);
                   3542:                                          previous_prev = 
                   3543:                                                   copy->cpy_hdr.links.prev;
                   3544:                                          copy->cpy_hdr.links.prev = copy_entry;
                   3545:                                          copy->size = copy_size;
                   3546:                                          remaining_entries = 
                   3547:                                                        copy->cpy_hdr.nentries;
                   3548:                                          remaining_entries -= nentries;
                   3549:                                          copy->cpy_hdr.nentries = nentries;
                   3550:                                          break;
                   3551:                                       } else {
                   3552:                                          local_size += entry_size;
                   3553:                                          new_offset += entry_size;
                   3554:                                          nentries++;
                   3555:                                       }
                   3556:                                       copy_entry = copy_entry->vme_next;
                   3557:                                   }
                   3558:                                }
                   3559:                        
                   3560:                                kr = vm_map_copy_overwrite(
                   3561:                                        entry->object.sub_map,
                   3562:                                        sub_start,
                   3563:                                        copy,
                   3564:                                        interruptible);
                   3565:                                if(kr != KERN_SUCCESS) {
                   3566:                                        if(next_copy != NULL) {
                   3567:                                           copy->cpy_hdr.nentries += 
                   3568:                                                           remaining_entries;
                   3569:                                           copy->cpy_hdr.links.prev->vme_next = 
                   3570:                                                           next_copy;
                   3571:                                           copy->cpy_hdr.links.prev 
                   3572:                                                           = previous_prev;
                   3573:                                           copy->size = total_size;
                   3574:                                        }
                   3575:                                        return kr;
                   3576:                                }
                   3577:                                if (dst_end <= local_end) {
                   3578:                                        return(KERN_SUCCESS);
                   3579:                                }
                   3580:                                /* otherwise copy no longer exists, it was */
                   3581:                                /* destroyed after successful copy_overwrite */
                   3582:                                copy = (vm_map_copy_t) 
                   3583:                                                zalloc(vm_map_copy_zone);
                   3584:                                vm_map_copy_first_entry(copy) =
                   3585:                                   vm_map_copy_last_entry(copy) =
                   3586:                                   vm_map_copy_to_entry(copy);
                   3587:                                copy->type = VM_MAP_COPY_ENTRY_LIST;
                   3588:                                copy->offset = new_offset;
                   3589: 
                   3590:                                total_size -= copy_size;
                   3591:                                copy_size = 0;
                   3592:                                /* put back remainder of copy in container */
                   3593:                                if(next_copy != NULL) {
                   3594:                                   copy->cpy_hdr.nentries = remaining_entries;
                   3595:                                   copy->cpy_hdr.links.next = next_copy;
                   3596:                                   copy->cpy_hdr.links.prev = previous_prev;
                   3597:                                   copy->size = total_size;
                   3598:                                   next_copy->vme_prev = 
                   3599:                                                 vm_map_copy_to_entry(copy);
                   3600:                                   next_copy = NULL;
                   3601:                                }
                   3602:                                base_addr = local_end;
                   3603:                                vm_map_lock(dst_map);
                   3604:                                if(!vm_map_lookup_entry(dst_map, 
                   3605:                                                local_end, &tmp_entry)) {
                   3606:                                        vm_map_unlock(dst_map);
                   3607:                                        return(KERN_INVALID_ADDRESS);
                   3608:                                }
                   3609:                                entry = tmp_entry;
                   3610:                                continue;
                   3611:                        } 
                   3612:                        if (dst_end <= entry->vme_end) {
                   3613:                                copy_size = dst_end - base_addr;
                   3614:                                break;
                   3615:                        }
                   3616: 
                   3617:                        if ((next == vm_map_to_entry(dst_map)) ||
                   3618:                                    (next->vme_start != entry->vme_end)) {
                   3619:                                vm_map_unlock(dst_map);
                   3620:                                return(KERN_INVALID_ADDRESS);
                   3621:                        }
                   3622: 
                   3623:                        entry = next;
                   3624:                }/* for */
                   3625: 
                   3626:                next_copy = NULL;
                   3627:                nentries = 1;
                   3628: 
                   3629:                /* adjust the copy object */
                   3630:                if (total_size > copy_size) {
                   3631:                        vm_size_t       local_size = 0;
                   3632:                        vm_size_t       entry_size;
                   3633: 
                   3634:                        new_offset = copy->offset;
                   3635:                        copy_entry = vm_map_copy_first_entry(copy);
                   3636:                        while(copy_entry != vm_map_copy_to_entry(copy)) {
                   3637:                                entry_size = copy_entry->vme_end - 
                   3638:                                                copy_entry->vme_start;
                   3639:                                if((local_size < copy_size) &&
                   3640:                                                ((local_size + entry_size) 
                   3641:                                                >= copy_size)) {
                   3642:                                        vm_map_copy_clip_end(copy, copy_entry, 
                   3643:                                                copy_entry->vme_start +
                   3644:                                                (copy_size - local_size));
                   3645:                                        entry_size = copy_entry->vme_end - 
                   3646:                                                   copy_entry->vme_start;
                   3647:                                        local_size += entry_size;
                   3648:                                        new_offset += entry_size;
                   3649:                                }
                   3650:                                if(local_size >= copy_size) {
                   3651:                                        next_copy = copy_entry->vme_next;
                   3652:                                        copy_entry->vme_next = 
                   3653:                                                vm_map_copy_to_entry(copy);
                   3654:                                        previous_prev = 
                   3655:                                                copy->cpy_hdr.links.prev;
                   3656:                                        copy->cpy_hdr.links.prev = copy_entry;
                   3657:                                        copy->size = copy_size;
                   3658:                                        remaining_entries = 
                   3659:                                                copy->cpy_hdr.nentries;
                   3660:                                        remaining_entries -= nentries;
                   3661:                                        copy->cpy_hdr.nentries = nentries;
                   3662:                                        break;
                   3663:                                } else {
                   3664:                                        local_size += entry_size;
                   3665:                                        new_offset += entry_size;
                   3666:                                        nentries++;
                   3667:                                }
                   3668:                                copy_entry = copy_entry->vme_next;
                   3669:                        }
                   3670:                }
                   3671: 
                   3672:                if (aligned) {
                   3673:                        if ((kr =  vm_map_copy_overwrite_aligned( 
                   3674:                                dst_map, tmp_entry,
                   3675:                                copy, base_addr)) != KERN_SUCCESS) {
                   3676:                                if(next_copy != NULL) {
                   3677:                                        copy->cpy_hdr.nentries += 
                   3678:                                                           remaining_entries;
                   3679:                                        copy->cpy_hdr.links.prev->vme_next = 
                   3680:                                                           next_copy;
                   3681:                                        copy->cpy_hdr.links.prev = 
                   3682:                                                        previous_prev;
                   3683:                                        copy->size += copy_size;
                   3684:                                }
                   3685:                                return kr;
                   3686:                        }
                   3687:                        vm_map_unlock(dst_map);
                   3688:                } else {
                   3689:                /*
                   3690:                 * Performance gain:
                   3691:                 *
                   3692:                 * if the copy and dst address are misaligned but the same
                   3693:                 * offset within the page we can copy_not_aligned the
                   3694:                 * misaligned parts and copy aligned the rest.  If they are
                   3695:                 * aligned but len is unaligned we simply need to copy
                   3696:                 * the end bit unaligned.  We'll need to split the misaligned
                   3697:                 * bits of the region in this case !
                   3698:                 */
                   3699:                /* ALWAYS UNLOCKS THE dst_map MAP */
                   3700:                        if ((kr =  vm_map_copy_overwrite_unaligned( dst_map,
                   3701:                                tmp_entry, copy, base_addr)) != KERN_SUCCESS) {
                   3702:                                if(next_copy != NULL) {
                   3703:                                        copy->cpy_hdr.nentries +=
                   3704:                                                             remaining_entries;
                   3705:                                        copy->cpy_hdr.links.prev->vme_next = 
                   3706:                                                             next_copy;
                   3707:                                        copy->cpy_hdr.links.prev = 
                   3708:                                                previous_prev;
                   3709:                                        copy->size += copy_size;
                   3710:                                }
                   3711:                                return kr;
                   3712:                        }
                   3713:                }
                   3714:                total_size -= copy_size;
                   3715:                if(total_size == 0)
                   3716:                        break;
                   3717:                base_addr += copy_size;
                   3718:                copy_size = 0;
                   3719:                copy->offset = new_offset;
                   3720:                if(next_copy != NULL) {
                   3721:                        copy->cpy_hdr.nentries = remaining_entries;
                   3722:                        copy->cpy_hdr.links.next = next_copy;
                   3723:                        copy->cpy_hdr.links.prev = previous_prev;
                   3724:                        next_copy->vme_prev = vm_map_copy_to_entry(copy);
                   3725:                        copy->size = total_size;
                   3726:                }
                   3727:                vm_map_lock(dst_map);
                   3728:                while(TRUE) {
                   3729:                        if (!vm_map_lookup_entry(dst_map, 
                   3730:                                                base_addr, &tmp_entry)) {
                   3731:                                vm_map_unlock(dst_map);
                   3732:                                return(KERN_INVALID_ADDRESS);
                   3733:                        }
                   3734:                        if (tmp_entry->in_transition) {
                   3735:                                        entry->needs_wakeup = TRUE;
                   3736:                                        vm_map_entry_wait(dst_map, THREAD_UNINT);
                   3737:                        } else {
                   3738:                                break;
                   3739:                        }
                   3740:                }
                   3741:                vm_map_clip_start(dst_map, tmp_entry, trunc_page(base_addr));
                   3742: 
                   3743:                entry = tmp_entry;
                   3744:        } /* while */
                   3745: 
                   3746:        /*
                   3747:         *      Throw away the vm_map_copy object
                   3748:         */
                   3749:        vm_map_copy_discard(copy);
                   3750: 
                   3751:        return(KERN_SUCCESS);
                   3752: }/* vm_map_copy_overwrite */
                   3753: 
                   3754: /*
                   3755:  *     Routine: vm_map_copy_overwrite_unaligned
                   3756:  *
                   3757:  *     Decription:
                   3758:  *     Physically copy unaligned data
                   3759:  *
                   3760:  *     Implementation:
                   3761:  *     Unaligned parts of pages have to be physically copied.  We use
                   3762:  *     a modified form of vm_fault_copy (which understands none-aligned
                   3763:  *     page offsets and sizes) to do the copy.  We attempt to copy as
                   3764:  *     much memory in one go as possibly, however vm_fault_copy copies
                   3765:  *     within 1 memory object so we have to find the smaller of "amount left"
                   3766:  *     "source object data size" and "target object data size".  With
                   3767:  *     unaligned data we don't need to split regions, therefore the source
                   3768:  *     (copy) object should be one map entry, the target range may be split
                   3769:  *     over multiple map entries however.  In any event we are pessimistic
                   3770:  *     about these assumptions.
                   3771:  *
                   3772:  *     Assumptions:
                   3773:  *     dst_map is locked on entry and is return locked on success,
                   3774:  *     unlocked on error.
                   3775:  */
                   3776: 
                   3777: kern_return_t
                   3778: vm_map_copy_overwrite_unaligned(
                   3779:        vm_map_t        dst_map,
                   3780:        vm_map_entry_t  entry,
                   3781:        vm_map_copy_t   copy,
                   3782:        vm_offset_t     start)
                   3783: {
                   3784:        vm_map_entry_t          copy_entry = vm_map_copy_first_entry(copy);
                   3785:        vm_map_version_t        version;
                   3786:        vm_object_t             dst_object;
                   3787:        vm_offset_t             dst_offset;
                   3788:        vm_offset_t             src_offset;
                   3789:        vm_offset_t             entry_offset;
                   3790:        vm_offset_t             entry_end;
                   3791:        vm_size_t               src_size,
                   3792:                                dst_size,
                   3793:                                copy_size,
                   3794:                                amount_left;
                   3795:        kern_return_t           kr = KERN_SUCCESS;
                   3796: 
                   3797:        vm_map_lock_write_to_read(dst_map);
                   3798: 
                   3799:        src_offset = copy->offset - trunc_page(copy->offset);
                   3800:        amount_left = copy->size;
                   3801: /*
                   3802:  *     unaligned so we never clipped this entry, we need the offset into
                   3803:  *     the vm_object not just the data.
                   3804:  */    
                   3805:        while (amount_left > 0) {
                   3806: 
                   3807:                /* "start" must be within the current map entry */
                   3808:                assert ((start>=entry->vme_start) && (start<entry->vme_end));
                   3809: 
                   3810:                dst_offset = start - entry->vme_start;
                   3811: 
                   3812:                dst_size = entry->vme_end - start;
                   3813: 
                   3814:                src_size = copy_entry->vme_end -
                   3815:                        (copy_entry->vme_start + src_offset);
                   3816: 
                   3817:                if (dst_size < src_size) {
                   3818: /*
                   3819:  *                     we can only copy dst_size bytes before
                   3820:  *                     we have to get the next destination entry
                   3821:  */
                   3822:                        copy_size = dst_size;
                   3823:                } else {
                   3824: /*
                   3825:  *                     we can only copy src_size bytes before
                   3826:  *                     we have to get the next source copy entry
                   3827:  */
                   3828:                        copy_size = src_size;
                   3829:                }
                   3830: 
                   3831:                if (copy_size > amount_left) {
                   3832:                        copy_size = amount_left;
                   3833:                }
                   3834: /*
                   3835:  *             Entry needs copy, create a shadow shadow object for
                   3836:  *             copy on write region.
                   3837:  */
                   3838:                if (entry->needs_copy &&
                   3839:                         ((entry->protection & VM_PROT_WRITE) != 0))
                   3840:                {
                   3841:                        if (vm_map_lock_read_to_write(dst_map)) {
                   3842:                                vm_map_lock_read(dst_map);
                   3843:                                goto RetryLookup;
                   3844:                        }
                   3845:                        vm_object_shadow(&entry->object.vm_object,
                   3846:                                        &entry->offset,
                   3847:                                        (vm_size_t)(entry->vme_end
                   3848:                                                - entry->vme_start));
                   3849:                        entry->needs_copy = FALSE;
                   3850:                        vm_map_lock_write_to_read(dst_map);
                   3851:                }
                   3852:                dst_object = entry->object.vm_object;
                   3853: /*
                   3854:  *             unlike with the virtual (aligned) copy we're going
                   3855:  *             to fault on it therefore we need a target object.
                   3856:  */
                   3857:                 if (dst_object == VM_OBJECT_NULL) {
                   3858:                        if (vm_map_lock_read_to_write(dst_map)) {
                   3859:                                vm_map_lock_read(dst_map);
                   3860:                                goto RetryLookup;
                   3861:                        }
                   3862:                        dst_object = vm_object_allocate((vm_size_t)
                   3863:                                        entry->vme_end - entry->vme_start);
                   3864:                        entry->object.vm_object = dst_object;
                   3865:                        entry->offset = 0;
                   3866:                        vm_map_lock_write_to_read(dst_map);
                   3867:                }
                   3868: /*
                   3869:  *             Take an object reference and unlock map. The "entry" may
                   3870:  *             disappear or change when the map is unlocked.
                   3871:  */
                   3872:                vm_object_reference(dst_object);
                   3873:                version.main_timestamp = dst_map->timestamp;
                   3874:                entry_offset = entry->offset;
                   3875:                entry_end = entry->vme_end;
                   3876:                vm_map_unlock_read(dst_map);
                   3877: /*
                   3878:  *             Copy as much as possible in one pass
                   3879:  */
                   3880:                kr = vm_fault_copy(
                   3881:                        copy_entry->object.vm_object,
                   3882:                        copy_entry->offset + src_offset,
                   3883:                        &copy_size,
                   3884:                        dst_object,
                   3885:                        entry_offset + dst_offset,
                   3886:                        dst_map,
                   3887:                        &version,
                   3888:                        THREAD_UNINT );
                   3889: 
                   3890:                start += copy_size;
                   3891:                src_offset += copy_size;
                   3892:                amount_left -= copy_size;
                   3893: /*
                   3894:  *             Release the object reference
                   3895:  */
                   3896:                vm_object_deallocate(dst_object);
                   3897: /*
                   3898:  *             If a hard error occurred, return it now
                   3899:  */
                   3900:                if (kr != KERN_SUCCESS)
                   3901:                        return kr;
                   3902: 
                   3903:                if ((copy_entry->vme_start + src_offset) == copy_entry->vme_end
                   3904:                        || amount_left == 0)
                   3905:                {
                   3906: /*
                   3907:  *                     all done with this copy entry, dispose.
                   3908:  */
                   3909:                        vm_map_copy_entry_unlink(copy, copy_entry);
                   3910:                        vm_object_deallocate(copy_entry->object.vm_object);
                   3911:                        vm_map_copy_entry_dispose(copy, copy_entry);
                   3912: 
                   3913:                        if ((copy_entry = vm_map_copy_first_entry(copy))
                   3914:                                == vm_map_copy_to_entry(copy) && amount_left) {
                   3915: /*
                   3916:  *                             not finished copying but run out of source
                   3917:  */
                   3918:                                return KERN_INVALID_ADDRESS;
                   3919:                        }
                   3920:                        src_offset = 0;
                   3921:                }
                   3922: 
                   3923:                if (amount_left == 0)
                   3924:                        return KERN_SUCCESS;
                   3925: 
                   3926:                vm_map_lock_read(dst_map);
                   3927:                if (version.main_timestamp == dst_map->timestamp) {
                   3928:                        if (start == entry_end) {
                   3929: /*
                   3930:  *                             destination region is split.  Use the version
                   3931:  *                             information to avoid a lookup in the normal
                   3932:  *                             case.
                   3933:  */
                   3934:                                entry = entry->vme_next;
                   3935: /*
                   3936:  *                             should be contiguous. Fail if we encounter
                   3937:  *                             a hole in the destination.
                   3938:  */
                   3939:                                if (start != entry->vme_start) {
                   3940:                                        vm_map_unlock_read(dst_map);
                   3941:                                        return KERN_INVALID_ADDRESS ;
                   3942:                                }
                   3943:                        }
                   3944:                } else {
                   3945: /*
                   3946:  *                     Map version check failed.
                   3947:  *                     we must lookup the entry because somebody
                   3948:  *                     might have changed the map behind our backs.
                   3949:  */
                   3950: RetryLookup:
                   3951:                        if (!vm_map_lookup_entry(dst_map, start, &entry))
                   3952:                        {
                   3953:                                vm_map_unlock_read(dst_map);
                   3954:                                return KERN_INVALID_ADDRESS ;
                   3955:                        }
                   3956:                }
                   3957:        }/* while */
                   3958: 
                   3959:        /* NOTREACHED ?? */
                   3960:        vm_map_unlock_read(dst_map);
                   3961: 
                   3962:        return KERN_SUCCESS;
                   3963: }/* vm_map_copy_overwrite_unaligned */
                   3964: 
                   3965: /*
                   3966:  *     Routine:        vm_map_copy_overwrite_aligned
                   3967:  *
                   3968:  *     Description:
                   3969:  *     Does all the vm_trickery possible for whole pages.
                   3970:  *
                   3971:  *     Implementation:
                   3972:  *
                   3973:  *     If there are no permanent objects in the destination,
                   3974:  *     and the source and destination map entry zones match,
                   3975:  *     and the destination map entry is not shared,
                   3976:  *     then the map entries can be deleted and replaced
                   3977:  *     with those from the copy.  The following code is the
                   3978:  *     basic idea of what to do, but there are lots of annoying
                   3979:  *     little details about getting protection and inheritance
                   3980:  *     right.  Should add protection, inheritance, and sharing checks
                   3981:  *     to the above pass and make sure that no wiring is involved.
                   3982:  */
                   3983: 
                   3984: kern_return_t
                   3985: vm_map_copy_overwrite_aligned(
                   3986:        vm_map_t        dst_map,
                   3987:        vm_map_entry_t  tmp_entry,
                   3988:        vm_map_copy_t   copy,
                   3989:        vm_offset_t     start)
                   3990: {
                   3991:        vm_object_t     object;
                   3992:        vm_map_entry_t  copy_entry;
                   3993:        vm_size_t       copy_size;
                   3994:        vm_size_t       size;
                   3995:        vm_map_entry_t  entry;
                   3996:                
                   3997:        while ((copy_entry = vm_map_copy_first_entry(copy))
                   3998:                != vm_map_copy_to_entry(copy))
                   3999:        {
                   4000:                copy_size = (copy_entry->vme_end - copy_entry->vme_start);
                   4001:                
                   4002:                entry = tmp_entry;
                   4003:                size = (entry->vme_end - entry->vme_start);
                   4004:                /*
                   4005:                 *      Make sure that no holes popped up in the
                   4006:                 *      address map, and that the protection is
                   4007:                 *      still valid, in case the map was unlocked
                   4008:                 *      earlier.
                   4009:                 */
                   4010: 
                   4011:                if ((entry->vme_start != start) || (entry->is_sub_map)) {
                   4012:                        vm_map_unlock(dst_map);
                   4013:                        return(KERN_INVALID_ADDRESS);
                   4014:                }
                   4015:                assert(entry != vm_map_to_entry(dst_map));
                   4016: 
                   4017:                /*
                   4018:                 *      Check protection again
                   4019:                 */
                   4020: 
                   4021:                if ( ! (entry->protection & VM_PROT_WRITE)) {
                   4022:                        vm_map_unlock(dst_map);
                   4023:                        return(KERN_PROTECTION_FAILURE);
                   4024:                }
                   4025: 
                   4026:                /*
                   4027:                 *      Adjust to source size first
                   4028:                 */
                   4029: 
                   4030:                if (copy_size < size) {
                   4031:                        vm_map_clip_end(dst_map, entry, entry->vme_start + copy_size);
                   4032:                        size = copy_size;
                   4033:                }
                   4034: 
                   4035:                /*
                   4036:                 *      Adjust to destination size
                   4037:                 */
                   4038: 
                   4039:                if (size < copy_size) {
                   4040:                        vm_map_copy_clip_end(copy, copy_entry,
                   4041:                                copy_entry->vme_start + size);
                   4042:                        copy_size = size;
                   4043:                }
                   4044: 
                   4045:                assert((entry->vme_end - entry->vme_start) == size);
                   4046:                assert((tmp_entry->vme_end - tmp_entry->vme_start) == size);
                   4047:                assert((copy_entry->vme_end - copy_entry->vme_start) == size);
                   4048: 
                   4049:                /*
                   4050:                 *      If the destination contains temporary unshared memory,
                   4051:                 *      we can perform the copy by throwing it away and
                   4052:                 *      installing the source data.
                   4053:                 */
                   4054: 
                   4055:                object = entry->object.vm_object;
                   4056:                if ((!entry->is_shared && 
                   4057:                    ((object == VM_OBJECT_NULL) || 
                   4058:                    (object->internal && !object->true_share))) ||
                   4059:                    entry->needs_copy) {
                   4060:                        vm_object_t     old_object = entry->object.vm_object;
                   4061:                        vm_offset_t     old_offset = entry->offset;
                   4062:                        vm_offset_t     offset;
                   4063: 
                   4064:                        /*
                   4065:                         * Ensure that the source and destination aren't
                   4066:                         * identical
                   4067:                         */
                   4068:                        if (old_object == copy_entry->object.vm_object &&
                   4069:                            old_offset == copy_entry->offset) {
                   4070:                                vm_map_copy_entry_unlink(copy, copy_entry);
                   4071:                                vm_map_copy_entry_dispose(copy, copy_entry);
                   4072: 
                   4073:                                if (old_object != VM_OBJECT_NULL)
                   4074:                                        vm_object_deallocate(old_object);
                   4075: 
                   4076:                                start = tmp_entry->vme_end;
                   4077:                                tmp_entry = tmp_entry->vme_next;
                   4078:                                continue;
                   4079:                        }
                   4080: 
                   4081:                        entry->object = copy_entry->object;
                   4082:                        object = entry->object.vm_object;
                   4083:                        offset = entry->offset = copy_entry->offset;
                   4084:                        entry->needs_copy = copy_entry->needs_copy;
                   4085:                        entry->wired_count = 0;
                   4086:                        entry->user_wired_count = 0;
                   4087: 
                   4088:                        vm_map_copy_entry_unlink(copy, copy_entry);
                   4089:                        vm_map_copy_entry_dispose(copy, copy_entry);
                   4090: 
                   4091:                        if (old_object != VM_OBJECT_NULL) {
                   4092:                                vm_object_pmap_protect(
                   4093:                                        old_object,
                   4094:                                        old_offset,
                   4095:                                        size,
                   4096:                                        dst_map->pmap,
                   4097:                                        tmp_entry->vme_start,
                   4098:                                        VM_PROT_NONE);
                   4099: 
                   4100:                                vm_object_deallocate(old_object);
                   4101:                        }
                   4102: 
                   4103:                        /*
                   4104:                         * Try to aggressively enter physical mappings
                   4105:                         * (but avoid uninstantiated objects)
                   4106:                         */
                   4107:                        if (object != VM_OBJECT_NULL) {
                   4108:                            vm_offset_t va = entry->vme_start;
                   4109: 
                   4110:                            while (va < entry->vme_end) {
                   4111:                                register vm_page_t      m;
                   4112:                                vm_prot_t               prot;
                   4113: 
                   4114:                                /*
                   4115:                                 * Look for the page in the top object
                   4116:                                 */
                   4117:                                prot = entry->protection;
                   4118:                                vm_object_lock(object);
                   4119:                                vm_object_paging_begin(object);
                   4120: 
                   4121:                                if ((m = vm_page_lookup(object,offset)) !=
                   4122:                                    VM_PAGE_NULL && !m->busy && 
                   4123:                                    !m->fictitious &&
                   4124:                                    (!m->unusual || (!m->error &&
                   4125:                                        !m->restart && !m->absent &&
                   4126:                                         (prot & m->page_lock) == 0))) {
                   4127:                                        
                   4128:                                        m->busy = TRUE;
                   4129:                                        vm_object_unlock(object);
                   4130:                                        
                   4131:                                        /* 
                   4132:                                         * Honor COW obligations
                   4133:                                         */
                   4134:                                        if (entry->needs_copy)
                   4135:                                                prot &= ~VM_PROT_WRITE;
                   4136: 
                   4137:                                        PMAP_ENTER(dst_map->pmap, va, m,
                   4138:                                                   prot, FALSE);
                   4139:                
                   4140:                                        vm_object_lock(object);
                   4141:                                        vm_page_lock_queues();
                   4142:                                        if (!m->active && !m->inactive)
                   4143:                                                vm_page_activate(m);
                   4144:                                        vm_page_unlock_queues();
                   4145:                                         PAGE_WAKEUP_DONE(m);
                   4146:                                }
                   4147:                                vm_object_paging_end(object);
                   4148:                                vm_object_unlock(object);
                   4149: 
                   4150:                                offset += PAGE_SIZE;
                   4151:                                va += PAGE_SIZE;
                   4152:                            } /* end while (va < entry->vme_end) */
                   4153:                        } /* end if (object) */
                   4154: 
                   4155:                        /*
                   4156:                         *      Set up for the next iteration.  The map
                   4157:                         *      has not been unlocked, so the next
                   4158:                         *      address should be at the end of this
                   4159:                         *      entry, and the next map entry should be
                   4160:                         *      the one following it.
                   4161:                         */
                   4162: 
                   4163:                        start = tmp_entry->vme_end;
                   4164:                        tmp_entry = tmp_entry->vme_next;
                   4165:                } else {
                   4166:                        vm_map_version_t        version;
                   4167:                        vm_object_t             dst_object = entry->object.vm_object;
                   4168:                        vm_offset_t             dst_offset = entry->offset;
                   4169:                        kern_return_t           r;
                   4170: 
                   4171:                        /*
                   4172:                         *      Take an object reference, and record
                   4173:                         *      the map version information so that the
                   4174:                         *      map can be safely unlocked.
                   4175:                         */
                   4176: 
                   4177:                        vm_object_reference(dst_object);
                   4178: 
                   4179:                        version.main_timestamp = dst_map->timestamp;
                   4180: 
                   4181:                        vm_map_unlock(dst_map);
                   4182: 
                   4183:                        /*
                   4184:                         *      Copy as much as possible in one pass
                   4185:                         */
                   4186: 
                   4187:                        copy_size = size;
                   4188:                        r = vm_fault_copy(
                   4189:                                        copy_entry->object.vm_object,
                   4190:                                        copy_entry->offset,
                   4191:                                        &copy_size,
                   4192:                                        dst_object,
                   4193:                                        dst_offset,
                   4194:                                        dst_map,
                   4195:                                        &version,
                   4196:                                        THREAD_UNINT );
                   4197: 
                   4198:                        /*
                   4199:                         *      Release the object reference
                   4200:                         */
                   4201: 
                   4202:                        vm_object_deallocate(dst_object);
                   4203: 
                   4204:                        /*
                   4205:                         *      If a hard error occurred, return it now
                   4206:                         */
                   4207: 
                   4208:                        if (r != KERN_SUCCESS)
                   4209:                                return(r);
                   4210: 
                   4211:                        if (copy_size != 0) {
                   4212:                                /*
                   4213:                                 *      Dispose of the copied region
                   4214:                                 */
                   4215: 
                   4216:                                vm_map_copy_clip_end(copy, copy_entry,
                   4217:                                        copy_entry->vme_start + copy_size);
                   4218:                                vm_map_copy_entry_unlink(copy, copy_entry);
                   4219:                                vm_object_deallocate(copy_entry->object.vm_object);
                   4220:                                vm_map_copy_entry_dispose(copy, copy_entry);
                   4221:                        }
                   4222: 
                   4223:                        /*
                   4224:                         *      Pick up in the destination map where we left off.
                   4225:                         *
                   4226:                         *      Use the version information to avoid a lookup
                   4227:                         *      in the normal case.
                   4228:                         */
                   4229: 
                   4230:                        start += copy_size;
                   4231:                        vm_map_lock(dst_map);
                   4232:                        if ((version.main_timestamp + 1) == dst_map->timestamp) {
                   4233:                                /* We can safely use saved tmp_entry value */
                   4234: 
                   4235:                                vm_map_clip_end(dst_map, tmp_entry, start);
                   4236:                                tmp_entry = tmp_entry->vme_next;
                   4237:                        } else {
                   4238:                                /* Must do lookup of tmp_entry */
                   4239: 
                   4240:                                if (!vm_map_lookup_entry(dst_map, start, &tmp_entry)) {
                   4241:                                        vm_map_unlock(dst_map);
                   4242:                                        return(KERN_INVALID_ADDRESS);
                   4243:                                }
                   4244:                                vm_map_clip_start(dst_map, tmp_entry, start);
                   4245:                        }
                   4246:                }
                   4247:        }/* while */
                   4248: 
                   4249:        return(KERN_SUCCESS);
                   4250: }/* vm_map_copy_overwrite_aligned */
                   4251: 
                   4252: #if    DIPC
                   4253: #include <dipc/dipc_counters.h>
                   4254: dcntr_decl(unsigned int c_dipc_overwrite_opt = 0;)
                   4255: dcntr_decl(unsigned int c_dipc_overwrite_nonopt = 0;)
                   4256: dcntr_decl(unsigned int c_dipc_overwrite_recv_done = 0;)
                   4257: #else  /* DIPC */
                   4258: #define        dstat_decl(foo)
                   4259: #define        dstat(foo)
                   4260: #define        dcntr_decl(foo)
                   4261: #define        dcntr(foo)
                   4262: #endif /* DIPC */
                   4263: 
                   4264: #if    DIPC
                   4265: vm_map_copy_t
                   4266: vm_map_copy_overwrite_recv(
                   4267:        vm_map_t        map,
                   4268:        vm_offset_t     addr,
                   4269:        vm_size_t       size)
                   4270: {
                   4271:        vm_offset_t     end_addr;
                   4272:        vm_map_copy_t   copy = VM_MAP_COPY_NULL;
                   4273:        vm_map_entry_t  entry, new_entry;
                   4274:        kern_return_t   kr;
                   4275: 
                   4276:        if (size == 0)
                   4277:                return VM_MAP_COPY_NULL;
                   4278: 
                   4279:        if (!page_aligned(size) || !page_aligned(addr)) {
                   4280:                end_addr = round_page(addr + size);
                   4281:        } else {
                   4282:                end_addr = addr + size;
                   4283:        }
                   4284: 
                   4285:        /* Do allocations before taking map lock. */
                   4286: 
                   4287:        /* build an ENTRY_LIST vm_map_copy_t */
                   4288:        copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
                   4289:        vm_map_copy_first_entry(copy) =
                   4290:         vm_map_copy_last_entry(copy) = vm_map_copy_to_entry(copy);
                   4291:        copy->type = VM_MAP_COPY_ENTRY_LIST;
                   4292:        copy->offset = addr;
                   4293:        copy->size = size;
                   4294:        copy->cpy_hdr.nentries = 0;
                   4295:        copy->cpy_hdr.entries_pageable = TRUE;
                   4296:        new_entry = vm_map_copy_entry_create(copy);
                   4297: 
                   4298:        vm_map_lock(map);
                   4299:        if (!vm_map_lookup_entry(map, addr, &entry)) {
                   4300:                vm_map_unlock(map);
                   4301:                vm_map_copy_entry_dispose(copy, new_entry);
                   4302:                vm_map_copy_discard(copy);
                   4303:                return VM_MAP_COPY_NULL;
                   4304:        }
                   4305:        if (entry->is_sub_map) {
                   4306:                vm_map_unlock(map);
                   4307:                vm_map_copy_entry_dispose(copy, new_entry);
                   4308:                vm_map_copy_discard(copy);
                   4309:                return VM_MAP_COPY_NULL;
                   4310:        }
                   4311: 
                   4312:        /*
                   4313:         * for now, only do this if the range is contained completely
                   4314:         * within a single entry.  Just give up if entry is in_transition:
                   4315:         * it could be another thread wiring/unwiring, but it could be another
                   4316:         * part of this message that set it, in which case we'd deadlock if
                   4317:         * we waited for it to clear.  If the entry is not writeable, give up
                   4318:         * and let the ipc_kmsg_copyout code handle the error later.
                   4319:         */
                   4320:        if ((end_addr > entry->vme_end) ||
                   4321:            entry->in_transition ||
                   4322:            !(entry->protection & VM_PROT_WRITE)) {
                   4323:                vm_map_unlock(map);
                   4324:                dcntr(++c_dipc_overwrite_nonopt);
                   4325:                vm_map_copy_entry_dispose(copy, new_entry);
                   4326:                vm_map_copy_discard(copy);
                   4327:                return VM_MAP_COPY_NULL;
                   4328:        }
                   4329: 
                   4330:        vm_map_clip_start(map, entry, trunc_page(addr));
                   4331: 
                   4332:        /* handle COW obligations */
                   4333:        if (entry->needs_copy) {
                   4334:                vm_object_shadow(&entry->object.vm_object, &entry->offset,
                   4335:                        (vm_size_t)(entry->vme_end - entry->vme_start));
                   4336:                entry->needs_copy = FALSE;
                   4337:        }
                   4338: 
                   4339:        /* make sure there's a target object to put pages into */
                   4340:        if (entry->object.vm_object == VM_OBJECT_NULL) {
                   4341:                entry->object.vm_object = vm_object_allocate((vm_size_t)
                   4342:                                        (entry->vme_end - entry->vme_start));
                   4343:                entry->offset = 0;
                   4344:        }
                   4345: 
                   4346:        /*
                   4347:         * set in_transition to keep the entry in the map from moving around
                   4348:         * while DIPC fills the object in with data.  This must be cleared
                   4349:         * later on by calling vm_map_copy_overwrite_recv_done (below).
                   4350:         */
                   4351:        entry->in_transition = TRUE;
                   4352: 
                   4353:        /* make a copy of the entry */
                   4354:        vm_map_entry_copy(new_entry, entry);
                   4355:        vm_object_reference(new_entry->object.vm_object);
                   4356: 
                   4357:        vm_map_unlock(map);
                   4358: 
                   4359:        /* link in the new entry */
                   4360:        vm_map_copy_entry_link(copy, vm_map_copy_last_entry(copy), new_entry);
                   4361: 
                   4362:        dcntr(++c_dipc_overwrite_opt);
                   4363:        return copy;
                   4364: }
                   4365: 
                   4366: /*
                   4367:  * Find the map entry that corresponds to the copy entry, then clear
                   4368:  * in_transition on it.  Discard the copy.
                   4369:  */
                   4370: kern_return_t
                   4371: vm_map_copy_overwrite_recv_done(
                   4372:        vm_map_t        map,
                   4373:        vm_map_copy_t   copy)
                   4374: {
                   4375:        vm_map_entry_t  entry, map_entry;
                   4376:        boolean_t       need_wakeup = FALSE;
                   4377: 
                   4378:        assert(copy != VM_MAP_COPY_NULL);
                   4379:        assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
                   4380:        dcntr(++c_dipc_overwrite_recv_done);
                   4381: 
                   4382:        entry = vm_map_copy_first_entry(copy);
                   4383:        assert(entry != VM_MAP_ENTRY_NULL);
                   4384: 
                   4385:        vm_map_lock(map);
                   4386:        
                   4387:        if (!vm_map_lookup_entry(map, entry->vme_start, &map_entry)) {
                   4388:                vm_map_unlock(map);
                   4389:                return KERN_INVALID_ADDRESS;
                   4390:        }
                   4391:        while ((map_entry != vm_map_to_entry(map)) &&
                   4392:            (map_entry->vme_end <= entry->vme_end)) {
                   4393:                assert(map_entry->in_transition);
                   4394:                map_entry->in_transition = FALSE;
                   4395:                if (map_entry->needs_wakeup) {
                   4396:                        map_entry->needs_wakeup = FALSE;
                   4397:                        need_wakeup = TRUE;
                   4398:                }
                   4399:                map_entry = map_entry->vme_next;
                   4400:        }
                   4401:        vm_map_unlock(map);
                   4402:        if (need_wakeup)
                   4403:                vm_map_entry_wakeup(map);
                   4404:        vm_map_copy_discard(copy);
                   4405: 
                   4406:        return KERN_SUCCESS;
                   4407: }
                   4408: 
                   4409: #endif /* DIPC */
                   4410: 
                   4411: /*
                   4412:  *     Routine:        vm_map_copyout_kernel_buffer
                   4413:  *
                   4414:  *     Description:
                   4415:  *             Copy out data from a kernel buffer into space in the
                   4416:  *             destination map. The space may be otpionally dynamically
                   4417:  *             allocated.
                   4418:  *
                   4419:  *             If successful, consumes the copy object.
                   4420:  *             Otherwise, the caller is responsible for it.
                   4421:  */
                   4422: kern_return_t
                   4423: vm_map_copyout_kernel_buffer(
                   4424:        vm_map_t        map,
                   4425:        vm_offset_t     *addr,  /* IN/OUT */
                   4426:        vm_map_copy_t   copy,
                   4427:        boolean_t       overwrite)
                   4428: {
                   4429:        kern_return_t kr = KERN_SUCCESS;
                   4430:        thread_act_t thr_act = current_act();
                   4431: 
                   4432:        if (!overwrite) {
                   4433: 
                   4434:                /*
                   4435:                 * Allocate space in the target map for the data
                   4436:                 */
                   4437:                *addr = 0;
                   4438:                kr = vm_map_enter(map, 
                   4439:                                  addr, 
                   4440:                                  round_page(copy->size),
                   4441:                                  (vm_offset_t) 0, 
                   4442:                                  TRUE,
                   4443:                                  VM_OBJECT_NULL, 
                   4444:                                  (vm_offset_t) 0, 
                   4445:                                  FALSE,
                   4446:                                  VM_PROT_DEFAULT, 
                   4447:                                  VM_PROT_ALL,
                   4448:                                  VM_INHERIT_DEFAULT);
                   4449:                if (kr != KERN_SUCCESS)
                   4450:                        return(kr);
                   4451:        }
                   4452: 
                   4453:        /*
                   4454:         * Copyout the data from the kernel buffer to the target map.
                   4455:         */     
                   4456:        if (thr_act->map == map) {
                   4457:        
                   4458:                /*
                   4459:                 * If the target map is the current map, just do
                   4460:                 * the copy.
                   4461:                 */
                   4462:                if (copyout((char *)copy->cpy_kdata, (char *)*addr,
                   4463:                                copy->size)) {
                   4464:                        kr = KERN_INVALID_ADDRESS;
                   4465:                }
                   4466:        }
                   4467:        else {
                   4468:                vm_map_t oldmap;
                   4469: 
                   4470:                /*
                   4471:                 * If the target map is another map, assume the
                   4472:                 * target's address space identity for the duration
                   4473:                 * of the copy.
                   4474:                 */
                   4475:                vm_map_reference(map);
                   4476:                oldmap = vm_map_switch(map);
                   4477: 
                   4478:                if (copyout((char *)copy->cpy_kdata, (char *)*addr,
                   4479:                                copy->size)) {
                   4480:                        kr = KERN_INVALID_ADDRESS;
                   4481:                }
                   4482:        
                   4483:                (void) vm_map_switch(oldmap);
                   4484:                vm_map_deallocate(map);
                   4485:        }
                   4486: 
                   4487:        kfree((vm_offset_t)copy, copy->cpy_kalloc_size);
                   4488: 
                   4489:        return(kr);
                   4490: }
                   4491:                
                   4492: /*
                   4493:  *     Macro:          vm_map_copy_insert
                   4494:  *     
                   4495:  *     Description:
                   4496:  *             Link a copy chain ("copy") into a map at the
                   4497:  *             specified location (after "where").
                   4498:  *     Side effects:
                   4499:  *             The copy chain is destroyed.
                   4500:  *     Warning:
                   4501:  *             The arguments are evaluated multiple times.
                   4502:  */
                   4503: #define        vm_map_copy_insert(map, where, copy)                            \
                   4504: MACRO_BEGIN                                                            \
                   4505:        vm_map_t VMCI_map;                                              \
                   4506:        vm_map_entry_t VMCI_where;                                      \
                   4507:        vm_map_copy_t VMCI_copy;                                        \
                   4508:        VMCI_map = (map);                                               \
                   4509:        VMCI_where = (where);                                           \
                   4510:        VMCI_copy = (copy);                                             \
                   4511:        ((VMCI_where->vme_next)->vme_prev = vm_map_copy_last_entry(VMCI_copy))\
                   4512:                ->vme_next = (VMCI_where->vme_next);                    \
                   4513:        ((VMCI_where)->vme_next = vm_map_copy_first_entry(VMCI_copy))   \
                   4514:                ->vme_prev = VMCI_where;                                \
                   4515:        VMCI_map->hdr.nentries += VMCI_copy->cpy_hdr.nentries;          \
                   4516:        UPDATE_FIRST_FREE(VMCI_map, VMCI_map->first_free);              \
                   4517:        zfree(vm_map_copy_zone, (vm_offset_t) VMCI_copy);               \
                   4518: MACRO_END
                   4519: 
                   4520: /*
                   4521:  *     Routine:        vm_map_copyout
                   4522:  *
                   4523:  *     Description:
                   4524:  *             Copy out a copy chain ("copy") into newly-allocated
                   4525:  *             space in the destination map.
                   4526:  *
                   4527:  *             If successful, consumes the copy object.
                   4528:  *             Otherwise, the caller is responsible for it.
                   4529:  */
                   4530: kern_return_t
                   4531: vm_map_copyout(
                   4532:        register vm_map_t       dst_map,
                   4533:        vm_offset_t             *dst_addr,      /* OUT */
                   4534:        register vm_map_copy_t  copy)
                   4535: {
                   4536:        vm_size_t       size;
                   4537:        vm_size_t       adjustment;
                   4538:        vm_offset_t     start;
                   4539:        vm_offset_t     vm_copy_start;
                   4540:        vm_map_entry_t  last;
                   4541:        register
                   4542:        vm_map_entry_t  entry;
                   4543: 
                   4544:        /*
                   4545:         *      Check for null copy object.
                   4546:         */
                   4547: 
                   4548:        if (copy == VM_MAP_COPY_NULL) {
                   4549:                *dst_addr = 0;
                   4550:                return(KERN_SUCCESS);
                   4551:        }
                   4552: 
                   4553:        /*
                   4554:         *      Check for special copy object, created
                   4555:         *      by vm_map_copyin_object.
                   4556:         */
                   4557: 
                   4558:        if (copy->type == VM_MAP_COPY_OBJECT) {
                   4559:                vm_object_t object = copy->cpy_object;
                   4560:                kern_return_t kr;
                   4561:                vm_size_t offset;
                   4562: 
                   4563:                offset = trunc_page(copy->offset);
                   4564:                size = round_page(copy->size + copy->offset - offset);
                   4565:                *dst_addr = 0;
                   4566:                kr = vm_map_enter(dst_map, dst_addr, size,
                   4567:                                  (vm_offset_t) 0, TRUE,
                   4568:                                  object, offset, FALSE,
                   4569:                                  VM_PROT_DEFAULT, VM_PROT_ALL,
                   4570:                                  VM_INHERIT_DEFAULT);
                   4571:                if (kr != KERN_SUCCESS)
                   4572:                        return(kr);
                   4573:                /* Account for non-pagealigned copy object */
                   4574:                *dst_addr += copy->offset - offset;
                   4575:                zfree(vm_map_copy_zone, (vm_offset_t) copy);
                   4576:                return(KERN_SUCCESS);
                   4577:        }
                   4578: 
                   4579:        /*
                   4580:         *      Check for special kernel buffer allocated
                   4581:         *      by new_ipc_kmsg_copyin.
                   4582:         */
                   4583: 
                   4584:        if (copy->type == VM_MAP_COPY_KERNEL_BUFFER) {
                   4585:                return(vm_map_copyout_kernel_buffer(dst_map, dst_addr, 
                   4586:                                                    copy, FALSE));
                   4587:        }
                   4588: 
                   4589:        if (copy->type == VM_MAP_COPY_PAGE_LIST)
                   4590:                return(vm_map_copyout_page_list(dst_map, dst_addr, copy));
                   4591: 
                   4592:        /*
                   4593:         *      Find space for the data
                   4594:         */
                   4595: 
                   4596:        vm_copy_start = trunc_page(copy->offset);
                   4597:        size =  round_page(copy->offset + copy->size) - vm_copy_start;
                   4598: 
                   4599:  StartAgain: ;
                   4600: 
                   4601:        vm_map_lock(dst_map);
                   4602:        assert(first_free_is_valid(dst_map));
                   4603:        start = ((last = dst_map->first_free) == vm_map_to_entry(dst_map)) ?
                   4604:                vm_map_min(dst_map) : last->vme_end;
                   4605: 
                   4606:        while (TRUE) {
                   4607:                vm_map_entry_t  next = last->vme_next;
                   4608:                vm_offset_t     end = start + size;
                   4609: 
                   4610:                if ((end > dst_map->max_offset) || (end < start)) {
                   4611:                        if (dst_map->wait_for_space) {
                   4612:                                if (size <= (dst_map->max_offset - dst_map->min_offset)) {
                   4613:                                        assert_wait((event_t) dst_map,
                   4614:                                                    THREAD_INTERRUPTIBLE);
                   4615:                                        vm_map_unlock(dst_map);
                   4616:                                        thread_block((void (*)(void))0);
                   4617:                                        goto StartAgain;
                   4618:                                }
                   4619:                        }
                   4620:                        vm_map_unlock(dst_map);
                   4621:                        return(KERN_NO_SPACE);
                   4622:                }
                   4623: 
                   4624:                if ((next == vm_map_to_entry(dst_map)) ||
                   4625:                    (next->vme_start >= end))
                   4626:                        break;
                   4627: 
                   4628:                last = next;
                   4629:                start = last->vme_end;
                   4630:        }
                   4631: 
                   4632:        /*
                   4633:         *      Since we're going to just drop the map
                   4634:         *      entries from the copy into the destination
                   4635:         *      map, they must come from the same pool.
                   4636:         */
                   4637: 
                   4638:        if (copy->cpy_hdr.entries_pageable != dst_map->hdr.entries_pageable) {
                   4639:            /*
                   4640:             * Mismatches occur when dealing with the default
                   4641:             * pager.
                   4642:             */
                   4643:            zone_t              old_zone;
                   4644:            vm_map_entry_t      next, new;
                   4645: 
                   4646:            /*
                   4647:             * Find the zone that the copies were allocated from
                   4648:             */
                   4649:            old_zone = (copy->cpy_hdr.entries_pageable)
                   4650:                        ? vm_map_entry_zone
                   4651:                        : vm_map_kentry_zone;
                   4652:            entry = vm_map_copy_first_entry(copy);
                   4653: 
                   4654:            /*
                   4655:             * Reinitialize the copy so that vm_map_copy_entry_link
                   4656:             * will work.
                   4657:             */
                   4658:            copy->cpy_hdr.nentries = 0;
                   4659:            copy->cpy_hdr.entries_pageable = dst_map->hdr.entries_pageable;
                   4660:            vm_map_copy_first_entry(copy) =
                   4661:             vm_map_copy_last_entry(copy) =
                   4662:                vm_map_copy_to_entry(copy);
                   4663: 
                   4664:            /*
                   4665:             * Copy each entry.
                   4666:             */
                   4667:            while (entry != vm_map_copy_to_entry(copy)) {
                   4668:                new = vm_map_copy_entry_create(copy);
                   4669:                vm_map_entry_copy_full(new, entry);
                   4670:                vm_map_copy_entry_link(copy,
                   4671:                                vm_map_copy_last_entry(copy),
                   4672:                                new);
                   4673:                next = entry->vme_next;
                   4674:                zfree(old_zone, (vm_offset_t) entry);
                   4675:                entry = next;
                   4676:            }
                   4677:        }
                   4678: 
                   4679:        /*
                   4680:         *      Adjust the addresses in the copy chain, and
                   4681:         *      reset the region attributes.
                   4682:         */
                   4683: 
                   4684:        adjustment = start - vm_copy_start;
                   4685:        for (entry = vm_map_copy_first_entry(copy);
                   4686:             entry != vm_map_copy_to_entry(copy);
                   4687:             entry = entry->vme_next) {
                   4688:                entry->vme_start += adjustment;
                   4689:                entry->vme_end += adjustment;
                   4690: 
                   4691:                entry->inheritance = VM_INHERIT_DEFAULT;
                   4692:                entry->protection = VM_PROT_DEFAULT;
                   4693:                entry->max_protection = VM_PROT_ALL;
                   4694:                entry->behavior = VM_BEHAVIOR_DEFAULT;
                   4695: 
                   4696:                /*
                   4697:                 * If the entry is now wired,
                   4698:                 * map the pages into the destination map.
                   4699:                 */
                   4700:                if (entry->wired_count != 0) {
                   4701:                    register vm_offset_t va;
                   4702:                    vm_offset_t          offset;
                   4703:                    register vm_object_t object;
                   4704: 
                   4705:                    object = entry->object.vm_object;
                   4706:                    offset = entry->offset;
                   4707:                    va = entry->vme_start;
                   4708: 
                   4709:                    pmap_pageable(dst_map->pmap,
                   4710:                                  entry->vme_start,
                   4711:                                  entry->vme_end,
                   4712:                                  TRUE);
                   4713: 
                   4714:                    while (va < entry->vme_end) {
                   4715:                        register vm_page_t      m;
                   4716: 
                   4717:                        /*
                   4718:                         * Look up the page in the object.
                   4719:                         * Assert that the page will be found in the
                   4720:                         * top object:
                   4721:                         * either
                   4722:                         *      the object was newly created by
                   4723:                         *      vm_object_copy_slowly, and has
                   4724:                         *      copies of all of the pages from
                   4725:                         *      the source object
                   4726:                         * or
                   4727:                         *      the object was moved from the old
                   4728:                         *      map entry; because the old map
                   4729:                         *      entry was wired, all of the pages
                   4730:                         *      were in the top-level object.
                   4731:                         *      (XXX not true if we wire pages for
                   4732:                         *       reading)
                   4733:                         */
                   4734:                        vm_object_lock(object);
                   4735:                        vm_object_paging_begin(object);
                   4736: 
                   4737:                        m = vm_page_lookup(object, offset);
                   4738:                        if (m == VM_PAGE_NULL || m->wire_count == 0 ||
                   4739:                            m->absent)
                   4740:                            panic("vm_map_copyout: wiring 0x%x", m);
                   4741: 
                   4742:                        m->busy = TRUE;
                   4743:                        vm_object_unlock(object);
                   4744: 
                   4745:                        PMAP_ENTER(dst_map->pmap, va, m,
                   4746:                                   entry->protection, TRUE);
                   4747: 
                   4748:                        vm_object_lock(object);
                   4749:                        PAGE_WAKEUP_DONE(m);
                   4750:                        /* the page is wired, so we don't have to activate */
                   4751:                        vm_object_paging_end(object);
                   4752:                        vm_object_unlock(object);
                   4753: 
                   4754:                        offset += PAGE_SIZE;
                   4755:                        va += PAGE_SIZE;
                   4756:                    }
                   4757:                }
                   4758:                else if (size <= vm_map_aggressive_enter_max) {
                   4759: 
                   4760:                        register vm_offset_t    va;
                   4761:                        vm_offset_t             offset;
                   4762:                        register vm_object_t    object;
                   4763:                        vm_prot_t               prot;
                   4764: 
                   4765:                        object = entry->object.vm_object;
                   4766:                        if (object != VM_OBJECT_NULL) {
                   4767: 
                   4768:                                offset = entry->offset;
                   4769:                                va = entry->vme_start;
                   4770:                                while (va < entry->vme_end) {
                   4771:                                        register vm_page_t      m;
                   4772:                                    
                   4773:                                        /*
                   4774:                                         * Look up the page in the object.
                   4775:                                         * Assert that the page will be found
                   4776:                                         * in the top object if at all...
                   4777:                                         */
                   4778:                                        vm_object_lock(object);
                   4779:                                        vm_object_paging_begin(object);
                   4780: 
                   4781:                                        if (((m = vm_page_lookup(object,
                   4782:                                                                 offset))
                   4783:                                             != VM_PAGE_NULL) &&
                   4784:                                            !m->busy && !m->fictitious &&
                   4785:                                            !m->absent && !m->error) {
                   4786:                                                m->busy = TRUE;
                   4787:                                                vm_object_unlock(object);
                   4788: 
                   4789:                                                /* honor cow obligations */
                   4790:                                                prot = entry->protection;
                   4791:                                                if (entry->needs_copy)
                   4792:                                                        prot &= ~VM_PROT_WRITE;
                   4793: 
                   4794:                                                PMAP_ENTER(dst_map->pmap, va, 
                   4795:                                                           m, prot, FALSE);
                   4796: 
                   4797:                                                vm_object_lock(object);
                   4798:                                                vm_page_lock_queues();
                   4799:                                                if (!m->active && !m->inactive)
                   4800:                                                        vm_page_activate(m);
                   4801:                                                vm_page_unlock_queues();
                   4802:                                                PAGE_WAKEUP_DONE(m);
                   4803:                                        }
                   4804:                                        vm_object_paging_end(object);
                   4805:                                        vm_object_unlock(object);
                   4806: 
                   4807:                                        offset += PAGE_SIZE;
                   4808:                                        va += PAGE_SIZE;
                   4809:                                }
                   4810:                        }
                   4811:                }
                   4812:        }
                   4813: 
                   4814:        /*
                   4815:         *      Correct the page alignment for the result
                   4816:         */
                   4817: 
                   4818:        *dst_addr = start + (copy->offset - vm_copy_start);
                   4819: 
                   4820:        /*
                   4821:         *      Update the hints and the map size
                   4822:         */
                   4823: 
                   4824:        SAVE_HINT(dst_map, vm_map_copy_last_entry(copy));
                   4825: 
                   4826:        dst_map->size += size;
                   4827: 
                   4828:        /*
                   4829:         *      Link in the copy
                   4830:         */
                   4831: 
                   4832:        vm_map_copy_insert(dst_map, last, copy);
                   4833: 
                   4834:        vm_map_unlock(dst_map);
                   4835: 
                   4836:        /*
                   4837:         * XXX  If wiring_required, call vm_map_pageable
                   4838:         */
                   4839: 
                   4840:        return(KERN_SUCCESS);
                   4841: }
                   4842: 
                   4843: boolean_t       vm_map_aggressive_enter;        /* not used yet */
                   4844: 
                   4845: /*
                   4846:  *
                   4847:  *     vm_map_copyout_page_list:
                   4848:  *
                   4849:  *     Version of vm_map_copyout() for page list vm map copies.
                   4850:  *
                   4851:  */
                   4852: kern_return_t
                   4853: vm_map_copyout_page_list(
                   4854:        register vm_map_t       dst_map,
                   4855:        vm_offset_t             *dst_addr,      /* OUT */
                   4856:        register vm_map_copy_t  copy)
                   4857: {
                   4858:        vm_size_t       size;
                   4859:        vm_offset_t     start;
                   4860:        vm_offset_t     end;
                   4861:        vm_offset_t     offset;
                   4862:        vm_map_entry_t  last;
                   4863:        register
                   4864:        vm_object_t     object;
                   4865:        vm_page_t       *page_list, m;
                   4866:        vm_map_entry_t  entry;
                   4867:        vm_offset_t     old_last_offset;
                   4868:        boolean_t       cont_invoked, needs_wakeup;
                   4869:        kern_return_t   result = KERN_SUCCESS;
                   4870:        vm_map_copy_t   orig_copy;
                   4871:        vm_offset_t     dst_offset;
                   4872:        boolean_t       must_wire;
                   4873:        boolean_t       aggressive_enter;
                   4874: 
                   4875:        /*
                   4876:         *      Check for null copy object.
                   4877:         */
                   4878: 
                   4879:        if (copy == VM_MAP_COPY_NULL) {
                   4880:                *dst_addr = 0;
                   4881:                return(KERN_SUCCESS);
                   4882:        }
                   4883: 
                   4884:        assert(copy->type == VM_MAP_COPY_PAGE_LIST);
                   4885: 
                   4886:        /*
                   4887:         *      Make sure the pages are stolen, because we are
                   4888:         *      going to put them in a new object.  Assume that
                   4889:         *      all pages are identical to first in this regard.
                   4890:         */
                   4891: 
                   4892:        page_list = &copy->cpy_page_list[0];
                   4893:        if (!copy->cpy_page_loose)
                   4894:                vm_map_copy_steal_pages(copy);
                   4895: 
                   4896:        /*
                   4897:         *      Find space for the data
                   4898:         */
                   4899: 
                   4900:        size =  round_page(copy->offset + copy->size) -
                   4901:                trunc_page(copy->offset);
                   4902: StartAgain:
                   4903:        vm_map_lock(dst_map);
                   4904:        must_wire = dst_map->wiring_required;
                   4905: 
                   4906:        assert(first_free_is_valid(dst_map));
                   4907:        last = dst_map->first_free;
                   4908:        if (last == vm_map_to_entry(dst_map)) {
                   4909:                start = vm_map_min(dst_map);
                   4910:        } else {
                   4911:                start = last->vme_end;
                   4912:        }
                   4913: 
                   4914:        while (TRUE) {
                   4915:                vm_map_entry_t next = last->vme_next;
                   4916:                end = start + size;
                   4917: 
                   4918:                if ((end > dst_map->max_offset) || (end < start)) {
                   4919:                        if (dst_map->wait_for_space) {
                   4920:                                if (size <= (dst_map->max_offset -
                   4921:                                             dst_map->min_offset)) {
                   4922:                                        assert_wait((event_t) dst_map,
                   4923:                                                    THREAD_INTERRUPTIBLE);
                   4924:                                        vm_map_unlock(dst_map);
                   4925:                                        thread_block((void (*)(void))0);
                   4926:                                        goto StartAgain;
                   4927:                                }
                   4928:                        }
                   4929:                        vm_map_unlock(dst_map);
                   4930:                        return(KERN_NO_SPACE);
                   4931:                }
                   4932: 
                   4933:                if ((next == vm_map_to_entry(dst_map)) ||
                   4934:                    (next->vme_start >= end)) {
                   4935:                        break;
                   4936:                }
                   4937: 
                   4938:                last = next;
                   4939:                start = last->vme_end;
                   4940:        }
                   4941: 
                   4942:        /*
                   4943:         *      See whether we can avoid creating a new entry (and object) by
                   4944:         *      extending one of our neighbors.  [So far, we only attempt to
                   4945:         *      extend from below.]
                   4946:         *
                   4947:         *      The code path below here is a bit twisted.  If any of the
                   4948:         *      extension checks fails, we branch to create_object.  If
                   4949:         *      it all works, we fall out the bottom and goto insert_pages.
                   4950:         */
                   4951:        if (last == vm_map_to_entry(dst_map) ||
                   4952:            last->vme_end != start ||
                   4953:            last->is_shared != FALSE ||
                   4954:            last->is_sub_map != FALSE ||
                   4955:            last->inheritance != VM_INHERIT_DEFAULT ||
                   4956:            last->protection != VM_PROT_DEFAULT ||
                   4957:            last->max_protection != VM_PROT_ALL ||
                   4958:            last->behavior != VM_BEHAVIOR_DEFAULT ||
                   4959:            last->in_transition ||
                   4960:            (must_wire ? (last->wired_count != 1 ||
                   4961:                    last->user_wired_count != 0) :
                   4962:                (last->wired_count != 0))) {
                   4963:                    goto create_object;
                   4964:        }
                   4965:        
                   4966:        /*
                   4967:         * If this entry needs an object, make one.
                   4968:         */
                   4969:        if (last->object.vm_object == VM_OBJECT_NULL) {
                   4970:                object = vm_object_allocate(
                   4971:                        (vm_size_t)(last->vme_end - last->vme_start + size));
                   4972:                last->object.vm_object = object;
                   4973:                last->offset = 0;
                   4974:        }
                   4975:        else {
                   4976:            vm_offset_t prev_offset = last->offset;
                   4977:            vm_size_t   prev_size = start - last->vme_start;
                   4978:            vm_size_t   new_size;
                   4979: 
                   4980:            /*
                   4981:             *  This is basically vm_object_coalesce.
                   4982:             */
                   4983: 
                   4984:            object = last->object.vm_object;
                   4985:            vm_object_lock(object);
                   4986: 
                   4987:            /*
                   4988:             *  Try to collapse the object first
                   4989:             */
                   4990:            vm_object_collapse(object);
                   4991: 
                   4992:            /*
                   4993:             *  Can't coalesce if pages not mapped to
                   4994:             *  last may be in use anyway:
                   4995:             *  . more than one reference
                   4996:             *  . paged out
                   4997:             *  . shadows another object
                   4998:             *  . has a copy elsewhere
                   4999:             *  . paging references (pages might be in page-list)
                   5000:             */
                   5001: 
                   5002:            if ((object->ref_count > 1) ||
                   5003:                object->pager_created ||
                   5004:                (object->shadow != VM_OBJECT_NULL) ||
                   5005:                (object->copy != VM_OBJECT_NULL) ||
                   5006:                (object->paging_in_progress != 0)) {
                   5007:                    vm_object_unlock(object);
                   5008:                    goto create_object;
                   5009:            }
                   5010: 
                   5011:            /*
                   5012:             *  Extend the object if necessary.  Don't have to call
                   5013:             *  vm_object_page_remove because the pages aren't mapped,
                   5014:             *  and vm_page_replace will free up any old ones it encounters.
                   5015:             */
                   5016:            new_size = prev_offset + prev_size + size;
                   5017:            if (new_size > object->size) {
                   5018: #if    MACH_PAGEMAP
                   5019:                    /*
                   5020:                     *  We cannot extend an object that has existence info,
                   5021:                     *  since the existence info might then fail to cover
                   5022:                     *  the entire object.
                   5023:                     *
                   5024:                     *  This assertion must be true because the object
                   5025:                     *  has no pager, and we only create existence info
                   5026:                     *  for objects with pagers.
                   5027:                     */
                   5028:                    assert(object->existence_map == VM_EXTERNAL_NULL);
                   5029: #endif /* MACH_PAGEMAP */
                   5030:                    object->size = new_size;
                   5031:            }
                   5032:            vm_object_unlock(object);
                   5033:         }
                   5034: 
                   5035:        /*
                   5036:         *      Coalesced the two objects - can extend
                   5037:         *      the previous map entry to include the
                   5038:         *      new range.
                   5039:         */
                   5040:        dst_map->size += size;
                   5041:        last->vme_end = end;
                   5042:        UPDATE_FIRST_FREE(dst_map, dst_map->first_free);
                   5043: 
                   5044:        SAVE_HINT(dst_map, last);
                   5045: 
                   5046:        goto insert_pages;
                   5047: 
                   5048: create_object:
                   5049: 
                   5050:        /*
                   5051:         *      Create object
                   5052:         */
                   5053:        object = vm_object_allocate(size);
                   5054: 
                   5055:        /*
                   5056:         *      Create entry
                   5057:         */
                   5058:        last = vm_map_entry_insert(dst_map, last, start, start + size,
                   5059:                                   object, 0, FALSE, FALSE, TRUE,
                   5060:                                   VM_PROT_DEFAULT, VM_PROT_ALL,
                   5061:                                   VM_BEHAVIOR_DEFAULT,
                   5062:                                   VM_INHERIT_DEFAULT, (must_wire ? 1 : 0));
                   5063: 
                   5064:        /*
                   5065:         *      Transfer pages into new object.  
                   5066:         *      Scan page list in vm_map_copy.
                   5067:         */
                   5068: insert_pages:
                   5069:        dst_offset = copy->offset & PAGE_MASK;
                   5070:        cont_invoked = FALSE;
                   5071:        orig_copy = copy;
                   5072:        last->in_transition = TRUE;
                   5073:        old_last_offset = last->offset
                   5074:            + (start - last->vme_start);
                   5075: 
                   5076:        aggressive_enter = (size <= vm_map_aggressive_enter_max);
                   5077: 
                   5078:        for (offset = 0; offset < size; offset += PAGE_SIZE) {
                   5079:                m = *page_list;
                   5080:                assert(m && !m->tabled);
                   5081: 
                   5082:                /*
                   5083:                 *      Must clear busy bit in page before inserting it.
                   5084:                 *      Ok to skip wakeup logic because nobody else
                   5085:                 *      can possibly know about this page.  Also set
                   5086:                 *      dirty bit on the assumption that the page is
                   5087:                 *      not a page of zeros.
                   5088:                 */
                   5089: 
                   5090:                m->busy = FALSE;
                   5091:                m->dirty = TRUE;
                   5092:                vm_object_lock(object);
                   5093:                vm_page_lock_queues();
                   5094:                vm_page_replace(m, object, old_last_offset + offset);
                   5095:                if (must_wire) {
                   5096:                        vm_page_wire(m);
                   5097:                } else if (aggressive_enter) {
                   5098:                        vm_page_activate(m);
                   5099:                }
                   5100:                vm_page_unlock_queues();
                   5101:                vm_object_unlock(object);
                   5102: 
                   5103:                if (aggressive_enter || must_wire) {
                   5104:                        PMAP_ENTER(dst_map->pmap,
                   5105:                                   last->vme_start + m->offset - last->offset,
                   5106:                                   m, last->protection, must_wire);
                   5107:                }
                   5108: 
                   5109:                *page_list++ = VM_PAGE_NULL;
                   5110:                assert(copy != VM_MAP_COPY_NULL);
                   5111:                assert(copy->type == VM_MAP_COPY_PAGE_LIST);
                   5112:                if (--(copy->cpy_npages) == 0 &&
                   5113:                    vm_map_copy_has_cont(copy)) {
                   5114:                        vm_map_copy_t   new_copy;
                   5115: 
                   5116:                        /*
                   5117:                         *      Ok to unlock map because entry is
                   5118:                         *      marked in_transition.
                   5119:                         */
                   5120:                        cont_invoked = TRUE;
                   5121:                        vm_map_unlock(dst_map);
                   5122:                        vm_map_copy_invoke_cont(copy, &new_copy, &result);
                   5123: 
                   5124:                        if (result == KERN_SUCCESS) {
                   5125: 
                   5126:                                /*
                   5127:                                 *      If we got back a copy with real pages,
                   5128:                                 *      steal them now.  Either all of the
                   5129:                                 *      pages in the list are tabled or none
                   5130:                                 *      of them are; mixtures are not possible.
                   5131:                                 *
                   5132:                                 *      Save original copy for consume on
                   5133:                                 *      success logic at end of routine.
                   5134:                                 */
                   5135:                                if (copy != orig_copy)
                   5136:                                        vm_map_copy_discard(copy);
                   5137: 
                   5138:                                if ((copy = new_copy) != VM_MAP_COPY_NULL) {
                   5139:                                        page_list = &copy->cpy_page_list[0];
                   5140:                                        if (!copy->cpy_page_loose)
                   5141:                                                vm_map_copy_steal_pages(copy);
                   5142:                                }
                   5143:                        }
                   5144:                        else {
                   5145:                                /*
                   5146:                                 *      Continuation failed.
                   5147:                                 */
                   5148:                                vm_map_lock(dst_map);
                   5149:                                goto error;
                   5150:                        }
                   5151: 
                   5152:                        vm_map_lock(dst_map);
                   5153:                }
                   5154:        }
                   5155: 
                   5156:        *dst_addr = start + dst_offset;
                   5157:        
                   5158:        /*
                   5159:         *      Clear the in transition bits.  This is easy if we
                   5160:         *      didn't have a continuation.
                   5161:         */
                   5162: error:
                   5163:        needs_wakeup = FALSE;
                   5164:        if (!cont_invoked) {
                   5165:                /*
                   5166:                 *      We didn't unlock the map, so nobody could
                   5167:                 *      be waiting.
                   5168:                 */
                   5169:                last->in_transition = FALSE;
                   5170:                assert(!last->needs_wakeup);
                   5171:        }
                   5172:        else {
                   5173:                if (!vm_map_lookup_entry(dst_map, start, &entry))
                   5174:                        panic("vm_map_copyout_page_list: missing entry");
                   5175: 
                   5176:                 /*
                   5177:                  * Clear transition bit for all constituent entries that
                   5178:                  * were in the original entry.  Also check for waiters.
                   5179:                  */
                   5180:                 while ((entry != vm_map_to_entry(dst_map)) &&
                   5181:                        (entry->vme_start < end)) {
                   5182:                         assert(entry->in_transition);
                   5183:                         entry->in_transition = FALSE;
                   5184:                         if (entry->needs_wakeup) {
                   5185:                                 entry->needs_wakeup = FALSE;
                   5186:                                 needs_wakeup = TRUE;
                   5187:                         }
                   5188:                         entry = entry->vme_next;
                   5189:                 }
                   5190:        }
                   5191:        
                   5192:        if (result != KERN_SUCCESS)
                   5193:                (void) vm_map_delete(dst_map, start, end, VM_MAP_NO_FLAGS);
                   5194: 
                   5195:        vm_map_unlock(dst_map);
                   5196: 
                   5197:        if (needs_wakeup)
                   5198:                vm_map_entry_wakeup(dst_map);
                   5199: 
                   5200:        /*
                   5201:         *      Consume on success logic.
                   5202:         */
                   5203:        if (copy != VM_MAP_COPY_NULL && copy != orig_copy) {
                   5204:                zfree(vm_map_copy_zone, (vm_offset_t) copy);
                   5205:        }
                   5206:        if (result == KERN_SUCCESS) {
                   5207:                assert(orig_copy != VM_MAP_COPY_NULL);
                   5208:                assert(orig_copy->type == VM_MAP_COPY_PAGE_LIST);
                   5209:                zfree(vm_map_copy_zone, (vm_offset_t) orig_copy);
                   5210:        }
                   5211:        
                   5212:        return(result);
                   5213: }
                   5214: 
                   5215: /*
                   5216:  *     Routine:        vm_map_copyin
                   5217:  *
                   5218:  *     Description:
                   5219:  *             Copy the specified region (src_addr, len) from the
                   5220:  *             source address space (src_map), possibly removing
                   5221:  *             the region from the source address space (src_destroy).
                   5222:  *
                   5223:  *     Returns:
                   5224:  *             A vm_map_copy_t object (copy_result), suitable for
                   5225:  *             insertion into another address space (using vm_map_copyout),
                   5226:  *             copying over another address space region (using
                   5227:  *             vm_map_copy_overwrite).  If the copy is unused, it
                   5228:  *             should be destroyed (using vm_map_copy_discard).
                   5229:  *
                   5230:  *     In/out conditions:
                   5231:  *             The source map should not be locked on entry.
                   5232:  */
                   5233: #if    DIPC
                   5234: dstat_decl(unsigned int c_vmcc_volatile = 0;)
                   5235: dstat_decl(unsigned int c_vmcc_null_entry = 0;)
                   5236: dstat_decl(unsigned int c_vmcc_null_entry_continue = 0;)
                   5237: dstat_decl(unsigned int c_vmcc_src_destroy_opt = 0;)
                   5238: dstat_decl(unsigned int c_vmcc_wasnt_wired = 0;)
                   5239: dstat_decl(unsigned int c_vmcc_vocq = 0;)
                   5240: dstat_decl(unsigned int c_vmcc_vopp = 0;)
                   5241: dstat_decl(unsigned int c_vmcc_voept = 0;)
                   5242: dstat_decl(unsigned int c_vmcc_vocs = 0;)
                   5243: dstat_decl(unsigned int c_vmcc_vocstrat = 0;)
                   5244: dstat_decl(unsigned int c_vmcc_vmle = 0;)
                   5245: dstat_decl(unsigned int c_vmcc_reloop = 0;)
                   5246: dstat_decl(unsigned int c_vmcc_vmd = 0;)
                   5247: #endif /* DIPC */
                   5248: 
                   5249: 
                   5250: typedef struct submap_map {
                   5251:        vm_map_t        parent_map;
                   5252:        vm_offset_t     base_start;
                   5253:        vm_offset_t     base_end;
                   5254:        struct submap_map *next;
                   5255: } submap_map_t;
                   5256: 
                   5257: kern_return_t
                   5258: vm_map_copyin_common(
                   5259:        vm_map_t        src_map,
                   5260:        vm_offset_t     src_addr,
                   5261:        vm_size_t       len,
                   5262:        boolean_t       src_destroy,
                   5263:        boolean_t       src_volatile,
                   5264:        vm_map_copy_t   *copy_result,   /* OUT */
                   5265:        boolean_t       use_maxprot)
                   5266: {
                   5267:        vm_map_entry_t  tmp_entry;      /* Result of last map lookup --
                   5268:                                         * in multi-level lookup, this
                   5269:                                         * entry contains the actual
                   5270:                                         * vm_object/offset.
                   5271:                                         */
                   5272:        register
                   5273:        vm_map_entry_t  new_entry = VM_MAP_ENTRY_NULL;  /* Map entry for copy */
                   5274: 
                   5275:        vm_offset_t     src_start;      /* Start of current entry --
                   5276:                                         * where copy is taking place now
                   5277:                                         */
                   5278:        vm_offset_t     src_end;        /* End of entire region to be
                   5279:                                         * copied */
                   5280:        vm_offset_t     base_start;     /* submap fields to save offsets */
                   5281:                                        /* in original map */
                   5282:        vm_offset_t     base_end;
                   5283:        vm_map_t        base_map=src_map;
                   5284:        vm_map_entry_t  base_entry;
                   5285:        boolean_t       map_share=FALSE;
                   5286:        submap_map_t    *parent_maps = NULL;
                   5287: 
                   5288:        register
                   5289:        vm_map_copy_t   copy;           /* Resulting copy */
                   5290: 
                   5291:        /*
                   5292:         *      Check for copies of zero bytes.
                   5293:         */
                   5294: 
                   5295:        if (len == 0) {
                   5296:                *copy_result = VM_MAP_COPY_NULL;
                   5297:                return(KERN_SUCCESS);
                   5298:        }
                   5299: 
                   5300:        /*
                   5301:         *      Compute start and end of region
                   5302:         */
                   5303: 
                   5304:        src_start = trunc_page(src_addr);
                   5305:        src_end = round_page(src_addr + len);
                   5306: 
                   5307: #if    DIPC
                   5308:        XPR(XPR_VM_MAP,
                   5309:            "vm_map_copyin_common map 0x%x addr 0x%x len 0x%x dest %d volatile %d\n",
                   5310:            (natural_t)src_map, src_addr, len, src_destroy, src_volatile);
                   5311: #else  /* DIPC */
                   5312:        XPR(XPR_VM_MAP, "vm_map_copyin_common map 0x%x addr 0x%x len 0x%x dest %d\n",
                   5313:            (natural_t)src_map, src_addr, len, src_destroy, 0);
                   5314: #endif /* DIPC */
                   5315: 
                   5316:        /*
                   5317:         *      Check that the end address doesn't overflow
                   5318:         */
                   5319: 
                   5320:        if (src_end <= src_start)
                   5321:                if ((src_end < src_start) || (src_start != 0))
                   5322:                        return(KERN_INVALID_ADDRESS);
                   5323: 
                   5324:        /*
                   5325:         *      Allocate a header element for the list.
                   5326:         *
                   5327:         *      Use the start and end in the header to 
                   5328:         *      remember the endpoints prior to rounding.
                   5329:         */
                   5330: 
                   5331:        copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
                   5332:        vm_map_copy_first_entry(copy) =
                   5333:         vm_map_copy_last_entry(copy) = vm_map_copy_to_entry(copy);
                   5334:        copy->type = VM_MAP_COPY_ENTRY_LIST;
                   5335:        copy->cpy_hdr.nentries = 0;
                   5336:        copy->cpy_hdr.entries_pageable = TRUE;
                   5337: 
                   5338:        copy->offset = src_addr;
                   5339:        copy->size = len;
                   5340:        
                   5341:        new_entry = vm_map_copy_entry_create(copy);
                   5342: 
                   5343: #define        RETURN(x)                                               \
                   5344:        MACRO_BEGIN                                             \
                   5345:        vm_map_unlock(src_map);                                 \
                   5346:        if (new_entry != VM_MAP_ENTRY_NULL)                     \
                   5347:                vm_map_copy_entry_dispose(copy,new_entry);      \
                   5348:        vm_map_copy_discard(copy);                              \
                   5349:        {                                                       \
                   5350:                submap_map_t    *ptr;                           \
                   5351:                                                                \
                   5352:                for(ptr = parent_maps; ptr != NULL; ptr = parent_maps) { \
                   5353:                        parent_maps=parent_maps->next;          \
                   5354:                        kfree((vm_offset_t)ptr, sizeof(submap_map_t));  \
                   5355:                }                                               \
                   5356:        }                                                       \
                   5357:        MACRO_RETURN(x);                                        \
                   5358:        MACRO_END
                   5359: 
                   5360:        /*
                   5361:         *      Find the beginning of the region.
                   5362:         */
                   5363: 
                   5364:        vm_map_lock(src_map);
                   5365: 
                   5366:        if (!vm_map_lookup_entry(src_map, src_start, &tmp_entry))
                   5367:                RETURN(KERN_INVALID_ADDRESS);
                   5368:        vm_map_clip_start(src_map, tmp_entry, src_start);
                   5369: 
                   5370:        /*
                   5371:         *      Go through entries until we get to the end.
                   5372:         */
                   5373: 
                   5374:        while (TRUE) {
                   5375:                register
                   5376:                vm_map_entry_t  src_entry = tmp_entry;  /* Top-level entry */
                   5377:                vm_size_t       src_size;               /* Size of source
                   5378:                                                         * map entry (in both
                   5379:                                                         * maps)
                   5380:                                                         */
                   5381: 
                   5382:                register
                   5383:                vm_object_t     src_object;             /* Object to copy */
                   5384:                vm_offset_t     src_offset;
                   5385: 
                   5386:                boolean_t       src_needs_copy;         /* Should source map
                   5387:                                                         * be made read-only
                   5388:                                                         * for copy-on-write?
                   5389:                                                         */
                   5390: 
                   5391:                boolean_t       new_entry_needs_copy;   /* Will new entry be COW? */
                   5392: 
                   5393:                boolean_t       was_wired;              /* Was source wired? */
                   5394:                vm_map_version_t version;               /* Version before locks
                   5395:                                                         * dropped to make copy
                   5396:                                                         */
                   5397:                kern_return_t   result;                 /* Return value from
                   5398:                                                         * copy_strategically.
                   5399:                                                         */
                   5400:                while(tmp_entry->is_sub_map) {
                   5401:                        vm_size_t submap_len;
                   5402:                        submap_map_t *ptr;
                   5403: 
                   5404:                        ptr = (submap_map_t *)kalloc(sizeof(submap_map_t));
                   5405:                        ptr->next = parent_maps;
                   5406:                        parent_maps = ptr;
                   5407:                        ptr->parent_map = src_map;
                   5408:                        ptr->base_start = src_start;
                   5409:                        ptr->base_end = src_end;
                   5410:                        submap_len = tmp_entry->vme_end - tmp_entry->vme_start;
                   5411:                        if(submap_len > (src_end-src_start))
                   5412:                                submap_len = src_end-src_start;
                   5413:                        ptr->base_start += submap_len;
                   5414:        
                   5415:                        src_start -= tmp_entry->vme_start;
                   5416:                        src_start += tmp_entry->offset;
                   5417:                        src_end = src_start + submap_len;
                   5418:                        src_map = tmp_entry->object.sub_map;
                   5419:                        vm_map_lock(src_map);
                   5420:                        vm_map_unlock(ptr->parent_map);
                   5421:                        if (!vm_map_lookup_entry(
                   5422:                                        src_map, src_start, &tmp_entry))
                   5423:                                RETURN(KERN_INVALID_ADDRESS);
                   5424:                        map_share = TRUE;
                   5425:                        vm_map_clip_start(src_map, tmp_entry, src_start);
                   5426:                        src_entry = tmp_entry;
                   5427:                }
                   5428:                /*
                   5429:                 *      Create a new address map entry to hold the result. 
                   5430:                 *      Fill in the fields from the appropriate source entries.
                   5431:                 *      We must unlock the source map to do this if we need
                   5432:                 *      to allocate a map entry.
                   5433:                 */
                   5434:                if (new_entry == VM_MAP_ENTRY_NULL) {
                   5435:                    version.main_timestamp = src_map->timestamp;
                   5436:                    vm_map_unlock(src_map);
                   5437: 
                   5438:                    dstat(++c_vmcc_null_entry);
                   5439:                    new_entry = vm_map_copy_entry_create(copy);
                   5440: 
                   5441:                    vm_map_lock(src_map);
                   5442:                    if ((version.main_timestamp + 1) != src_map->timestamp) {
                   5443:                        if (!vm_map_lookup_entry(src_map, src_start,
                   5444:                                        &tmp_entry)) {
                   5445:                                RETURN(KERN_INVALID_ADDRESS);
                   5446:                        }
                   5447:                        vm_map_clip_start(src_map, tmp_entry, src_start);
                   5448:                        dstat(++c_vmcc_null_entry_continue);
                   5449:                        continue; /* restart w/ new tmp_entry */
                   5450:                    }
                   5451:                }
                   5452: 
                   5453:                /*
                   5454:                 *      Verify that the region can be read.
                   5455:                 */
                   5456:                if (((src_entry->protection & VM_PROT_READ) == VM_PROT_NONE &&
                   5457:                        !use_maxprot) ||
                   5458:                    (src_entry->max_protection & VM_PROT_READ) == 0)
                   5459:                        RETURN(KERN_PROTECTION_FAILURE);
                   5460: 
                   5461:                /*
                   5462:                 *      Clip against the endpoints of the entire region.
                   5463:                 */
                   5464: 
                   5465:                vm_map_clip_end(src_map, src_entry, src_end);
                   5466: 
                   5467:                src_size = src_entry->vme_end - src_start;
                   5468:                src_object = src_entry->object.vm_object;
                   5469:                src_offset = src_entry->offset;
                   5470:                was_wired = (src_entry->wired_count != 0);
                   5471: 
                   5472:                vm_map_entry_copy(new_entry, src_entry);
                   5473: 
                   5474:                /*
                   5475:                 *      Attempt non-blocking copy-on-write optimizations.
                   5476:                 */
                   5477: 
                   5478:                if (src_destroy && 
                   5479:                    (src_object == VM_OBJECT_NULL || 
                   5480:                    (src_object->internal && !src_object->true_share
                   5481:                    && !map_share))) {
                   5482:                    /*
                   5483:                     * If we are destroying the source, and the object
                   5484:                     * is internal, we can move the object reference
                   5485:                     * from the source to the copy.  The copy is
                   5486:                     * copy-on-write only if the source is.
                   5487:                     * We make another reference to the object, because
                   5488:                     * destroying the source entry will deallocate it.
                   5489:                     */
                   5490:                    vm_object_reference(src_object);
                   5491: 
                   5492:                    /*
                   5493:                     * Copy is always unwired.  vm_map_copy_entry
                   5494:                     * set its wired count to zero.
                   5495:                     */
                   5496: 
                   5497:                    dstat(++c_vmcc_src_destroy_opt);
                   5498:                    goto CopySuccessful;
                   5499:                }
                   5500: 
                   5501: #if    DIPC
                   5502:                /*
                   5503:                 *      If the caller promises not to modify the data,
                   5504:                 *      we don't have to apply copy-on-write processing
                   5505:                 *      to it.  This works best in the distributed case.
                   5506:                 *      In the local case, we can wind up with fully
                   5507:                 *      shared data between sender and receiver -- a
                   5508:                 *      behavior that we aren't entirely sure we want
                   5509:                 *      at this point.  So for now, we'll only do this
                   5510:                 *      on remote data transfers.
                   5511:                 */
                   5512:                if (src_volatile == TRUE) {
                   5513:                    XPR(XPR_VM_MAP,
                   5514:                        "vmcc src_obj 0x%x ent 0x%x obj 0x%x VOLATILE\n",
                   5515:                        src_object, new_entry, new_entry->object.vm_object,
                   5516:                        0, 0);
                   5517:                    assert(src_destroy == FALSE);
                   5518:                    dstat(++c_vmcc_volatile);
                   5519:                    vm_object_reference(src_object);
                   5520:                    goto CopySuccessful;
                   5521:                }
                   5522: #endif /* DIPC */
                   5523: 
                   5524: RestartCopy:
                   5525:                XPR(XPR_VM_MAP, "vm_map_copyin_common src_obj 0x%x ent 0x%x obj 0x%x was_wired %d\n",
                   5526:                    src_object, new_entry, new_entry->object.vm_object,
                   5527:                    was_wired, 0);
                   5528:                dstat(!was_wired ? ++c_vmcc_wasnt_wired : 0);
                   5529:                if (!was_wired &&
                   5530:                    vm_object_copy_quickly(
                   5531:                                &new_entry->object.vm_object,
                   5532:                                src_offset,
                   5533:                                src_size,
                   5534:                                &src_needs_copy,
                   5535:                                &new_entry_needs_copy)) {
                   5536: 
                   5537:                        dstat(++c_vmcc_vocq);
                   5538:                        new_entry->needs_copy = new_entry_needs_copy;
                   5539: 
                   5540:                        /*
                   5541:                         *      Handle copy-on-write obligations
                   5542:                         */
                   5543: 
                   5544:                        if (src_needs_copy && !tmp_entry->needs_copy) {
                   5545:                                if (tmp_entry->is_shared  || 
                   5546:                                     tmp_entry->object.vm_object->true_share ||
                   5547:                                     map_share) {
                   5548:                                        /* dec ref gained in copy_quickly */
                   5549:                                        vm_object_lock(src_object);
                   5550:                                        src_object->ref_count--; 
                   5551:                                        vm_object_res_deallocate(src_object);
                   5552:                                        vm_object_unlock(src_object);
                   5553:                                        new_entry->object.vm_object = 
                   5554:                                                vm_object_copy_delayed(
                   5555:                                                        src_object,
                   5556:                                                        src_offset,     
                   5557:                                                        src_size);
                   5558:                                } else {
                   5559:                                        dstat(++c_vmcc_vopp);
                   5560:                                        vm_object_pmap_protect(
                   5561:                                                src_object,
                   5562:                                                src_offset,
                   5563:                                                src_size,
                   5564:                                                (src_entry->is_shared ? 
                   5565:                                                        PMAP_NULL
                   5566:                                                        : src_map->pmap),
                   5567:                                                src_entry->vme_start,
                   5568:                                                src_entry->protection &
                   5569:                                                        ~VM_PROT_WRITE);
                   5570: 
                   5571:                                        tmp_entry->needs_copy = TRUE;
                   5572:                                }
                   5573:                        }
                   5574: 
                   5575:                        /*
                   5576:                         *      The map has never been unlocked, so it's safe
                   5577:                         *      to move to the next entry rather than doing
                   5578:                         *      another lookup.
                   5579:                         */
                   5580: 
                   5581:                        goto CopySuccessful;
                   5582:                }
                   5583: 
                   5584:                new_entry->needs_copy = FALSE;
                   5585: 
                   5586:                /*
                   5587:                 *      Take an object reference, so that we may
                   5588:                 *      release the map lock(s).
                   5589:                 */
                   5590: 
                   5591:                assert(src_object != VM_OBJECT_NULL);
                   5592:                vm_object_reference(src_object);
                   5593: 
                   5594:                /*
                   5595:                 *      Record the timestamp for later verification.
                   5596:                 *      Unlock the map.
                   5597:                 */
                   5598: 
                   5599:                version.main_timestamp = src_map->timestamp;
                   5600:                vm_map_unlock(src_map);
                   5601: 
                   5602:                /*
                   5603:                 *      Perform the copy
                   5604:                 */
                   5605: 
                   5606:                if (was_wired) {
                   5607:                        dstat(++c_vmcc_vocs);
                   5608:                        vm_object_lock(src_object);
                   5609:                        result = vm_object_copy_slowly(
                   5610:                                        src_object,
                   5611:                                        src_offset,
                   5612:                                        src_size,
                   5613:                                        THREAD_UNINT,
                   5614:                                        &new_entry->object.vm_object);
                   5615:                        new_entry->offset = 0;
                   5616:                        new_entry->needs_copy = FALSE;
                   5617:                } else {
                   5618:                        dstat(++c_vmcc_vocstrat);
                   5619:                        result = vm_object_copy_strategically(src_object,
                   5620:                                src_offset,
                   5621:                                src_size,
                   5622:                                &new_entry->object.vm_object,
                   5623:                                &new_entry->offset,
                   5624:                                &new_entry_needs_copy);
                   5625: 
                   5626:                        new_entry->needs_copy = new_entry_needs_copy;
                   5627:                        
                   5628:                }
                   5629: 
                   5630:                if (result != KERN_SUCCESS &&
                   5631:                    result != KERN_MEMORY_RESTART_COPY) {
                   5632:                        vm_map_lock(src_map);
                   5633:                        RETURN(result);
                   5634:                }
                   5635: 
                   5636:                /*
                   5637:                 *      Throw away the extra reference
                   5638:                 */
                   5639: 
                   5640:                vm_object_deallocate(src_object);
                   5641: 
                   5642:                /*
                   5643:                 *      Verify that the map has not substantially
                   5644:                 *      changed while the copy was being made.
                   5645:                 */
                   5646: 
                   5647:                vm_map_lock(src_map);   /* Increments timestamp once! */
                   5648: 
                   5649:                if ((version.main_timestamp + 1) == src_map->timestamp)
                   5650:                        goto VerificationSuccessful;
                   5651: 
                   5652:                /*
                   5653:                 *      Simple version comparison failed.
                   5654:                 *
                   5655:                 *      Retry the lookup and verify that the
                   5656:                 *      same object/offset are still present.
                   5657:                 *
                   5658:                 *      [Note: a memory manager that colludes with
                   5659:                 *      the calling task can detect that we have
                   5660:                 *      cheated.  While the map was unlocked, the
                   5661:                 *      mapping could have been changed and restored.]
                   5662:                 */
                   5663: 
                   5664:                dstat(++c_vmcc_vmle);
                   5665:                if (!vm_map_lookup_entry(src_map, src_start, &tmp_entry)) {
                   5666:                        RETURN(KERN_INVALID_ADDRESS);
                   5667:                }
                   5668: 
                   5669:                src_entry = tmp_entry;
                   5670:                vm_map_clip_start(src_map, src_entry, src_start);
                   5671: 
                   5672:                if ((src_entry->protection & VM_PROT_READ == VM_PROT_NONE &&
                   5673:                        !use_maxprot) ||
                   5674:                    src_entry->max_protection & VM_PROT_READ == 0)
                   5675:                        goto VerificationFailed;
                   5676: 
                   5677:                if (src_entry->vme_end < new_entry->vme_end)
                   5678:                        src_size = (new_entry->vme_end = src_entry->vme_end) - src_start;
                   5679: 
                   5680:                if ((src_entry->object.vm_object != src_object) ||
                   5681:                    (src_entry->offset != src_offset) ) {
                   5682: 
                   5683:                        /*
                   5684:                         *      Verification failed.
                   5685:                         *
                   5686:                         *      Start over with this top-level entry.
                   5687:                         */
                   5688: 
                   5689:                 VerificationFailed: ;
                   5690: 
                   5691:                        vm_object_deallocate(new_entry->object.vm_object);
                   5692:                        tmp_entry = src_entry;
                   5693:                        continue;
                   5694:                }
                   5695: 
                   5696:                /*
                   5697:                 *      Verification succeeded.
                   5698:                 */
                   5699: 
                   5700:         VerificationSuccessful: ;
                   5701: 
                   5702:                if (result == KERN_MEMORY_RESTART_COPY)
                   5703:                        goto RestartCopy;
                   5704: 
                   5705:                /*
                   5706:                 *      Copy succeeded.
                   5707:                 */
                   5708: 
                   5709:         CopySuccessful: ;
                   5710: 
                   5711:                /*
                   5712:                 *      Link in the new copy entry.
                   5713:                 */
                   5714: 
                   5715:                vm_map_copy_entry_link(copy, vm_map_copy_last_entry(copy),
                   5716:                                       new_entry);
                   5717:                
                   5718:                /*
                   5719:                 *      Determine whether the entire region
                   5720:                 *      has been copied.
                   5721:                 */
                   5722:                src_start = new_entry->vme_end;
                   5723:                new_entry = VM_MAP_ENTRY_NULL;
                   5724:                while ((src_start >= src_end) && (src_end != 0)) {
                   5725:                        if (src_map != base_map) {
                   5726:                                submap_map_t    *ptr;
                   5727: 
                   5728:                                ptr = parent_maps;
                   5729:                                assert(ptr != NULL);
                   5730:                                parent_maps = parent_maps->next;
                   5731:                                vm_map_lock(ptr->parent_map);
                   5732:                                vm_map_unlock(src_map);
                   5733:                                src_map = ptr->parent_map;
                   5734:                                src_start = ptr->base_start;
                   5735:                                src_end = ptr->base_end;
                   5736:                                if ((src_end > src_start) &&
                   5737:                                              !vm_map_lookup_entry(
                   5738:                                              src_map, src_start, &tmp_entry))
                   5739:                                        RETURN(KERN_INVALID_ADDRESS);
                   5740:                                kfree((vm_offset_t)ptr, sizeof(submap_map_t));
                   5741:                                if(parent_maps == NULL)
                   5742:                                        map_share = FALSE;
                   5743:                                src_entry = tmp_entry->vme_prev;
                   5744:                        } else
                   5745:                                break;
                   5746:                }
                   5747:                if ((src_start >= src_end) && (src_end != 0))
                   5748:                        break;
                   5749: 
                   5750:                /*
                   5751:                 *      Verify that there are no gaps in the region
                   5752:                 */
                   5753: 
                   5754:                tmp_entry = src_entry->vme_next;
                   5755:                dstat(++c_vmcc_reloop);
                   5756:                if (tmp_entry->vme_start != src_start)
                   5757:                        RETURN(KERN_INVALID_ADDRESS);
                   5758:        }
                   5759: 
                   5760:        /*
                   5761:         * If the source should be destroyed, do it now, since the
                   5762:         * copy was successful. 
                   5763:         */
                   5764:        if (src_destroy) {
                   5765:                dstat(++c_vmcc_vmd);
                   5766:                (void) vm_map_delete(src_map,
                   5767:                                     trunc_page(src_addr),
                   5768:                                     src_end,
                   5769:                                     (src_map == kernel_map) ?
                   5770:                                        VM_MAP_REMOVE_KUNWIRE :
                   5771:                                        VM_MAP_NO_FLAGS);
                   5772:        }
                   5773: 
                   5774:        vm_map_unlock(src_map);
                   5775: 
                   5776:        *copy_result = copy;
                   5777:        return(KERN_SUCCESS);
                   5778: 
                   5779: #undef RETURN
                   5780: }
                   5781: 
                   5782: /*
                   5783:  *     vm_map_copyin_object:
                   5784:  *
                   5785:  *     Create a copy object from an object.
                   5786:  *     Our caller donates an object reference.
                   5787:  */
                   5788: 
                   5789: kern_return_t
                   5790: vm_map_copyin_object(
                   5791:        vm_object_t     object,
                   5792:        vm_offset_t     offset,         /* offset of region in object */
                   5793:        vm_size_t       size,           /* size of region in object */
                   5794:        vm_map_copy_t   *copy_result)   /* OUT */
                   5795: {
                   5796:        vm_map_copy_t   copy;           /* Resulting copy */
                   5797: 
                   5798:        /*
                   5799:         *      We drop the object into a special copy object
                   5800:         *      that contains the object directly.
                   5801:         */
                   5802: 
                   5803:        copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
                   5804:        copy->type = VM_MAP_COPY_OBJECT;
                   5805:        copy->cpy_object = object;
                   5806:        copy->cpy_index = 0;
                   5807:        copy->offset = offset;
                   5808:        copy->size = size;
                   5809: 
                   5810:        *copy_result = copy;
                   5811:        return(KERN_SUCCESS);
                   5812: }
                   5813: 
                   5814: /*
                   5815:  *     vm_map_copyin_page_list_cont:
                   5816:  *
                   5817:  *     Continuation routine for vm_map_copyin_page_list.
                   5818:  *     
                   5819:  *     If vm_map_copyin_page_list can't fit the entire vm range
                   5820:  *     into a single page list object, it creates a continuation.
                   5821:  *     When the target of the operation has used the pages in the
                   5822:  *     initial page list, it invokes the continuation, which calls
                   5823:  *     this routine.  If an error happens, the continuation is aborted
                   5824:  *     (abort arg to this routine is TRUE).  To avoid deadlocks, the
                   5825:  *     pages are discarded from the initial page list before invoking
                   5826:  *     the continuation.
                   5827:  *
                   5828:  *     NOTE: This is not the same sort of continuation used by
                   5829:  *     the scheduler.
                   5830:  */
                   5831: 
                   5832: kern_return_t
                   5833: vm_map_copyin_page_list_cont(
                   5834:        vm_map_copyin_args_t    cont_args,
                   5835:        vm_map_copy_t           *copy_result)   /* OUT */
                   5836: {
                   5837:        kern_return_t   result = KERN_SUCCESS;
                   5838:        register boolean_t      abort, src_destroy, src_destroy_only;
                   5839: 
                   5840:        /*
                   5841:         *      Check for cases that only require memory destruction.
                   5842:         */
                   5843:        abort = (copy_result == (vm_map_copy_t *) 0);
                   5844:        src_destroy = (cont_args->destroy_len != (vm_size_t) 0);
                   5845:        src_destroy_only = (cont_args->src_len == (vm_size_t) 0);
                   5846: 
                   5847:        if (abort || src_destroy_only) {
                   5848:                if (src_destroy)
                   5849:                        result = vm_map_remove(cont_args->map,
                   5850:                            cont_args->destroy_addr,
                   5851:                            cont_args->destroy_addr + cont_args->destroy_len,
                   5852:                            VM_MAP_NO_FLAGS);
                   5853:                if (!abort)
                   5854:                        *copy_result = VM_MAP_COPY_NULL;
                   5855:        }
                   5856:        else {
                   5857:                result = vm_map_copyin_page_list(cont_args->map,
                   5858:                        cont_args->src_addr, cont_args->src_len,
                   5859:                        cont_args->options, copy_result, TRUE);
                   5860: 
                   5861:                if (src_destroy &&
                   5862:                    (cont_args->options & VM_MAP_COPYIN_OPT_STEAL_PAGES) &&
                   5863:                    vm_map_copy_has_cont(*copy_result)) {
                   5864:                            vm_map_copyin_args_t        new_args;
                   5865:                            /*
                   5866:                             *  Transfer old destroy info.
                   5867:                             */
                   5868:                            new_args = (vm_map_copyin_args_t)
                   5869:                                        (*copy_result)->cpy_cont_args;
                   5870:                            new_args->destroy_addr = cont_args->destroy_addr;
                   5871:                            new_args->destroy_len = cont_args->destroy_len;
                   5872:                }
                   5873:        }
                   5874:        
                   5875:        vm_map_deallocate(cont_args->map);
                   5876:        kfree((vm_offset_t)cont_args, sizeof(vm_map_copyin_args_data_t));
                   5877: 
                   5878:        return(result);
                   5879: }
                   5880: 
                   5881: /*
                   5882:  *     vm_map_copyin_page_list:
                   5883:  *
                   5884:  *     This is a variant of vm_map_copyin that copies in a list of pages.
                   5885:  *     If steal_pages is TRUE, the pages are only in the returned list.
                   5886:  *     If steal_pages is FALSE, the pages are busy and still in their
                   5887:  *     objects.  A continuation may be returned if not all the pages fit:
                   5888:  *     the recipient of this copy_result must be prepared to deal with it.
                   5889:  */
                   5890: 
                   5891: kern_return_t
                   5892: vm_map_copyin_page_list(
                   5893:     vm_map_t           src_map,
                   5894:     vm_offset_t                src_addr,
                   5895:     vm_size_t          len,
                   5896:     int                        options,
                   5897:     vm_map_copy_t      *copy_result,   /* OUT */
                   5898:     boolean_t          is_cont)
                   5899: {
                   5900:     vm_map_entry_t             src_entry;
                   5901:     vm_page_t                  m;
                   5902:     vm_offset_t                        src_start;
                   5903:     vm_offset_t                        src_end;
                   5904:     vm_size_t                  src_size;
                   5905:     register vm_object_t       src_object;
                   5906:     register vm_offset_t       src_offset;
                   5907:     vm_offset_t                        src_last_offset;
                   5908:     register vm_map_copy_t     copy;           /* Resulting copy */
                   5909:     kern_return_t              result = KERN_SUCCESS;
                   5910:     boolean_t                  need_map_lookup;
                   5911:     vm_map_copyin_args_t       cont_args;
                   5912:     kern_return_t              error_code;
                   5913:     vm_prot_t                  prot;
                   5914:     boolean_t                  wired;
                   5915:     boolean_t                  no_zero_fill;
                   5916: 
                   5917:     submap_map_t       *parent_maps = NULL;
                   5918:     vm_map_t           base_map = src_map;
                   5919: 
                   5920:     prot = (options & VM_MAP_COPYIN_OPT_VM_PROT);
                   5921:     no_zero_fill = (options & VM_MAP_COPYIN_OPT_NO_ZERO_FILL);
                   5922:     
                   5923:     /*
                   5924:      *         If steal_pages is FALSE, this leaves busy pages in
                   5925:      * the object.  A continuation must be used if src_destroy
                   5926:      * is true in this case (!steal_pages && src_destroy).
                   5927:      *
                   5928:      * XXX     Still have a more general problem of what happens
                   5929:      * XXX     if the same page occurs twice in a list.  Deadlock
                   5930:      * XXX     can happen if vm_fault_page was called.  A
                   5931:      * XXX     possible solution is to use a continuation if vm_fault_page
                   5932:      * XXX     is called and we cross a map entry boundary.
                   5933:      */
                   5934: 
                   5935:     /*
                   5936:      * Check for copies of zero bytes.
                   5937:      */
                   5938: 
                   5939:     if (len == 0) {
                   5940:         *copy_result = VM_MAP_COPY_NULL;
                   5941:        return(KERN_SUCCESS);
                   5942:     }
                   5943: 
                   5944:     /*
                   5945:      * Compute start and end of region
                   5946:      */
                   5947: 
                   5948:     src_start = trunc_page(src_addr);
                   5949:     src_end = round_page(src_addr + len);
                   5950: 
                   5951:     /*
                   5952:      * If the region is not page aligned, override the no_zero_fill
                   5953:      * argument.
                   5954:      */
                   5955: 
                   5956:     if (options & VM_MAP_COPYIN_OPT_NO_ZERO_FILL) {
                   5957:         if (!page_aligned(src_addr) || !page_aligned(src_addr +len))
                   5958:            options &= ~VM_MAP_COPYIN_OPT_NO_ZERO_FILL;
                   5959:     }
                   5960: 
                   5961:     /*
                   5962:      * Check that the end address doesn't overflow
                   5963:      */
                   5964: 
                   5965:     if (src_end <= src_start && (src_end < src_start || src_start != 0)) {
                   5966:         return KERN_INVALID_ADDRESS;
                   5967:     }
                   5968: 
                   5969:     /*
                   5970:      * Allocate a header element for the page list.
                   5971:      *
                   5972:      * Record original offset and size, as caller may not
                   5973:      *      be page-aligned.
                   5974:      */
                   5975: 
                   5976:     copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
                   5977:     copy->type = VM_MAP_COPY_PAGE_LIST;
                   5978:     copy->cpy_npages = 0;
                   5979:     copy->cpy_page_loose = FALSE;
                   5980:     copy->offset = src_addr;
                   5981:     copy->size = len;
                   5982:     copy->cpy_cont = VM_MAP_COPY_CONT_NULL;
                   5983:     copy->cpy_cont_args = VM_MAP_COPYIN_ARGS_NULL;
                   5984:        
                   5985:     /*
                   5986:      * Find the beginning of the region.
                   5987:      */
                   5988: 
                   5989: do_map_lookup:
                   5990: 
                   5991:     vm_map_lock(src_map);
                   5992: 
                   5993:     if (!vm_map_lookup_entry(src_map, src_start, &src_entry)) {
                   5994:         result = KERN_INVALID_ADDRESS;
                   5995:        goto error;
                   5996:     }
                   5997:     need_map_lookup = FALSE;
                   5998: 
                   5999:     /*
                   6000:      * Go through entries until we get to the end.
                   6001:      */
                   6002: 
                   6003:     while (TRUE) {
                   6004:         if ((src_entry->protection & prot) != prot) {
                   6005:            result = KERN_PROTECTION_FAILURE;
                   6006:            goto error;
                   6007:        }
                   6008: 
                   6009:        /* translate down through submaps to find the target entry */
                   6010:        while(src_entry->is_sub_map) {
                   6011:                vm_size_t submap_len;
                   6012:                submap_map_t *ptr;
                   6013: 
                   6014:                ptr = (submap_map_t *)kalloc(sizeof(submap_map_t));
                   6015:                ptr->next = parent_maps;
                   6016:                parent_maps = ptr;
                   6017:                ptr->parent_map = src_map;
                   6018:                ptr->base_start = src_start;
                   6019:                ptr->base_end = src_end;
                   6020:                submap_len = src_entry->vme_end - src_entry->vme_start;
                   6021:                if(submap_len > (src_end-src_start))
                   6022:                                submap_len = src_end-src_start;
                   6023:                ptr->base_start += submap_len;
                   6024:        
                   6025:                src_start -= src_entry->vme_start;
                   6026:                src_start += src_entry->offset;
                   6027:                src_end = src_start + submap_len;
                   6028:                src_map = src_entry->object.sub_map;
                   6029:                vm_map_lock(src_map);
                   6030:                vm_map_unlock(ptr->parent_map);
                   6031:                if (!vm_map_lookup_entry(
                   6032:                                src_map, src_start, &src_entry)) {
                   6033:                        result = KERN_INVALID_ADDRESS;
                   6034:                        goto error;
                   6035:                }
                   6036:                vm_map_clip_start(src_map, src_entry, src_start);
                   6037:        }
                   6038: 
                   6039:        wired = (src_entry->wired_count != 0);
                   6040: 
                   6041:        if (src_end > src_entry->vme_end)
                   6042:            src_size = src_entry->vme_end - src_start;
                   6043:        else
                   6044:            src_size = src_end - src_start;
                   6045: 
                   6046:        src_object = src_entry->object.vm_object;
                   6047: 
                   6048:        /*
                   6049:         *      If src_object is NULL, allocate it now;
                   6050:         *      we're going to fault on it shortly.
                   6051:         */
                   6052:        if (src_object == VM_OBJECT_NULL) {
                   6053:            src_object = vm_object_allocate((vm_size_t)
                   6054:                                            src_entry->vme_end -
                   6055:                                            src_entry->vme_start);
                   6056:            src_entry->object.vm_object = src_object;
                   6057:        }
                   6058:        else if (src_entry->needs_copy && (prot & VM_PROT_WRITE)) {
                   6059:            vm_object_shadow(
                   6060:                             &src_entry->object.vm_object,
                   6061:                             &src_entry->offset,
                   6062:                             (vm_size_t) (src_entry->vme_end -
                   6063:                                          src_entry->vme_start));
                   6064: 
                   6065:            src_entry->needs_copy = FALSE;
                   6066: 
                   6067:            /* reset src_object */
                   6068:            src_object = src_entry->object.vm_object;
                   6069:        }
                   6070: 
                   6071:        /*
                   6072:         * calculate src_offset now, since vm_object_shadow
                   6073:         * may have changed src_entry->offset.
                   6074:         */
                   6075:        src_offset = src_entry->offset + (src_start - src_entry->vme_start);
                   6076: 
                   6077:        /*
                   6078:         * Iterate over pages.  Fault in ones that aren't present.
                   6079:         */
                   6080:        src_last_offset = src_offset + src_size;
                   6081:        for (; (src_offset < src_last_offset);
                   6082:             src_offset += PAGE_SIZE, src_start += PAGE_SIZE) {
                   6083: 
                   6084:            if (copy->cpy_npages == VM_MAP_COPY_PAGE_LIST_MAX) {
                   6085:                vm_offset_t     src_delta;
                   6086: make_continuation:
                   6087:                /*
                   6088:                 * At this point we have the max number of
                   6089:                 * pages busy for this thread that we're
                   6090:                 * willing to allow.  Stop here and record
                   6091:                 * arguments for the remainder.  Note:
                   6092:                 * this means that this routine isn't atomic,
                   6093:                 * but that's the breaks.  Note that only
                   6094:                 * the first vm_map_copy_t that comes back
                   6095:                 * from this routine has the right offset
                   6096:                 * and size; those from continuations are
                   6097:                 * page rounded, and short by the amount
                   6098:                 * already done.
                   6099:                 *
                   6100:                 * Reset src_end so the src_destroy
                   6101:                 * code at the bottom doesn't do
                   6102:                 * something stupid.
                   6103:                 */
                   6104: 
                   6105:                src_delta = src_end - src_start;
                   6106:                while (src_map != base_map) {
                   6107:                        submap_map_t *ptr;
                   6108: 
                   6109:                        if(!need_map_lookup) {
                   6110:                                vm_map_unlock(src_map);
                   6111:                        }
                   6112:                        ptr = parent_maps;
                   6113:                        assert(ptr != NULL);
                   6114:                        parent_maps = parent_maps->next;
                   6115:                        src_map = ptr->parent_map;
                   6116:                        src_start = ptr->base_start - src_delta;
                   6117:                        src_delta = ptr->base_end - src_start;
                   6118:                        kfree((vm_offset_t)ptr, sizeof(submap_map_t));
                   6119: 
                   6120:                        need_map_lookup = TRUE;
                   6121:                }
                   6122:                src_end = src_start;
                   6123: 
                   6124: 
                   6125:                cont_args = (vm_map_copyin_args_t) 
                   6126:                            kalloc(sizeof(vm_map_copyin_args_data_t));
                   6127:                cont_args->map = src_map;
                   6128:                vm_map_reference(src_map);
                   6129:                cont_args->src_addr = src_start;
                   6130:                cont_args->src_len = len - (src_start - src_addr);
                   6131:                if (options & VM_MAP_COPYIN_OPT_SRC_DESTROY) {
                   6132:                    cont_args->destroy_addr = cont_args->src_addr;
                   6133:                    cont_args->destroy_len = cont_args->src_len;
                   6134:                } else {
                   6135:                    cont_args->destroy_addr = (vm_offset_t) 0;
                   6136:                    cont_args->destroy_len = (vm_offset_t) 0;
                   6137:                }
                   6138:                cont_args->options = options;
                   6139:                
                   6140:                copy->cpy_cont_args = cont_args;
                   6141:                copy->cpy_cont = vm_map_copyin_page_list_cont;
                   6142:                
                   6143:                break;
                   6144:            }
                   6145: 
                   6146:            /*
                   6147:             *  Try to find the page of data.  Have to
                   6148:             *  fault it in if there's no page, or something
                   6149:             *  going on with the page, or the object has
                   6150:             *  a copy object.
                   6151:             */
                   6152:            vm_object_lock(src_object);
                   6153:            vm_object_paging_begin(src_object);
                   6154:            if (((m = vm_page_lookup(src_object, src_offset)) !=
                   6155:                 VM_PAGE_NULL) && 
                   6156:                !m->busy && !m->fictitious && !m->unusual &&
                   6157:                ((prot & VM_PROT_WRITE) == 0 ||
                   6158:                 (m->object->copy == VM_OBJECT_NULL))) {
                   6159:              
                   6160:                if (!m->absent &&
                   6161:                    !(options & VM_MAP_COPYIN_OPT_STEAL_PAGES)) {
                   6162: 
                   6163:                        /* 
                   6164:                         * The page is present and will not be
                   6165:                         * replaced, prep it. Thus allowing
                   6166:                         * mutiple access on this page 
                   6167:                         */
                   6168:                        kern_return_t kr;
                   6169: 
                   6170:                        kr = vm_page_prep(m);
                   6171:                        assert(kr == KERN_SUCCESS);
                   6172:                        kr = vm_page_pin(m);
                   6173:                        assert(kr == KERN_SUCCESS);
                   6174:                } else {
                   6175:                        /*
                   6176:                         *      This is the page.  Mark it busy
                   6177:                         *      and keep the paging reference on
                   6178:                         *      the object whilst we do our thing.
                   6179:                         */
                   6180:        
                   6181:                        m->busy = TRUE;
                   6182:                }
                   6183:            } else {
                   6184:                vm_prot_t       result_prot;
                   6185:                vm_page_t       top_page;
                   6186:                kern_return_t   kr;
                   6187:                boolean_t       data_supply;
                   6188:                                
                   6189:                /*
                   6190:                 *      Have to fault the page in; must
                   6191:                 *      unlock the map to do so.  While
                   6192:                 *      the map is unlocked, anything
                   6193:                 *      can happen, we must lookup the
                   6194:                 *      map entry before continuing.
                   6195:                 */
                   6196:                vm_map_unlock(src_map);
                   6197:                need_map_lookup = TRUE;
                   6198:                data_supply = src_object->silent_overwrite &&
                   6199:                  (prot & VM_PROT_WRITE) &&
                   6200:                    src_start >= src_addr &&
                   6201:                      src_start + PAGE_SIZE <=
                   6202:                        src_addr + len;
                   6203: 
                   6204: retry:
                   6205:                result_prot = prot;
                   6206:                                
                   6207:                XPR(XPR_VM_FAULT,
                   6208:                    "vm_map_copyin_page_list -> vm_fault_page\n",
                   6209:                    0,0,0,0,0);
                   6210:                kr = vm_fault_page(src_object, src_offset,
                   6211:                                   prot, FALSE, THREAD_UNINT,
                   6212:                                   src_entry->offset,
                   6213:                                   src_entry->offset +
                   6214:                                   (src_entry->vme_end -
                   6215:                                    src_entry->vme_start),
                   6216:                                   VM_BEHAVIOR_SEQUENTIAL,
                   6217:                                   &result_prot, &m, &top_page,
                   6218:                                   (int *)0,
                   6219:                                   &error_code,
                   6220:                                   options & VM_MAP_COPYIN_OPT_NO_ZERO_FILL,
                   6221:                                   data_supply);
                   6222:                /*
                   6223:                 *      Cope with what happened.
                   6224:                 */
                   6225:                switch (kr) {
                   6226:                case VM_FAULT_SUCCESS:
                   6227: 
                   6228:                    /*
                   6229:                     *  If we lost write access,
                   6230:                     *  try again.
                   6231:                     */
                   6232:                    if ((prot & VM_PROT_WRITE) &&
                   6233:                        !(result_prot & VM_PROT_WRITE)) {
                   6234:                        vm_object_lock(src_object);
                   6235:                        vm_object_paging_begin(src_object);
                   6236:                        goto retry;
                   6237:                    }
                   6238:                    break;
                   6239:                case VM_FAULT_INTERRUPTED: /* ??? */
                   6240:                case VM_FAULT_RETRY:
                   6241:                    vm_object_lock(src_object);
                   6242:                    vm_object_paging_begin(src_object);
                   6243:                    goto retry;
                   6244:                case VM_FAULT_MEMORY_SHORTAGE:
                   6245:                    VM_PAGE_WAIT();
                   6246:                    vm_object_lock(src_object);
                   6247:                    vm_object_paging_begin(src_object);
                   6248:                    goto retry;
                   6249:                case VM_FAULT_FICTITIOUS_SHORTAGE:
                   6250:                    vm_page_more_fictitious();
                   6251:                    vm_object_lock(src_object);
                   6252:                    vm_object_paging_begin(src_object);
                   6253:                    goto retry;
                   6254:                case VM_FAULT_MEMORY_ERROR:
                   6255:                    /*
                   6256:                     * Something broke.  If this
                   6257:                     * is a continuation, return
                   6258:                     * a partial result if possible,
                   6259:                     * else fail the whole thing.
                   6260:                     * In the continuation case, the
                   6261:                     * next continuation call will
                   6262:                     * get this error if it persists.
                   6263:                     */
                   6264:                    vm_map_lock(src_map);
                   6265:                    if (is_cont &&
                   6266:                        copy->cpy_npages != 0)
                   6267:                        goto make_continuation;
                   6268: 
                   6269:                    result = error_code ? error_code : KERN_MEMORY_ERROR;
                   6270:                    goto error;
                   6271:                }
                   6272:                                
                   6273:                if (top_page != VM_PAGE_NULL) {
                   6274:                    vm_object_lock(src_object);
                   6275:                    VM_PAGE_FREE(top_page);
                   6276:                    vm_object_paging_end(src_object);
                   6277:                    vm_object_unlock(src_object);
                   6278:                }
                   6279: 
                   6280:            }
                   6281: 
                   6282:            /*
                   6283:             * The page is busy, its object is locked, and
                   6284:             * we have a paging reference on it.  Either
                   6285:             * the map is locked, or need_map_lookup is
                   6286:             * TRUE.
                   6287:             */
                   6288: 
                   6289:            /*
                   6290:             * Put the page in the page list.
                   6291:             */
                   6292:            copy->cpy_page_list[copy->cpy_npages++] = m;
                   6293:            vm_object_unlock(m->object);
                   6294: 
                   6295:            /*
                   6296:             * Pmap enter support.  Only used for
                   6297:             * device I/O for colocated server.
                   6298:             *
                   6299:             * WARNING:  This code assumes that this
                   6300:             * option is only used for well behaved
                   6301:             * memory.  If the mapping has changed,
                   6302:             * the following code will make mistakes.
                   6303:             *
                   6304:             * XXXO probably ought to do pmap_extract first,
                   6305:             * XXXO to avoid needless pmap_enter, but this
                   6306:             * XXXO can't detect protection mismatch??
                   6307:             */
                   6308: 
                   6309:            if (options & VM_MAP_COPYIN_OPT_PMAP_ENTER) {
                   6310:                /*
                   6311:                 * XXX  Only used on kernel map.
                   6312:                 * XXX  Must not remove VM_PROT_WRITE on
                   6313:                 * XXX  an I/O only requiring VM_PROT_READ
                   6314:                 * XXX  as another I/O may be active on same page
                   6315:                 * XXX  assume that if mapping exists, it must
                   6316:                 * XXX  have the equivalent of at least VM_PROT_READ,
                   6317:                 * XXX  but don't assume it has VM_PROT_WRITE as the
                   6318:                 * XXX  pmap might not all the rights of the object
                   6319:                 */
                   6320:                assert(vm_map_pmap(src_map) == kernel_pmap);
                   6321:              
                   6322:                if ((prot & VM_PROT_WRITE) ||
                   6323:                    (pmap_extract(vm_map_pmap(src_map),
                   6324:                                  src_start) != m->phys_addr))
                   6325: 
                   6326:                    PMAP_ENTER(vm_map_pmap(src_map), src_start,
                   6327:                               m, prot, wired);
                   6328:            }
                   6329:            if(need_map_lookup) {
                   6330:                need_map_lookup = FALSE;
                   6331:                vm_map_lock(src_map);
                   6332:                if (!vm_map_lookup_entry(src_map, src_start, &src_entry)) {
                   6333:                   result = KERN_INVALID_ADDRESS;
                   6334:                   goto error;
                   6335:                }
                   6336:           }
                   6337:        }
                   6338:                        
                   6339:        /*
                   6340:         *      Verify that there are no gaps in the region
                   6341:         */
                   6342:        src_start = src_entry->vme_end;
                   6343:        if (src_start < src_end) {
                   6344:                src_entry = src_entry->vme_next;
                   6345:                if (need_map_lookup) {
                   6346:                        need_map_lookup = FALSE;
                   6347:                        vm_map_lock(src_map);
                   6348:                        if(!vm_map_lookup_entry(src_map, 
                   6349:                                                src_start, &src_entry)) {
                   6350:                                result = KERN_INVALID_ADDRESS;
                   6351:                                goto error;
                   6352:                        }
                   6353:                } else if (src_entry->vme_start != src_start) {
                   6354:                        result = KERN_INVALID_ADDRESS;
                   6355:                        goto error;
                   6356:                }
                   6357:        }
                   6358: 
                   6359:        /*
                   6360:         *      DETERMINE whether the entire region
                   6361:         *      has been copied.
                   6362:         */
                   6363: 
                   6364:        while ((src_start >= src_end) && (src_end != 0)) {
                   6365:                if (src_map != base_map) {
                   6366:                        submap_map_t    *ptr;
                   6367: 
                   6368:                        ptr = parent_maps;
                   6369:                        assert(ptr != NULL);
                   6370:                        parent_maps = parent_maps->next;
                   6371:                        src_start = ptr->base_start;
                   6372:                        src_end = ptr->base_end;
                   6373:                        if(need_map_lookup) {
                   6374:                                need_map_lookup = FALSE;
                   6375:                        }
                   6376:                        else {
                   6377:                                vm_map_unlock(src_map);
                   6378:                        }
                   6379:                        src_map = ptr->parent_map;
                   6380:                        vm_map_lock(src_map);
                   6381:                        if((src_start < src_end) &&
                   6382:                                        (!vm_map_lookup_entry(ptr->parent_map, 
                   6383:                                        src_start, &src_entry))) {
                   6384:                                result = KERN_INVALID_ADDRESS;
                   6385:                                kfree((vm_offset_t)ptr, sizeof(submap_map_t));
                   6386:                                goto error;
                   6387:                        }
                   6388:                        kfree((vm_offset_t)ptr, sizeof(submap_map_t));
                   6389:                } else
                   6390:                        break;
                   6391:        }
                   6392:        if ((src_start >= src_end) && (src_end != 0)) {
                   6393:                if (need_map_lookup)
                   6394:                        vm_map_lock(src_map);
                   6395:                break;
                   6396:        }
                   6397: 
                   6398:     }
                   6399: 
                   6400:     /*
                   6401:      * If steal_pages is true, make sure all
                   6402:      * pages in the copy are not in any object
                   6403:      * We try to remove them from the original
                   6404:      * object, but we may have to copy them.
                   6405:      *
                   6406:      * At this point every page in the list is busy
                   6407:      * and holds a paging reference to its object.
                   6408:      * When we're done stealing, every page is busy,
                   6409:      * and in no object (m->tabled == FALSE).
                   6410:      */
                   6411:     src_start = trunc_page(src_addr);
                   6412:     if (options & VM_MAP_COPYIN_OPT_STEAL_PAGES) {
                   6413:         register int   i;
                   6414:        vm_offset_t     page_vaddr;
                   6415:        vm_offset_t     unwire_end;
                   6416:        vm_offset_t     map_entry_end;
                   6417:        boolean_t       share_map = FALSE;
                   6418: 
                   6419:        unwire_end = src_start;
                   6420:        map_entry_end = src_start;
                   6421:        for (i = 0; i < copy->cpy_npages; i++) {
                   6422:          
                   6423:          
                   6424:            /*
                   6425:             * Remove the page from its object if it
                   6426:             * can be stolen.  It can be stolen if:
                   6427:             *
                   6428:             * (1) The source is being destroyed, 
                   6429:             *       the object is internal (hence
                   6430:             *       temporary), and not shared.
                   6431:             * (2) The page is not precious.
                   6432:             *
                   6433:             * The not shared check consists of two
                   6434:             * parts:  (a) there are no objects that
                   6435:             * shadow this object.  (b) it is not the
                   6436:             * object in any shared map entries (i.e.,
                   6437:             * use_shared_copy is not set).
                   6438:             *
                   6439:             * The first check (a) means that we can't
                   6440:             * steal pages from objects that are not
                   6441:             * at the top of their shadow chains.  This
                   6442:             * should not be a frequent occurrence.
                   6443:             *
                   6444:             * Stealing wired pages requires telling the
                   6445:             * pmap module to let go of them.
                   6446:             * 
                   6447:             * NOTE: stealing clean pages from objects
                   6448:             *          whose mappings survive requires a call to
                   6449:             * the pmap module.  Maybe later.
                   6450:             */
                   6451:            m = copy->cpy_page_list[i];
                   6452:            src_object = m->object;
                   6453:            vm_object_lock(src_object);
                   6454: 
                   6455:            page_vaddr = src_start + (i * PAGE_SIZE);
                   6456:            if(page_vaddr > map_entry_end) {
                   6457:                if (!vm_map_lookup_entry(src_map, page_vaddr, &src_entry))
                   6458:                        share_map = TRUE;
                   6459:                else if (src_entry->is_sub_map)  {
                   6460:                        map_entry_end = src_entry->vme_end;
                   6461:                        share_map = TRUE;
                   6462:                } else {
                   6463:                        map_entry_end = src_entry->vme_end;
                   6464:                        share_map = FALSE;
                   6465:                }
                   6466:            }
                   6467:            
                   6468: 
                   6469:            if ((options & VM_MAP_COPYIN_OPT_SRC_DESTROY) &&
                   6470:                src_object->internal &&
                   6471:                !src_object->true_share &&
                   6472:                (!src_object->shadowed) &&
                   6473:                (src_object->copy_strategy ==
                   6474:                 MEMORY_OBJECT_COPY_SYMMETRIC) &&
                   6475:                !m->precious &&
                   6476:                !share_map) {
                   6477:                
                   6478:                if (m->wire_count > 0) {
                   6479: 
                   6480:                    assert(m->wire_count == 1);
                   6481:                    /*
                   6482:                     * In order to steal a wired
                   6483:                     * page, we have to unwire it
                   6484:                     * first.  We do this inline
                   6485:                     * here because we have the page.
                   6486:                     *
                   6487:                     * Step 1: Unwire the map entry.
                   6488:                     *  Also tell the pmap module
                   6489:                     *  that this piece of the
                   6490:                     *  pmap is pageable.
                   6491:                     */
                   6492:                    vm_object_unlock(src_object);
                   6493:                    if (page_vaddr >= unwire_end) {
                   6494:                        if (!vm_map_lookup_entry(src_map,
                   6495:                                                 page_vaddr, &src_entry))
                   6496:                            panic("vm_map_copyin_page_list: missing wired map entry");
                   6497: 
                   6498:                        vm_map_clip_start(src_map, src_entry,
                   6499:                                          page_vaddr);
                   6500:                        vm_map_clip_end(src_map, src_entry,
                   6501:                                        src_start + src_size);
                   6502: 
                   6503: /*  revisit why this assert fails CDY
                   6504:                        assert(src_entry->wired_count > 0);
                   6505: */
                   6506:                        src_entry->wired_count = 0;
                   6507:                        src_entry->user_wired_count = 0;
                   6508:                        unwire_end = src_entry->vme_end;
                   6509:                        pmap_pageable(vm_map_pmap(src_map),
                   6510:                                      page_vaddr, unwire_end, TRUE);
                   6511:                    }
                   6512: 
                   6513:                    /*
                   6514:                     * Step 2: Unwire the page.
                   6515:                     * pmap_remove handles this for us.
                   6516:                     */
                   6517:                    vm_object_lock(src_object);
                   6518:                }
                   6519: 
                   6520:                /*
                   6521:                 * Don't need to remove the mapping;
                   6522:                 * vm_map_delete will handle it.
                   6523:                 * 
                   6524:                 * Steal the page.  Setting the wire count
                   6525:                 * to zero is vm_page_unwire without
                   6526:                 * activating the page.
                   6527:                 */
                   6528:                vm_page_lock_queues();
                   6529:                vm_page_remove(m);
                   6530:                if (m->wire_count > 0) {
                   6531:                    m->wire_count = 0;
                   6532:                    vm_page_wire_count--;
                   6533:                } else {
                   6534:                    VM_PAGE_QUEUES_REMOVE(m);
                   6535:                }
                   6536:                vm_page_unlock_queues();
                   6537:            } else {
                   6538:                /*
                   6539:                 * Have to copy this page.  Have to
                   6540:                 * unlock the map while copying,
                   6541:                 * hence no further page stealing.
                   6542:                 * Hence just copy all the pages.
                   6543:                 * Unlock the map while copying;
                   6544:                 * This means no further page stealing.
                   6545:                 */
                   6546:                vm_object_unlock(src_object);
                   6547:                vm_map_unlock(src_map);
                   6548:                vm_map_copy_steal_pages(copy);
                   6549:                vm_map_lock(src_map);
                   6550:                break;
                   6551:            }
                   6552: 
                   6553:            vm_object_paging_end(src_object);
                   6554:            vm_object_unlock(src_object);
                   6555:        }
                   6556: 
                   6557:        copy->cpy_page_loose = TRUE;
                   6558: 
                   6559:        /*
                   6560:         * If the source should be destroyed, do it now, since the
                   6561:         * copy was successful.
                   6562:         */
                   6563: 
                   6564:        if (options & VM_MAP_COPYIN_OPT_SRC_DESTROY) {
                   6565:            (void) vm_map_delete(src_map, src_start,
                   6566:                                 src_end, VM_MAP_NO_FLAGS);
                   6567:        }
                   6568:     } else {
                   6569:         /*
                   6570:         * Not stealing pages leaves busy or prepped pages in the map.
                   6571:         * This will cause source destruction to hang.  Use
                   6572:         * a continuation to prevent this.
                   6573:         */
                   6574:         if ((options & VM_MAP_COPYIN_OPT_SRC_DESTROY) &&
                   6575:            !vm_map_copy_has_cont(copy)) {
                   6576:            cont_args = (vm_map_copyin_args_t) 
                   6577:                        kalloc(sizeof(vm_map_copyin_args_data_t));
                   6578:            vm_map_reference(src_map);
                   6579:            cont_args->map = src_map;
                   6580:            cont_args->src_addr = (vm_offset_t) 0;
                   6581:            cont_args->src_len = (vm_size_t) 0;
                   6582:            cont_args->destroy_addr = src_start;
                   6583:            cont_args->destroy_len = src_end - src_start;
                   6584:            cont_args->options = options;
                   6585: 
                   6586:            copy->cpy_cont_args = cont_args;
                   6587:            copy->cpy_cont = vm_map_copyin_page_list_cont;
                   6588:        }
                   6589:     }
                   6590: 
                   6591:     vm_map_unlock(src_map);
                   6592: 
                   6593:     *copy_result = copy;
                   6594:     return(result);
                   6595: 
                   6596: error:
                   6597:     {
                   6598:        submap_map_t    *ptr;
                   6599: 
                   6600:        vm_map_unlock(src_map);
                   6601:        vm_map_copy_discard(copy);
                   6602: 
                   6603:        for(ptr = parent_maps; ptr != NULL; ptr = parent_maps) {
                   6604:                parent_maps=parent_maps->next;
                   6605:                kfree((vm_offset_t)ptr, sizeof(submap_map_t));
                   6606:        }
                   6607:        return(result);
                   6608:      }
                   6609: }
                   6610: 
                   6611: void
                   6612: vm_map_fork_share(
                   6613:        vm_map_t        old_map,
                   6614:        vm_map_entry_t  old_entry,
                   6615:        vm_map_t        new_map)
                   6616: {
                   6617:        vm_object_t object;
                   6618:        vm_map_entry_t new_entry;
                   6619: 
                   6620:        /*
                   6621:         *      New sharing code.  New map entry
                   6622:         *      references original object.  Internal
                   6623:         *      objects use asynchronous copy algorithm for
                   6624:         *      future copies.  First make sure we have
                   6625:         *      the right object.  If we need a shadow,
                   6626:         *      or someone else already has one, then
                   6627:         *      make a new shadow and share it.
                   6628:         */
                   6629:        
                   6630:        object = old_entry->object.vm_object;
                   6631:        if (old_entry->is_sub_map) {
                   6632:                assert(old_entry->wired_count == 0);
                   6633:        } else if (object == VM_OBJECT_NULL) {
                   6634:                object = vm_object_allocate((vm_size_t)(old_entry->vme_end -
                   6635:                                                        old_entry->vme_start));
                   6636:                old_entry->offset = 0;
                   6637:                old_entry->object.vm_object = object;
                   6638:                assert(!old_entry->needs_copy);
                   6639:        } else if (object->copy_strategy !=
                   6640:                 MEMORY_OBJECT_COPY_SYMMETRIC) {
                   6641:                
                   6642:                /*
                   6643:                 *      We are already using an asymmetric
                   6644:                 *      copy, and therefore we already have
                   6645:                 *      the right object.
                   6646:                 */
                   6647:                
                   6648:                assert(! old_entry->needs_copy);
                   6649:        }
                   6650:        else if (old_entry->needs_copy ||       /* case 1 */
                   6651:                 object->shadowed ||            /* case 2 */
                   6652:                 (!object->true_share &&        /* case 3 */
                   6653:                 !old_entry->is_shared &&
                   6654:                 (object->size >
                   6655:                  (vm_size_t)(old_entry->vme_end -
                   6656:                              old_entry->vme_start)))) {
                   6657:                
                   6658:                /*
                   6659:                 *      We need to create a shadow.
                   6660:                 *      There are three cases here.
                   6661:                 *      In the first case, we need to
                   6662:                 *      complete a deferred symmetrical
                   6663:                 *      copy that we participated in.
                   6664:                 *      In the second and third cases,
                   6665:                 *      we need to create the shadow so
                   6666:                 *      that changes that we make to the
                   6667:                 *      object do not interfere with
                   6668:                 *      any symmetrical copies which
                   6669:                 *      have occured (case 2) or which
                   6670:                 *      might occur (case 3).
                   6671:                 *
                   6672:                 *      The first case is when we had
                   6673:                 *      deferred shadow object creation
                   6674:                 *      via the entry->needs_copy mechanism.
                   6675:                 *      This mechanism only works when
                   6676:                 *      only one entry points to the source
                   6677:                 *      object, and we are about to create
                   6678:                 *      a second entry pointing to the
                   6679:                 *      same object. The problem is that
                   6680:                 *      there is no way of mapping from
                   6681:                 *      an object to the entries pointing
                   6682:                 *      to it. (Deferred shadow creation
                   6683:                 *      works with one entry because occurs
                   6684:                 *      at fault time, and we walk from the
                   6685:                 *      entry to the object when handling
                   6686:                 *      the fault.)
                   6687:                 *
                   6688:                 *      The second case is when the object
                   6689:                 *      to be shared has already been copied
                   6690:                 *      with a symmetric copy, but we point
                   6691:                 *      directly to the object without
                   6692:                 *      needs_copy set in our entry. (This
                   6693:                 *      can happen because different ranges
                   6694:                 *      of an object can be pointed to by
                   6695:                 *      different entries. In particular,
                   6696:                 *      a single entry pointing to an object
                   6697:                 *      can be split by a call to vm_inherit,
                   6698:                 *      which, combined with task_create, can
                   6699:                 *      result in the different entries
                   6700:                 *      having different needs_copy values.)
                   6701:                 *      The shadowed flag in the object allows
                   6702:                 *      us to detect this case. The problem
                   6703:                 *      with this case is that if this object
                   6704:                 *      has or will have shadows, then we
                   6705:                 *      must not perform an asymmetric copy
                   6706:                 *      of this object, since such a copy
                   6707:                 *      allows the object to be changed, which
                   6708:                 *      will break the previous symmetrical
                   6709:                 *      copies (which rely upon the object
                   6710:                 *      not changing). In a sense, the shadowed
                   6711:                 *      flag says "don't change this object".
                   6712:                 *      We fix this by creating a shadow
                   6713:                 *      object for this object, and sharing
                   6714:                 *      that. This works because we are free
                   6715:                 *      to change the shadow object (and thus
                   6716:                 *      to use an asymmetric copy strategy);
                   6717:                 *      this is also semantically correct,
                   6718:                 *      since this object is temporary, and
                   6719:                 *      therefore a copy of the object is
                   6720:                 *      as good as the object itself. (This
                   6721:                 *      is not true for permanent objects,
                   6722:                 *      since the pager needs to see changes,
                   6723:                 *      which won't happen if the changes
                   6724:                 *      are made to a copy.)
                   6725:                 *
                   6726:                 *      The third case is when the object
                   6727:                 *      to be shared has parts sticking
                   6728:                 *      outside of the entry we're working
                   6729:                 *      with, and thus may in the future
                   6730:                 *      be subject to a symmetrical copy.
                   6731:                 *      (This is a preemptive version of
                   6732:                 *      case 2.)
                   6733:                 */
                   6734:                
                   6735:                assert(!(object->shadowed && old_entry->is_shared));
                   6736:                vm_object_shadow(&old_entry->object.vm_object,
                   6737:                                 &old_entry->offset,
                   6738:                                 (vm_size_t) (old_entry->vme_end -
                   6739:                                              old_entry->vme_start));
                   6740:                
                   6741:                /*
                   6742:                 *      If we're making a shadow for other than
                   6743:                 *      copy on write reasons, then we have
                   6744:                 *      to remove write permission.
                   6745:                 */
                   6746:                
                   6747:                if (!old_entry->needs_copy &&
                   6748:                    (old_entry->protection & VM_PROT_WRITE)) {
                   6749:                        pmap_protect(vm_map_pmap(old_map),
                   6750:                                     old_entry->vme_start,
                   6751:                                     old_entry->vme_end,
                   6752:                                     old_entry->protection & ~VM_PROT_WRITE);
                   6753:                }
                   6754:                old_entry->needs_copy = FALSE;
                   6755:                object = old_entry->object.vm_object;
                   6756:        }
                   6757:        
                   6758:        /*
                   6759:         *      If object was using a symmetric copy strategy,
                   6760:         *      change its copy strategy to the default
                   6761:         *      asymmetric copy strategy, which is copy_delay
                   6762:         *      in the non-norma case and copy_call in the
                   6763:         *      norma case. Bump the reference count for the
                   6764:         *      new entry.
                   6765:         */
                   6766:        
                   6767:        if(old_entry->is_sub_map) {
                   6768:                vm_map_lock(old_entry->object.sub_map);
                   6769:                vm_map_reference(old_entry->object.sub_map);
                   6770:                vm_map_unlock(old_entry->object.sub_map);
                   6771:        } else {
                   6772:                vm_object_lock(object);
                   6773:                object->ref_count++;
                   6774:                vm_object_res_reference(object);
                   6775:                if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC) {
                   6776:                        object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
                   6777:                }
                   6778:                vm_object_unlock(object);
                   6779:        }
                   6780:        
                   6781:        /*
                   6782:         *      Clone the entry, using object ref from above.
                   6783:         *      Mark both entries as shared.
                   6784:         */
                   6785:        
                   6786:        new_entry = vm_map_entry_create(new_map);
                   6787:        vm_map_entry_copy(new_entry, old_entry);
                   6788:        old_entry->is_shared = TRUE;
                   6789:        new_entry->is_shared = TRUE;
                   6790:        
                   6791:        /*
                   6792:         *      Insert the entry into the new map -- we
                   6793:         *      know we're inserting at the end of the new
                   6794:         *      map.
                   6795:         */
                   6796:        
                   6797:        vm_map_entry_link(new_map, vm_map_last_entry(new_map), new_entry);
                   6798:        
                   6799:        /*
                   6800:         *      Update the physical map
                   6801:         */
                   6802:        
                   6803:        if (old_entry->is_sub_map) {
                   6804:                /* Bill Angell pmap support goes here */
                   6805:        } else {
                   6806:                pmap_copy(new_map->pmap, old_map->pmap, new_entry->vme_start,
                   6807:                  old_entry->vme_end - old_entry->vme_start,
                   6808:                  old_entry->vme_start);
                   6809:        }
                   6810: }
                   6811: 
                   6812: boolean_t
                   6813: vm_map_fork_copy(
                   6814:        vm_map_t        old_map,
                   6815:        vm_map_entry_t  *old_entry_p,
                   6816:        vm_map_t        new_map)
                   6817: {
                   6818:        vm_map_entry_t old_entry = *old_entry_p;
                   6819:        vm_size_t entry_size = old_entry->vme_end - old_entry->vme_start;
                   6820:        vm_offset_t start = old_entry->vme_start;
                   6821:        vm_map_copy_t copy;
                   6822:        vm_map_entry_t last = vm_map_last_entry(new_map);
                   6823: 
                   6824:        vm_map_unlock(old_map);
                   6825:        /*
                   6826:         *      Use maxprot version of copyin because we
                   6827:         *      care about whether this memory can ever
                   6828:         *      be accessed, not just whether it's accessible
                   6829:         *      right now.
                   6830:         */
                   6831:        if (vm_map_copyin_maxprot(old_map, start, entry_size, FALSE, &copy)
                   6832:            != KERN_SUCCESS) {
                   6833:                /*
                   6834:                 *      The map might have changed while it
                   6835:                 *      was unlocked, check it again.  Skip
                   6836:                 *      any blank space or permanently
                   6837:                 *      unreadable region.
                   6838:                 */
                   6839:                vm_map_lock(old_map);
                   6840:                if (!vm_map_lookup_entry(old_map, start, &last) ||
                   6841:                    last->max_protection & VM_PROT_READ ==
                   6842:                                         VM_PROT_NONE) {
                   6843:                        last = last->vme_next;
                   6844:                }
                   6845:                *old_entry_p = last;
                   6846: 
                   6847:                /*
                   6848:                 * XXX  For some error returns, want to
                   6849:                 * XXX  skip to the next element.  Note
                   6850:                 *      that INVALID_ADDRESS and
                   6851:                 *      PROTECTION_FAILURE are handled above.
                   6852:                 */
                   6853:                
                   6854:                return FALSE;
                   6855:        }
                   6856:        
                   6857:        /*
                   6858:         *      Insert the copy into the new map
                   6859:         */
                   6860:        
                   6861:        vm_map_copy_insert(new_map, last, copy);
                   6862:        
                   6863:        /*
                   6864:         *      Pick up the traversal at the end of
                   6865:         *      the copied region.
                   6866:         */
                   6867:        
                   6868:        vm_map_lock(old_map);
                   6869:        start += entry_size;
                   6870:        if (! vm_map_lookup_entry(old_map, start, &last)) {
                   6871:                last = last->vme_next;
                   6872:        } else {
                   6873:                vm_map_clip_start(old_map, last, start);
                   6874:        }
                   6875:        *old_entry_p = last;
                   6876: 
                   6877:        return TRUE;
                   6878: }
                   6879: 
                   6880: /*
                   6881:  *     vm_map_fork:
                   6882:  *
                   6883:  *     Create and return a new map based on the old
                   6884:  *     map, according to the inheritance values on the
                   6885:  *     regions in that map.
                   6886:  *
                   6887:  *     The source map must not be locked.
                   6888:  */
                   6889: vm_map_t
                   6890: vm_map_fork(
                   6891:        vm_map_t        old_map)
                   6892: {
                   6893:        pmap_t          new_pmap = pmap_create((vm_size_t) 0);
                   6894:        vm_map_t        new_map;
                   6895:        vm_map_entry_t  old_entry;
                   6896:        vm_size_t       new_size = 0, entry_size;
                   6897:        vm_map_entry_t  new_entry;
                   6898:        boolean_t       src_needs_copy;
                   6899:        boolean_t       new_entry_needs_copy;
                   6900: 
                   6901:        vm_map_reference_swap(old_map);
                   6902:        vm_map_lock(old_map);
                   6903: 
                   6904:        new_map = vm_map_create(new_pmap,
                   6905:                        old_map->min_offset,
                   6906:                        old_map->max_offset,
                   6907:                        old_map->hdr.entries_pageable);
                   6908: 
                   6909:        for (
                   6910:            old_entry = vm_map_first_entry(old_map);
                   6911:            old_entry != vm_map_to_entry(old_map);
                   6912:            ) {
                   6913: 
                   6914:                entry_size = old_entry->vme_end - old_entry->vme_start;
                   6915: 
                   6916:                switch (old_entry->inheritance) {
                   6917:                case VM_INHERIT_NONE:
                   6918:                        break;
                   6919: 
                   6920:                case VM_INHERIT_SHARE:
                   6921:                        vm_map_fork_share(old_map, old_entry, new_map);
                   6922:                        new_size += entry_size;
                   6923:                        break;
                   6924: 
                   6925:                case VM_INHERIT_COPY:
                   6926: 
                   6927:                        /*
                   6928:                         *      Inline the copy_quickly case;
                   6929:                         *      upon failure, fall back on call
                   6930:                         *      to vm_map_fork_copy.
                   6931:                         */
                   6932: 
                   6933:                        if(old_entry->is_sub_map)
                   6934:                                break;
                   6935:                        if (old_entry->wired_count != 0) {
                   6936:                                goto slow_vm_map_fork_copy;
                   6937:                        }
                   6938: 
                   6939:                        new_entry = vm_map_entry_create(new_map);
                   6940:                        vm_map_entry_copy(new_entry, old_entry);
                   6941: 
                   6942:                        if (! vm_object_copy_quickly(
                   6943:                                                &new_entry->object.vm_object,
                   6944:                                                old_entry->offset,
                   6945:                                                (old_entry->vme_end -
                   6946:                                                        old_entry->vme_start),
                   6947:                                                &src_needs_copy,
                   6948:                                                &new_entry_needs_copy)) {
                   6949:                                vm_map_entry_dispose(new_map, new_entry);
                   6950:                                goto slow_vm_map_fork_copy;
                   6951:                        }
                   6952: 
                   6953:                        /*
                   6954:                         *      Handle copy-on-write obligations
                   6955:                         */
                   6956:                        
                   6957:                        if (src_needs_copy && !old_entry->needs_copy) {
                   6958:                                vm_object_pmap_protect(
                   6959:                                        old_entry->object.vm_object,
                   6960:                                        old_entry->offset,
                   6961:                                        (old_entry->vme_end -
                   6962:                                                        old_entry->vme_start),
                   6963:                                        (old_entry->is_shared ? PMAP_NULL :
                   6964:                                                        old_map->pmap),
                   6965:                                        old_entry->vme_start,
                   6966:                                        old_entry->protection & ~VM_PROT_WRITE);
                   6967: 
                   6968:                                old_entry->needs_copy = TRUE;
                   6969:                        }
                   6970:                        new_entry->needs_copy = new_entry_needs_copy;
                   6971:                        
                   6972:                        /*
                   6973:                         *      Insert the entry at the end
                   6974:                         *      of the map.
                   6975:                         */
                   6976:                        
                   6977:                        vm_map_entry_link(new_map, vm_map_last_entry(new_map),
                   6978:                                          new_entry);
                   6979:                        new_size += entry_size;
                   6980:                        break;
                   6981: 
                   6982:                slow_vm_map_fork_copy:
                   6983:                        if (vm_map_fork_copy(old_map, &old_entry, new_map)) {
                   6984:                                new_size += entry_size;
                   6985:                        }
                   6986:                        continue;
                   6987:                }
                   6988:                old_entry = old_entry->vme_next;
                   6989:        }
                   6990: 
                   6991:        new_map->size = new_size;
                   6992:        vm_map_unlock(old_map);
                   6993:        vm_map_deallocate(old_map);
                   6994: 
                   6995:        return(new_map);
                   6996: }
                   6997: 
                   6998: /*
                   6999:  *     vm_map_lookup_locked:
                   7000:  *
                   7001:  *     Finds the VM object, offset, and
                   7002:  *     protection for a given virtual address in the
                   7003:  *     specified map, assuming a page fault of the
                   7004:  *     type specified.
                   7005:  *
                   7006:  *     Returns the (object, offset, protection) for
                   7007:  *     this address, whether it is wired down, and whether
                   7008:  *     this map has the only reference to the data in question.
                   7009:  *     In order to later verify this lookup, a "version"
                   7010:  *     is returned.
                   7011:  *
                   7012:  *     The map MUST be locked by the caller and WILL be
                   7013:  *     locked on exit.  In order to guarantee the
                   7014:  *     existence of the returned object, it is returned
                   7015:  *     locked.
                   7016:  *
                   7017:  *     If a lookup is requested with "write protection"
                   7018:  *     specified, the map may be changed to perform virtual
                   7019:  *     copying operations, although the data referenced will
                   7020:  *     remain the same.
                   7021:  */
                   7022: kern_return_t
                   7023: vm_map_lookup_locked(
                   7024:        vm_map_t                *var_map,       /* IN/OUT */
                   7025:        register vm_offset_t    vaddr,
                   7026:        register vm_prot_t      fault_type,
                   7027:        vm_map_version_t        *out_version,   /* OUT */
                   7028:        vm_object_t             *object,        /* OUT */
                   7029:        vm_offset_t             *offset,        /* OUT */
                   7030:        vm_prot_t               *out_prot,      /* OUT */
                   7031:        boolean_t               *wired,         /* OUT */
                   7032:        int                     *behavior,      /* OUT */
                   7033:        vm_offset_t             *lo_offset,     /* OUT */
                   7034:        vm_offset_t             *hi_offset)     /* OUT */
                   7035: {
                   7036:        vm_map_entry_t                  entry;
                   7037:        register vm_map_t               map = *var_map;
                   7038:        vm_map_t                        old_map = *var_map;
                   7039:        vm_offset_t                     old_vaddr = vaddr;
                   7040:        vm_map_t                        cow_sub_map;
                   7041:        vm_offset_t                     old_start;
                   7042:        vm_offset_t                     old_end;
                   7043:        register vm_prot_t              prot;
                   7044: 
                   7045:        RetryLookup: ;
                   7046: 
                   7047:        /*
                   7048:         *      If the map has an interesting hint, try it before calling
                   7049:         *      full blown lookup routine.
                   7050:         */
                   7051: 
                   7052:        mutex_lock(&map->s_lock);
                   7053:        entry = map->hint;
                   7054:        mutex_unlock(&map->s_lock);
                   7055: 
                   7056:        if ((entry == vm_map_to_entry(map)) ||
                   7057:            (vaddr < entry->vme_start) || (vaddr >= entry->vme_end)) {
                   7058:                vm_map_entry_t  tmp_entry;
                   7059: 
                   7060:                /*
                   7061:                 *      Entry was either not a valid hint, or the vaddr
                   7062:                 *      was not contained in the entry, so do a full lookup.
                   7063:                 */
                   7064:                if (!vm_map_lookup_entry(map, vaddr, &tmp_entry))
                   7065:                        return KERN_INVALID_ADDRESS;
                   7066: 
                   7067:                entry = tmp_entry;
                   7068:        }
                   7069:        if(map == old_map) {
                   7070:                old_start = entry->vme_start;
                   7071:                old_end = entry->vme_end;
                   7072:        }
                   7073: 
                   7074:        /*
                   7075:         *      Handle submaps.  Drop lock on upper map, submap is
                   7076:         *      returned locked.
                   7077:         */
                   7078: 
                   7079: submap_recurse:
                   7080:        if (entry->is_sub_map) {
                   7081:                vm_map_entry_t          our_entry;
                   7082:                vm_offset_t             local_vaddr;
                   7083:                vm_offset_t             end_delta;
                   7084:                vm_offset_t             start_delta; 
                   7085:                vm_map_entry_t          submap_entry;
                   7086:                boolean_t               mapped_needs_copy=FALSE;
                   7087: 
                   7088:                local_vaddr = vaddr;
                   7089:                our_entry = entry;
                   7090: 
                   7091:                vm_map_lock_read(entry->object.sub_map);
                   7092:                vm_map_unlock_read(map);
                   7093:                *var_map = map = entry->object.sub_map;
                   7094: 
                   7095:                /* calculate the offset in the submap for vaddr */
                   7096:                local_vaddr = (local_vaddr - entry->vme_start) + entry->offset;
                   7097: 
                   7098:                if(entry->needs_copy) {
                   7099:                        if(!mapped_needs_copy) {
                   7100:                                cow_sub_map = entry->object.sub_map;
                   7101:                                mapped_needs_copy = TRUE;
                   7102:                        }
                   7103:                }
                   7104: 
                   7105:                if(!vm_map_lookup_entry(map, local_vaddr, &submap_entry)) {
                   7106:                        return KERN_INVALID_ADDRESS;
                   7107:                }
                   7108:                /* find the attenuated shadow of the underlying object */
                   7109:                /* on our target map */
                   7110: 
                   7111:                /* in english the submap object may extend beyond the     */
                   7112:                /* region mapped by the entry or, may only fill a portion */
                   7113:                /* of it.  For our purposes, we only care if the object   */
                   7114:                /* doesn't fill.  In this case the area which will        */
                   7115:                /* ultimately be clipped in the top map will only need    */
                   7116:                /* to be as big as the portion of the underlying entry    */
                   7117:                /* which is mapped */
                   7118:                start_delta = submap_entry->vme_start > entry->offset ?
                   7119:                            submap_entry->vme_start - entry->offset : 0;
                   7120: 
                   7121:                end_delta = 
                   7122:                   (entry->offset + start_delta + (old_end - old_start)) <=
                   7123:                        submap_entry->vme_end ?
                   7124:                                0 : (entry->offset + 
                   7125:                                        start_delta + (old_end - old_start))
                   7126:                                        - submap_entry->vme_end; 
                   7127: 
                   7128:                old_start += start_delta;
                   7129:                old_end -= end_delta;
                   7130: 
                   7131:                vaddr = local_vaddr;
                   7132:                entry = submap_entry;
                   7133:                if(submap_entry->is_sub_map) {
                   7134:                        goto submap_recurse;
                   7135:                }
                   7136:                if((fault_type & VM_PROT_WRITE) && 
                   7137:                        !(submap_entry->protection & VM_PROT_WRITE))  {
                   7138:                        if(mapped_needs_copy) {
                   7139: 
                   7140:                                vm_object_t     copy_object;
                   7141:                                vm_offset_t     object_offset;
                   7142:                                vm_offset_t     local_start;
                   7143:                                vm_offset_t     local_end;
                   7144: 
                   7145:                                object_offset = submap_entry->offset;
                   7146: 
                   7147:                                /* This is the COW case, lets connect */
                   7148:                                /* an entry in our space to the underlying */
                   7149:                                /* object in the submap, bypassing the  */
                   7150:                                /* submap. */
                   7151:                                
                   7152:                                /* set up shadow object */
                   7153:                                copy_object = 
                   7154:                                        vm_object_copy_delayed(
                   7155:                                                submap_entry->object.vm_object,
                   7156:                                                submap_entry->offset, 
                   7157:                                                old_end-old_start);
                   7158: 
                   7159:                                /* This case works opposite of the */
                   7160:                                /* normal submap case.  We go back */
                   7161:                                /* to the top of the map tree and  */
                   7162:                                /* clip out the target portion of  */
                   7163:                                /* the sub_map, substituting the   */
                   7164:                                /* new copy object, we do this for */
                   7165:                                /* all maps in the tree, down to   */
                   7166:                                /* the COW one.                    */
                   7167: 
                   7168:                                vm_map_unlock_read(map);
                   7169:                                vm_map_lock(old_map);
                   7170:                                local_start = old_start;
                   7171:                                local_end = old_end;
                   7172:                                local_vaddr = vaddr = old_vaddr;
                   7173:                                map = old_map;
                   7174:                                while(TRUE) {
                   7175:                                        vm_map_t        new_map;
                   7176: 
                   7177:                                        if(!vm_map_lookup_entry(map, 
                   7178:                                                local_vaddr, &entry)) {
                   7179:                                                vm_object_deallocate(
                   7180:                                                                copy_object);
                   7181:                                                vm_map_unlock(map);
                   7182:                                                vm_map_lock_read(*var_map);
                   7183:                                                return KERN_INVALID_ADDRESS;
                   7184:                                        }
                   7185:                                        
                   7186:                                        /* clip out the portion of space */
                   7187:                                        /* mapped by the sub map which   */
                   7188:                                        /* corresponds to the underlying */
                   7189:                                        /* object */
                   7190:                                        vm_map_clip_start(map, entry, 
                   7191:                                                                local_start);
                   7192:                                        vm_map_clip_end(map, entry, 
                   7193:                                                                local_end);
                   7194:                                        new_map = entry->object.sub_map;
                   7195: 
                   7196:                                        /* update local start and end    */
                   7197:                                        /* in possible underlying submap */
                   7198:                                        local_start =  entry->offset;
                   7199:                                        local_end = (entry->vme_end -
                   7200:                                                        entry->vme_start) +
                   7201:                                                        entry->offset;
                   7202:                                        local_vaddr -= entry->vme_start;
                   7203:                                        local_vaddr += entry->offset;
                   7204: 
                   7205:                                        /* substitute copy object for */
                   7206:                                        /* shared map entry           */
                   7207:                                        vm_map_deallocate(
                   7208:                                                        entry->object.sub_map);
                   7209:                                        entry->is_sub_map = FALSE;
                   7210:                                        vm_object_reference(copy_object);
                   7211:                                        entry->object.vm_object = copy_object;
                   7212:                                        entry->protection |= VM_PROT_WRITE;
                   7213:                                        entry->max_protection |= VM_PROT_WRITE;
                   7214:                                        entry->needs_copy = FALSE;
                   7215:                                        if(entry->inheritance 
                   7216:                                                        == VM_INHERIT_SHARE) 
                   7217:                                        entry->inheritance = VM_INHERIT_COPY;
                   7218:                                        entry->offset = object_offset;
                   7219:                                        if (map != old_map)
                   7220:                                                entry->is_shared = TRUE;
                   7221: 
                   7222:                                        vm_map_unlock(map);
                   7223:                                        if(new_map == cow_sub_map)
                   7224:                                                break;
                   7225:                                        map = new_map;
                   7226:                                        vm_map_lock(map);
                   7227:                                }
                   7228:                                map = old_map;
                   7229:                                vm_map_lock_read(map);
                   7230:                                vaddr = old_vaddr;
                   7231:                                /* get rid of extra reference */
                   7232:                                vm_object_deallocate(copy_object);
                   7233:                                if(!vm_map_lookup_entry(map, vaddr, &entry)) {
                   7234:                                        return KERN_INVALID_ADDRESS;
                   7235:                                }
                   7236:                        } else {
                   7237:                                /* write fault! */
                   7238:                                return KERN_INVALID_ADDRESS;
                   7239:                        }
                   7240:                }
                   7241:                vm_map_lock_read(old_map);
                   7242:                vm_map_unlock_read(map);
                   7243:                *var_map = map = old_map;
                   7244:        }
                   7245:                
                   7246:        /*
                   7247:         *      Check whether this task is allowed to have
                   7248:         *      this page.
                   7249:         */
                   7250: 
                   7251:        prot = entry->protection;
                   7252:        if ((fault_type & (prot)) != fault_type)
                   7253:                return KERN_PROTECTION_FAILURE;
                   7254: 
                   7255:        /*
                   7256:         *      If this page is not pageable, we have to get
                   7257:         *      it for all possible accesses.
                   7258:         */
                   7259: 
                   7260:        if (*wired = (entry->wired_count != 0))
                   7261:                prot = fault_type = entry->protection;
                   7262: 
                   7263:        /*
                   7264:         *      If the entry was copy-on-write, we either ...
                   7265:         */
                   7266: 
                   7267:        if (entry->needs_copy) {
                   7268:                /*
                   7269:                 *      If we want to write the page, we may as well
                   7270:                 *      handle that now since we've got the map locked.
                   7271:                 *
                   7272:                 *      If we don't need to write the page, we just
                   7273:                 *      demote the permissions allowed.
                   7274:                 */
                   7275: 
                   7276:                if (fault_type & VM_PROT_WRITE || *wired) {
                   7277:                        /*
                   7278:                         *      Make a new object, and place it in the
                   7279:                         *      object chain.  Note that no new references
                   7280:                         *      have appeared -- one just moved from the
                   7281:                         *      map to the new object.
                   7282:                         */
                   7283: 
                   7284:                        if (vm_map_lock_read_to_write(map)) {
                   7285:                                vm_map_lock_read(map);
                   7286:                                goto RetryLookup;
                   7287:                        }
                   7288:                        vm_object_shadow(&entry->object.vm_object,
                   7289:                                         &entry->offset,
                   7290:                                         (vm_size_t) (entry->vme_end -
                   7291:                                                      entry->vme_start));
                   7292: 
                   7293:                        entry->needs_copy = FALSE;
                   7294:                        vm_map_lock_write_to_read(map);
                   7295:                }
                   7296:                else {
                   7297:                        /*
                   7298:                         *      We're attempting to read a copy-on-write
                   7299:                         *      page -- don't allow writes.
                   7300:                         */
                   7301: 
                   7302:                        prot &= (~VM_PROT_WRITE);
                   7303:                }
                   7304:        }
                   7305: 
                   7306:        /*
                   7307:         *      Create an object if necessary.
                   7308:         */
                   7309:        if (entry->object.vm_object == VM_OBJECT_NULL) {
                   7310: 
                   7311:                if (vm_map_lock_read_to_write(map)) {
                   7312:                        vm_map_lock_read(map);
                   7313:                        goto RetryLookup;
                   7314:                }
                   7315: 
                   7316:                entry->object.vm_object = vm_object_allocate(
                   7317:                        (vm_size_t)(entry->vme_end - entry->vme_start));
                   7318:                entry->offset = 0;
                   7319:                vm_map_lock_write_to_read(map);
                   7320:        }
                   7321: 
                   7322:        /*
                   7323:         *      Return the object/offset from this entry.  If the entry
                   7324:         *      was copy-on-write or empty, it has been fixed up.  Also
                   7325:         *      return the protection.
                   7326:         */
                   7327: 
                   7328:         *offset = (vaddr - entry->vme_start) + entry->offset;
                   7329:         *object = entry->object.vm_object;
                   7330:        *out_prot = prot;
                   7331:        *behavior = entry->behavior;
                   7332:        *lo_offset = entry->offset;
                   7333:        *hi_offset = (entry->vme_end - entry->vme_start) + entry->offset;
                   7334: 
                   7335:        /*
                   7336:         *      Lock the object to prevent it from disappearing
                   7337:         */
                   7338: 
                   7339:        vm_object_lock(*object);
                   7340: 
                   7341:        /*
                   7342:         *      Save the version number
                   7343:         */
                   7344: 
                   7345:        out_version->main_timestamp = map->timestamp;
                   7346: 
                   7347:        return KERN_SUCCESS;
                   7348: }
                   7349: 
                   7350: 
                   7351: /*
                   7352:  *     vm_map_verify:
                   7353:  *
                   7354:  *     Verifies that the map in question has not changed
                   7355:  *     since the given version.  If successful, the map
                   7356:  *     will not change until vm_map_verify_done() is called.
                   7357:  */
                   7358: boolean_t
                   7359: vm_map_verify(
                   7360:        register vm_map_t               map,
                   7361:        register vm_map_version_t       *version)       /* REF */
                   7362: {
                   7363:        boolean_t       result;
                   7364: 
                   7365:        vm_map_lock_read(map);
                   7366:        result = (map->timestamp == version->main_timestamp);
                   7367: 
                   7368:        if (!result)
                   7369:                vm_map_unlock_read(map);
                   7370: 
                   7371:        return(result);
                   7372: }
                   7373: 
                   7374: /*
                   7375:  *     vm_map_verify_done:
                   7376:  *
                   7377:  *     Releases locks acquired by a vm_map_verify.
                   7378:  *
                   7379:  *     This is now a macro in vm/vm_map.h.  It does a
                   7380:  *     vm_map_unlock_read on the map.
                   7381:  */
                   7382: 
                   7383: 
                   7384: /*
                   7385:  *     vm_region:
                   7386:  *
                   7387:  *     User call to obtain information about a region in
                   7388:  *     a task's address map. Currently, only one flavor is
                   7389:  *     supported.
                   7390:  *
                   7391:  *     XXX The reserved and behavior fields cannot be filled
                   7392:  *         in until the vm merge from the IK is completed, and
                   7393:  *         vm_reserve is implemented.
                   7394:  *
                   7395:  *     XXX Dependency: syscall_vm_region() also supports only one flavor.
                   7396:  */
                   7397: 
                   7398: kern_return_t
                   7399: vm_region(
                   7400:        vm_map_t                 map,
                   7401:        vm_offset_t             *address,               /* IN/OUT */
                   7402:        vm_size_t               *size,                  /* OUT */
                   7403:        vm_region_flavor_t       flavor,                /* IN */
                   7404:        vm_region_info_t         info,                  /* OUT */
                   7405:        mach_msg_type_number_t  *count,                 /* IN/OUT */
                   7406:        ipc_port_t              *object_name)           /* OUT */
                   7407: {
                   7408:        vm_map_entry_t          tmp_entry;
                   7409:        register
                   7410:        vm_map_entry_t          entry;
                   7411:        register
                   7412:        vm_offset_t             start;
                   7413:        vm_region_basic_info_t  basic;
                   7414:        vm_region_extended_info_t       extended;
                   7415:        vm_region_top_info_t    top;
                   7416: 
                   7417:        if (map == VM_MAP_NULL) 
                   7418:                return(KERN_INVALID_ARGUMENT);
                   7419: 
                   7420:        switch (flavor) {
                   7421:        
                   7422:        case VM_REGION_BASIC_INFO:
                   7423:        {
                   7424:            if (*count < VM_REGION_BASIC_INFO_COUNT)
                   7425:                return(KERN_INVALID_ARGUMENT);
                   7426: 
                   7427:            basic = (vm_region_basic_info_t) info;
                   7428:            *count = VM_REGION_BASIC_INFO_COUNT;
                   7429: 
                   7430:            vm_map_lock_read(map);
                   7431: 
                   7432:            start = *address;
                   7433:            if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   7434:                if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
                   7435:                        vm_map_unlock_read(map);
                   7436:                        return(KERN_INVALID_ADDRESS);
                   7437:                }
                   7438:            } else {
                   7439:                entry = tmp_entry;
                   7440:            }
                   7441: 
                   7442:            start = entry->vme_start;
                   7443: 
                   7444:            basic->offset = entry->offset;
                   7445:            basic->protection = entry->protection;
                   7446:            basic->inheritance = entry->inheritance;
                   7447:            basic->max_protection = entry->max_protection;
                   7448:            basic->behavior = entry->behavior;
                   7449:            basic->user_wired_count = entry->user_wired_count;
                   7450:            basic->reserved = FALSE;            /* XXX when vm_reserve fini */
                   7451:            *address = start;
                   7452:            *size = (entry->vme_end - start);
                   7453: 
                   7454:            if (object_name) *object_name = IP_NULL;
                   7455:            if (entry->is_sub_map) {
                   7456:                basic->shared = FALSE;
                   7457:            } else {
                   7458:                basic->shared = entry->is_shared;
                   7459:            }
                   7460: 
                   7461:            vm_map_unlock_read(map);
                   7462:            return(KERN_SUCCESS);
                   7463:        }
                   7464:        case VM_REGION_EXTENDED_INFO:
                   7465:        {   void vm_region_walk();
                   7466: 
                   7467:            if (*count < VM_REGION_EXTENDED_INFO_COUNT)
                   7468:                return(KERN_INVALID_ARGUMENT);
                   7469: 
                   7470:            extended = (vm_region_extended_info_t) info;
                   7471:            *count = VM_REGION_EXTENDED_INFO_COUNT;
                   7472: 
                   7473:            vm_map_lock_read(map);
                   7474: 
                   7475:            start = *address;
                   7476:            if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   7477:                if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
                   7478:                        vm_map_unlock_read(map);
                   7479:                        return(KERN_INVALID_ADDRESS);
                   7480:                }
                   7481:            } else {
                   7482:                entry = tmp_entry;
                   7483:            }
                   7484:            start = entry->vme_start;
                   7485: 
                   7486:            extended->protection = entry->protection;
                   7487:            extended->user_tag = entry->alias;
                   7488:            extended->pages_resident = 0;
                   7489:            extended->pages_swapped_out = 0;
                   7490:            extended->pages_shared_now_private = 0;
                   7491:            extended->pages_referenced = 0;
                   7492:            extended->external_pager = 0;
                   7493:            extended->shadow_depth = 0;
                   7494: 
                   7495:            vm_region_walk(entry, extended, entry->offset, entry->vme_end - start, map, start);
                   7496: 
                   7497:            if (object_name)
                   7498:                *object_name = IP_NULL;
                   7499:            *address = start;
                   7500:            *size = (entry->vme_end - start);
                   7501: 
                   7502:            vm_map_unlock_read(map);
                   7503:            return(KERN_SUCCESS);
                   7504:        }
                   7505:        case VM_REGION_TOP_INFO:
                   7506:        {   void vm_region_top_walk();
                   7507: 
                   7508:            if (*count < VM_REGION_TOP_INFO_COUNT)
                   7509:                return(KERN_INVALID_ARGUMENT);
                   7510: 
                   7511:            top = (vm_region_top_info_t) info;
                   7512:            *count = VM_REGION_TOP_INFO_COUNT;
                   7513: 
                   7514:            vm_map_lock_read(map);
                   7515: 
                   7516:            start = *address;
                   7517:            if (!vm_map_lookup_entry(map, start, &tmp_entry)) {
                   7518:                if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) {
                   7519:                        vm_map_unlock_read(map);
                   7520:                        return(KERN_INVALID_ADDRESS);
                   7521:                }
                   7522:            } else {
                   7523:                entry = tmp_entry;
                   7524: 
                   7525:            }
                   7526:            start = entry->vme_start;
                   7527: 
                   7528:            top->private_pages_resident = 0;
                   7529:            top->shared_pages_resident = 0;
                   7530: 
                   7531:            vm_region_top_walk(entry, top);
                   7532: 
                   7533:            if (object_name)
                   7534:                *object_name = IP_NULL;
                   7535:            *address = start;
                   7536:            *size = (entry->vme_end - start);
                   7537: 
                   7538:            vm_map_unlock_read(map);
                   7539:            return(KERN_SUCCESS);
                   7540:        }
                   7541:        default:
                   7542:            return(KERN_INVALID_ARGUMENT);
                   7543:        }
                   7544: }
                   7545: 
                   7546: 
                   7547: void
                   7548: vm_region_top_walk(
                   7549:         vm_map_entry_t            entry,
                   7550:        vm_region_top_info_t       top)
                   7551: {
                   7552:         register struct vm_object *obj, *tmp_obj;
                   7553: 
                   7554:        if (entry->object.vm_object == 0) {
                   7555:            top->share_mode = SM_EMPTY;
                   7556:            top->ref_count = 0;
                   7557:            top->obj_id = 0;
                   7558:            return;
                   7559:        }
                   7560:         if (entry->is_sub_map)
                   7561:            vm_region_top_walk((vm_map_entry_t)entry->object.sub_map, top);
                   7562:        else {
                   7563:            obj = entry->object.vm_object;
                   7564: 
                   7565:            vm_object_lock(obj);
                   7566: 
                   7567:            if (obj->shadow) {
                   7568:                if (obj->ref_count == 1)
                   7569:                    top->private_pages_resident = obj->resident_page_count;
                   7570:                else
                   7571:                    top->shared_pages_resident = obj->resident_page_count;
                   7572:                top->ref_count  = obj->ref_count;
                   7573:                top->share_mode = SM_COW;
                   7574:            
                   7575:                while (tmp_obj = obj->shadow) {
                   7576:                    vm_object_lock(tmp_obj);
                   7577:                    vm_object_unlock(obj);
                   7578:                    obj = tmp_obj;
                   7579: 
                   7580:                    top->shared_pages_resident += obj->resident_page_count;
                   7581:                    top->ref_count += obj->resident_page_count - 1;
                   7582:                }
                   7583:            } else {
                   7584:                if (entry->needs_copy) {
                   7585:                    top->share_mode = SM_COW;
                   7586:                    top->shared_pages_resident = obj->resident_page_count;
                   7587:                } else {
                   7588:                    if (obj->ref_count == 1) {
                   7589:                        top->share_mode = SM_PRIVATE;
                   7590:                        top->private_pages_resident = obj->resident_page_count;
                   7591:                    } else {
                   7592:                        top->share_mode = SM_SHARED;
                   7593:                        top->shared_pages_resident = obj->resident_page_count;
                   7594:                    }
                   7595:                }
                   7596:                top->ref_count = obj->ref_count;
                   7597:            }
                   7598:            top->obj_id = (int)obj;
                   7599: 
                   7600:            vm_object_unlock(obj);
                   7601:        }
                   7602: }
                   7603: 
                   7604: void
                   7605: vm_region_walk(
                   7606:         vm_map_entry_t            entry,
                   7607:        vm_region_extended_info_t  extended,
                   7608:        vm_offset_t                offset,
                   7609:        vm_offset_t                range,
                   7610:        vm_map_t                   map,
                   7611:        vm_offset_t                va)
                   7612: {
                   7613:         register struct vm_object *obj, *tmp_obj;
                   7614:        register vm_offset_t       last_offset;
                   7615:        register int               i;
                   7616:        void vm_region_look_for_page();
                   7617: 
                   7618:        if (entry->object.vm_object == 0) {
                   7619:            extended->share_mode = SM_EMPTY;
                   7620:            extended->ref_count = 0;
                   7621:            return;
                   7622:        }
                   7623:         if (entry->is_sub_map)
                   7624:            vm_region_walk((vm_map_entry_t)entry->object.sub_map, extended, offset + entry->offset,
                   7625:                           range, map, va);
                   7626:        else {
                   7627:            obj = entry->object.vm_object;
                   7628: 
                   7629:            vm_object_lock(obj);
                   7630: 
                   7631:            for (last_offset = offset + range; offset < last_offset; offset += PAGE_SIZE, va += PAGE_SIZE)
                   7632:                vm_region_look_for_page(obj, extended, offset, obj->ref_count, 0, map, va);
                   7633: 
                   7634:            if (extended->shadow_depth || entry->needs_copy)
                   7635:                extended->share_mode = SM_COW;
                   7636:            else {
                   7637:                if (obj->ref_count == 1)
                   7638:                    extended->share_mode = SM_PRIVATE;
                   7639:                else {
                   7640:                    if (obj->true_share)
                   7641:                        extended->share_mode = SM_TRUESHARED;
                   7642:                    else
                   7643:                        extended->share_mode = SM_SHARED;
                   7644:                }
                   7645:            }
                   7646:            extended->ref_count = obj->ref_count - extended->shadow_depth;
                   7647:            
                   7648:            for (i = 0; i < extended->shadow_depth; i++) {
                   7649:                if ((tmp_obj = obj->shadow) == 0)
                   7650:                    break;
                   7651:                vm_object_lock(tmp_obj);
                   7652:                vm_object_unlock(obj);
                   7653:                extended->ref_count += tmp_obj->ref_count;
                   7654:                obj = tmp_obj;
                   7655:            }
                   7656:            vm_object_unlock(obj);
                   7657: 
                   7658:            if (extended->share_mode == SM_SHARED) {
                   7659:                register vm_map_entry_t      cur;
                   7660:                register vm_map_entry_t      last;
                   7661:                int      my_refs;
                   7662: 
                   7663:                obj = entry->object.vm_object;
                   7664:                last = vm_map_to_entry(map);
                   7665:                my_refs = 0;
                   7666: 
                   7667:                for (cur = vm_map_first_entry(map); cur != last; cur = cur->vme_next)
                   7668:                    my_refs += vm_region_count_obj_refs(cur, obj);
                   7669: 
                   7670:                if (my_refs == obj->ref_count)
                   7671:                    extended->share_mode = SM_PRIVATE_ALIASED;
                   7672:                else if (my_refs > 1)
                   7673:                    extended->share_mode = SM_SHARED_ALIASED;
                   7674:            }
                   7675:        }
                   7676: }
                   7677: 
                   7678: 
                   7679: 
                   7680: void
                   7681: vm_region_look_for_page(
                   7682:         vm_object_t               object,
                   7683:        vm_region_extended_info_t  extended,
                   7684:        vm_offset_t                offset,
                   7685:        int                        max_refcnt,
                   7686:         int                        depth,
                   7687:        vm_map_t                   map,
                   7688:        vm_offset_t                va)
                   7689: {
                   7690:         register vm_page_t        p;
                   7691:         register vm_object_t      shadow;
                   7692:         
                   7693:        shadow = object->shadow;
                   7694: 
                   7695:         queue_iterate(&object->memq, p, vm_page_t, listq) {
                   7696:            if (p->offset == offset) {
                   7697:                if (shadow && (max_refcnt == 1))
                   7698:                    extended->pages_shared_now_private++;
                   7699: 
                   7700:                if (pmap_extract(vm_map_pmap(map), va))
                   7701:                    extended->pages_referenced++;
                   7702:                extended->pages_resident++;
                   7703: 
                   7704:                return;
                   7705:            }
                   7706:        }
                   7707:        if (object->existence_map) {
                   7708:            if (vm_external_state_get(object->existence_map, offset) == VM_EXTERNAL_STATE_EXISTS) {
                   7709:                if (shadow && (max_refcnt == 1))
                   7710:                    extended->pages_shared_now_private++;
                   7711:                extended->pages_swapped_out++;
                   7712: 
                   7713:                return;
                   7714:            }
                   7715:        }
                   7716:        if (shadow) {
                   7717:            vm_object_lock(shadow);
                   7718: 
                   7719:            if (++depth > extended->shadow_depth)
                   7720:                extended->shadow_depth = depth;
                   7721: 
                   7722:            if (shadow->ref_count > max_refcnt)
                   7723:                max_refcnt = shadow->ref_count;
                   7724:        
                   7725:            vm_region_look_for_page(shadow, extended, offset + object->shadow_offset,
                   7726:                                    max_refcnt, depth, map, va);
                   7727:            vm_object_unlock(shadow);
                   7728: 
                   7729:            return;
                   7730:        }
                   7731:        if ( !(object->pager_trusted) && !(object->internal))
                   7732:            extended->external_pager = 1;
                   7733: }
                   7734: 
                   7735: 
                   7736: vm_region_count_obj_refs(
                   7737:         vm_map_entry_t    entry,
                   7738:        vm_object_t       object)
                   7739: {
                   7740:         register int ref_count;
                   7741:        register vm_object_t chk_obj;
                   7742:        register vm_object_t tmp_obj;
                   7743: 
                   7744:        if (entry->object.vm_object == 0)
                   7745:            return(0);
                   7746: 
                   7747:         if (entry->is_sub_map)
                   7748:            ref_count = vm_region_count_obj_refs((vm_map_entry_t)entry->object.sub_map, object);
                   7749:        else {
                   7750:            ref_count = 0;
                   7751: 
                   7752:            chk_obj = entry->object.vm_object;
                   7753:            vm_object_lock(chk_obj);
                   7754: 
                   7755:            while (chk_obj) {
                   7756:                if (chk_obj == object)
                   7757:                    ref_count++;
                   7758:                if (tmp_obj = chk_obj->shadow)
                   7759:                    vm_object_lock(tmp_obj);
                   7760:                vm_object_unlock(chk_obj);
                   7761:                
                   7762:                chk_obj = tmp_obj;
                   7763:            }
                   7764:        }
                   7765:        return(ref_count);
                   7766: }
                   7767: 
                   7768: 
                   7769: /*
                   7770:  *     Routine:        vm_map_simplify
                   7771:  *
                   7772:  *     Description:
                   7773:  *             Attempt to simplify the map representation in
                   7774:  *             the vicinity of the given starting address.
                   7775:  *     Note:
                   7776:  *             This routine is intended primarily to keep the
                   7777:  *             kernel maps more compact -- they generally don't
                   7778:  *             benefit from the "expand a map entry" technology
                   7779:  *             at allocation time because the adjacent entry
                   7780:  *             is often wired down.
                   7781:  */
                   7782: void
                   7783: vm_map_simplify(
                   7784:        vm_map_t        map,
                   7785:        vm_offset_t     start)
                   7786: {
                   7787:        vm_map_entry_t  this_entry;
                   7788:        vm_map_entry_t  prev_entry;
                   7789:        vm_map_entry_t  next_entry;
                   7790: 
                   7791:        vm_map_lock(map);
                   7792:        if (
                   7793:                (vm_map_lookup_entry(map, start, &this_entry)) &&
                   7794:                ((prev_entry = this_entry->vme_prev) != vm_map_to_entry(map)) &&
                   7795: 
                   7796:                (prev_entry->vme_end == this_entry->vme_start) &&
                   7797: 
                   7798:                (prev_entry->is_shared == FALSE) &&
                   7799:                (prev_entry->is_sub_map == FALSE) &&
                   7800: 
                   7801:                (this_entry->is_shared == FALSE) &&
                   7802:                (this_entry->is_sub_map == FALSE) &&
                   7803: 
                   7804:                (prev_entry->inheritance == this_entry->inheritance) &&
                   7805:                (prev_entry->protection == this_entry->protection) &&
                   7806:                (prev_entry->max_protection == this_entry->max_protection) &&
                   7807:                (prev_entry->behavior == this_entry->behavior) &&
                   7808:                (prev_entry->wired_count == this_entry->wired_count) &&
                   7809:                (prev_entry->user_wired_count == this_entry->user_wired_count)&&
                   7810:                (prev_entry->in_transition == FALSE) &&
                   7811:                (this_entry->in_transition == FALSE) &&
                   7812: 
                   7813:                (prev_entry->needs_copy == this_entry->needs_copy) &&
                   7814: 
                   7815:                (prev_entry->object.vm_object == this_entry->object.vm_object)&&
                   7816:                ((prev_entry->offset +
                   7817:                 (prev_entry->vme_end - prev_entry->vme_start))
                   7818:                     == this_entry->offset)
                   7819:        ) {
                   7820:                SAVE_HINT(map, prev_entry);
                   7821:                vm_map_entry_unlink(map, this_entry);
                   7822:                prev_entry->vme_end = this_entry->vme_end;
                   7823:                UPDATE_FIRST_FREE(map, map->first_free);
                   7824:                vm_object_deallocate(this_entry->object.vm_object);
                   7825:                vm_map_entry_dispose(map, this_entry);
                   7826:                counter(c_vm_map_simplified_lower++);
                   7827:        }
                   7828:        if (
                   7829:                (vm_map_lookup_entry(map, start, &this_entry)) &&
                   7830:                ((next_entry = this_entry->vme_next) != vm_map_to_entry(map)) &&
                   7831: 
                   7832:                (next_entry->vme_start == this_entry->vme_end) &&
                   7833: 
                   7834:                (next_entry->is_shared == FALSE) &&
                   7835:                (next_entry->is_sub_map == FALSE) &&
                   7836: 
                   7837:                (next_entry->is_shared == FALSE) &&
                   7838:                (next_entry->is_sub_map == FALSE) &&
                   7839: 
                   7840:                (next_entry->inheritance == this_entry->inheritance) &&
                   7841:                (next_entry->protection == this_entry->protection) &&
                   7842:                (next_entry->max_protection == this_entry->max_protection) &&
                   7843:                (next_entry->behavior == this_entry->behavior) &&
                   7844:                (next_entry->wired_count == this_entry->wired_count) &&
                   7845:                (next_entry->user_wired_count == this_entry->user_wired_count)&&
                   7846:                (this_entry->in_transition == FALSE) &&
                   7847:                (next_entry->in_transition == FALSE) &&
                   7848: 
                   7849:                (next_entry->needs_copy == this_entry->needs_copy) &&
                   7850: 
                   7851:                (next_entry->object.vm_object == this_entry->object.vm_object)&&
                   7852:                ((this_entry->offset +
                   7853:                 (this_entry->vme_end - this_entry->vme_start))
                   7854:                     == next_entry->offset)
                   7855:        ) {
                   7856:                vm_map_entry_unlink(map, next_entry);
                   7857:                this_entry->vme_end = next_entry->vme_end;
                   7858:                UPDATE_FIRST_FREE(map, map->first_free);
                   7859:                vm_object_deallocate(next_entry->object.vm_object);
                   7860:                vm_map_entry_dispose(map, next_entry);
                   7861:                counter(c_vm_map_simplified_upper++);
                   7862:        }
                   7863:        counter(c_vm_map_simplify_called++);
                   7864:        vm_map_unlock(map);
                   7865: }
                   7866: 
                   7867: 
                   7868: /*
                   7869:  *     Routine:        vm_map_machine_attribute
                   7870:  *     Purpose:
                   7871:  *             Provide machine-specific attributes to mappings,
                   7872:  *             such as cachability etc. for machines that provide
                   7873:  *             them.  NUMA architectures and machines with big/strange
                   7874:  *             caches will use this.
                   7875:  *     Note:
                   7876:  *             Responsibilities for locking and checking are handled here,
                   7877:  *             everything else in the pmap module. If any non-volatile
                   7878:  *             information must be kept, the pmap module should handle
                   7879:  *             it itself. [This assumes that attributes do not
                   7880:  *             need to be inherited, which seems ok to me]
                   7881:  */
                   7882: kern_return_t
                   7883: vm_map_machine_attribute(
                   7884:        vm_map_t        map,
                   7885:        vm_offset_t     address,
                   7886:        vm_size_t       size,
                   7887:        vm_machine_attribute_t  attribute,
                   7888:        vm_machine_attribute_val_t* value)              /* IN/OUT */
                   7889: {
                   7890:        kern_return_t   ret;
                   7891: 
                   7892:        if (address < vm_map_min(map) ||
                   7893:            (address + size) > vm_map_max(map))
                   7894:                return KERN_INVALID_ADDRESS;
                   7895: 
                   7896:        vm_map_lock(map);
                   7897: 
                   7898:        ret = pmap_attribute(map->pmap, address, size, attribute, value);
                   7899: 
                   7900:        vm_map_unlock(map);
                   7901: 
                   7902:        return ret;
                   7903: }
                   7904: 
                   7905: /*
                   7906:  *     vm_map_behavior_set:
                   7907:  *
                   7908:  *     Sets the paging reference behavior of the specified address
                   7909:  *     range in the target map.  Paging reference behavior affects
                   7910:  *     how pagein operations resulting from faults on the map will be 
                   7911:  *     clustered.
                   7912:  */
                   7913: kern_return_t 
                   7914: vm_map_behavior_set(
                   7915:        vm_map_t        map,
                   7916:        vm_offset_t     start,
                   7917:        vm_offset_t     end,
                   7918:        vm_behavior_t   new_behavior)
                   7919: {
                   7920:        register vm_map_entry_t entry;
                   7921:        vm_map_entry_t  temp_entry;
                   7922: 
                   7923:        XPR(XPR_VM_MAP,
                   7924:                "vm_map_behavior_set, 0x%X start 0x%X end 0x%X behavior %d",
                   7925:                (integer_t)map, start, end, new_behavior, 0);
                   7926: 
                   7927:        switch (new_behavior) {
                   7928:        case VM_BEHAVIOR_DEFAULT:
                   7929:        case VM_BEHAVIOR_RANDOM:
                   7930:        case VM_BEHAVIOR_SEQUENTIAL:
                   7931:        case VM_BEHAVIOR_RSEQNTL:
                   7932:                break;
                   7933:        default:
                   7934:                return(KERN_INVALID_ARGUMENT);
                   7935:        }
                   7936: 
                   7937:        vm_map_lock(map);
                   7938: 
                   7939:        /*
                   7940:         *      The entire address range must be valid for the map.
                   7941:         *      Note that vm_map_range_check() does a 
                   7942:         *      vm_map_lookup_entry() internally and returns the
                   7943:         *      entry containing the start of the address range if
                   7944:         *      the entire range is valid.
                   7945:         */
                   7946:        if (vm_map_range_check(map, start, end, &temp_entry)) {
                   7947:                entry = temp_entry;
                   7948:                vm_map_clip_start(map, entry, start);
                   7949:        }
                   7950:        else {
                   7951:                vm_map_unlock(map);
                   7952:                return(KERN_INVALID_ADDRESS);
                   7953:        }
                   7954: 
                   7955:        while ((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
                   7956:                vm_map_clip_end(map, entry, end);
                   7957: 
                   7958:                entry->behavior = new_behavior;
                   7959: 
                   7960:                entry = entry->vme_next;
                   7961:        }
                   7962: 
                   7963:        vm_map_unlock(map);
                   7964:        return(KERN_SUCCESS);
                   7965: }
                   7966: 
                   7967: #if    DIPC
                   7968: 
                   7969: /*
                   7970:  * This should one day be eliminated;
                   7971:  * we should always construct the right flavor of copy object
                   7972:  * the first time. Troublesome areas include vm_read, where vm_map_copyin
                   7973:  * is called without knowing whom the copy object is for.
                   7974:  * There are also situations where we do want a lazy data structure
                   7975:  * even if we are sending to a remote port...
                   7976:  */
                   7977: 
                   7978: extern kern_return_t vm_map_object_to_page_list(
                   7979:                                                vm_map_copy_t   *caller_copy);
                   7980: 
                   7981: /*
                   7982:  *     Convert a copy to a page list.  The copy argument is in/out
                   7983:  *     because we probably have to allocate a new vm_map_copy structure.
                   7984:  *     We take responsibility for discarding the old structure and
                   7985:  *     use a continuation to do so.  Postponing this discard ensures
                   7986:  *     that the objects containing the pages we've marked busy will stick
                   7987:  *     around.  
                   7988:  *
                   7989:  *     N.B.  For the entry list case, be warned that this routine steals
                   7990:  *     the pages from the entry list's objects!
                   7991:  */
                   7992: kern_return_t
                   7993: vm_map_convert_to_page_list(
                   7994:        vm_map_copy_t   *caller_copy)
                   7995: {
                   7996:        vm_map_entry_t  entry;
                   7997:        vm_offset_t     va;
                   7998:        vm_offset_t     offset;
                   7999:        vm_object_t     object;
                   8000:        vm_map_copy_t   copy, new_copy;
                   8001:        vm_size_t       vm_copy_size;
                   8002:        vm_prot_t       result_prot;
                   8003:        vm_page_t       m, top_page;
                   8004:        kern_return_t   result;
                   8005:        kern_return_t   kr;
                   8006: 
                   8007:        copy = *caller_copy;
                   8008: 
                   8009:        /*
                   8010: 
                   8011:         * We may not have to do anything,
                   8012:         * or may not be able to do anything.
                   8013:         */
                   8014:        if (copy == VM_MAP_COPY_NULL || copy->type == VM_MAP_COPY_PAGE_LIST) {
                   8015:                return KERN_SUCCESS;
                   8016:        }
                   8017:        if (copy->type == VM_MAP_COPY_OBJECT) {
                   8018:                return vm_map_object_to_page_list(caller_copy);
                   8019:        }
                   8020:        assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
                   8021: 
                   8022:        /*
                   8023:         *      Check size.  If this is really big, copy it out
                   8024:         *      to the kernel map, and copy in using src_destroy
                   8025:         */
                   8026:        vm_copy_size = round_page(copy->offset + copy->size) -
                   8027:                        trunc_page(copy->offset);
                   8028: 
                   8029:        if (vm_copy_size > (VM_MAP_COPY_PAGE_LIST_MAX * PAGE_SIZE)) {
                   8030:                vm_size_t       copy_size;
                   8031: 
                   8032:                offset = copy->offset;
                   8033:                copy_size = copy->size;
                   8034:                result = vm_map_copyout(kernel_map, &va, copy);
                   8035:                assert(result == KERN_SUCCESS);
                   8036:                va += offset - trunc_page(offset);
                   8037:                result = vm_map_copyin_page_list(kernel_map, va, copy_size,
                   8038:                                (VM_MAP_COPYIN_OPT_SRC_DESTROY|
                   8039:                                 VM_MAP_COPYIN_OPT_STEAL_PAGES|
                   8040:                                 VM_PROT_READ),
                   8041:                                caller_copy, FALSE);
                   8042:                return(result);
                   8043:        }
                   8044: 
                   8045:        /*
                   8046:         *      Allocate the new copy.  Set its continuation to
                   8047:         *      discard the old one.
                   8048:         */
                   8049:        new_copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
                   8050:        new_copy->type = VM_MAP_COPY_PAGE_LIST;
                   8051:        new_copy->cpy_npages = 0;
                   8052:        new_copy->cpy_page_loose = FALSE;
                   8053:        new_copy->offset = copy->offset;
                   8054:        new_copy->size = copy->size;
                   8055:        new_copy->cpy_cont = vm_map_copy_discard_cont;
                   8056:        new_copy->cpy_cont_args = (vm_map_copyin_args_t) copy;
                   8057: 
                   8058:        /*
                   8059:         * Iterate over entries.
                   8060:         */
                   8061:        for (entry = vm_map_copy_first_entry(copy);
                   8062:             entry != vm_map_copy_to_entry(copy);
                   8063:             entry = entry->vme_next) {
                   8064: 
                   8065:                object = entry->object.vm_object;
                   8066:                offset = entry->offset;
                   8067:                /*
                   8068:                 * Iterate over pages.
                   8069:                 */
                   8070:                for (va = entry->vme_start;
                   8071:                     va < entry->vme_end;
                   8072:                     va += PAGE_SIZE, offset += PAGE_SIZE) {
                   8073: 
                   8074:                        assert(new_copy->cpy_npages !=
                   8075:                               VM_MAP_COPY_PAGE_LIST_MAX);
                   8076: 
                   8077:                        /*
                   8078:                         *      If the object is null, this is
                   8079:                         *      zero fill data.
                   8080:                         */
                   8081:                        if (object == VM_OBJECT_NULL) {
                   8082:                                while ((m = vm_page_grab()) == VM_PAGE_NULL) {
                   8083:                                        VM_PAGE_WAIT();
                   8084:                                }
                   8085:                                vm_page_zero_fill(m);
                   8086:                                vm_page_gobble(m);
                   8087:                                new_copy->cpy_page_list[
                   8088:                                                new_copy->cpy_npages++] = m;
                   8089:                                continue;
                   8090:                        }
                   8091: 
                   8092:                        /*
                   8093:                         *      Try to find the page of data.
                   8094:                         */
                   8095: 
                   8096:                        vm_object_lock(object);
                   8097:                        if (((m = vm_page_lookup(object, offset)) !=
                   8098:                             VM_PAGE_NULL) && !m->busy && !m->fictitious &&
                   8099:                            !m->unusual) {
                   8100: 
                   8101:                                /*
                   8102:                                 *      This is the page.  Mark it busy.
                   8103:                                 *      Remove it from its old object.
                   8104:                                 */
                   8105:                                m->busy = TRUE;
                   8106:                                vm_page_lock_queues();
                   8107:                                VM_PAGE_QUEUES_REMOVE(m);
                   8108:                                vm_page_remove(m);
                   8109:                                vm_page_unlock_queues();
                   8110:                                vm_object_unlock(object);
                   8111:                                new_copy->cpy_page_list[new_copy->cpy_npages++]
                   8112:                                        = m;
                   8113:                                continue;
                   8114:                        }
                   8115: 
                   8116: retry:
                   8117:                        result_prot = VM_PROT_READ;
                   8118:                        vm_object_paging_begin(object);
                   8119:                        XPR(XPR_VM_FAULT,
                   8120:                            "vm_map_convert_to_page_list -> vm_fault_page\n",
                   8121:                                0,0,0,0,0);
                   8122:                        kr = vm_fault_page(object, offset,
                   8123:                                           VM_PROT_READ, FALSE, THREAD_UNINT,
                   8124:                                           entry->offset,
                   8125:                                           entry->offset + 
                   8126:                                           (entry->vme_end -
                   8127:                                            entry->vme_start),
                   8128:                                           VM_BEHAVIOR_SEQUENTIAL,
                   8129:                                           &result_prot, &m, &top_page,
                   8130:                                           (int *)0,
                   8131:                                           FALSE, FALSE, FALSE);
                   8132:                        if (kr == VM_FAULT_MEMORY_SHORTAGE) {
                   8133:                                VM_PAGE_WAIT();
                   8134:                                vm_object_lock(object);
                   8135:                                goto retry;
                   8136:                        }
                   8137:                        if (kr == VM_FAULT_FICTITIOUS_SHORTAGE) {
                   8138:                                vm_page_more_fictitious();
                   8139:                                vm_object_lock(object);
                   8140:                                goto retry;
                   8141:                        }
                   8142:                        if (kr != VM_FAULT_SUCCESS) {
                   8143:                                /* XXX what about data_error? */
                   8144:                                vm_object_lock(object);
                   8145:                                goto retry;
                   8146:                        }
                   8147: 
                   8148:                        assert(m != VM_PAGE_NULL);
                   8149:                        m->busy = TRUE;
                   8150:                        vm_page_lock_queues();
                   8151:                        VM_PAGE_QUEUES_REMOVE(m);
                   8152:                        vm_page_remove(m);
                   8153:                        vm_page_unlock_queues();
                   8154:                        vm_object_paging_end(object);
                   8155:                        vm_object_unlock(object);
                   8156:                        new_copy->cpy_page_list[new_copy->cpy_npages++] = m;
                   8157: 
                   8158:                        if (top_page != VM_PAGE_NULL) {
                   8159:                                assert(top_page->object == object);
                   8160:                                vm_object_lock(object);
                   8161:                                VM_PAGE_FREE(top_page);
                   8162:                                vm_object_paging_end(object);
                   8163:                                vm_object_unlock(object);
                   8164:                        }
                   8165:                }
                   8166:        }
                   8167: 
                   8168:        *caller_copy = new_copy;
                   8169:        return KERN_SUCCESS;
                   8170: }
                   8171: 
                   8172: 
                   8173: /*
                   8174:  *     Continue converting pages from an object-flavor
                   8175:  *     copy object into a page-list flavor copy object.
                   8176:  *     The parameters in the copy object were updated
                   8177:  *     by the last invocation of vm_map_object_to_page_list
                   8178:  *     so there's no work to be done other than calling
                   8179:  *     back into that routine.  Note that the contents
                   8180:  *     of the underlying object itself never change
                   8181:  *     during the conversion process.
                   8182:  */
                   8183: kern_return_t
                   8184: vm_map_object_to_page_list_cont(
                   8185:        vm_map_copy_t   cont_args,
                   8186:        vm_map_copy_t   *copy_result)   /* OUT */
                   8187: {
                   8188:        boolean_t       abort;
                   8189: 
                   8190:        abort = (copy_result == (vm_map_copy_t *) 0);
                   8191:        if (abort) {
                   8192:                printf("vm_map_object_to_page_list_cont:  abort\n");
                   8193:                vm_map_copy_discard(cont_args);
                   8194:        }
                   8195: 
                   8196:        assert(cont_args->type == VM_MAP_COPY_OBJECT);
                   8197:        *copy_result = cont_args;
                   8198:        return vm_map_object_to_page_list(copy_result);
                   8199: }
                   8200: 
                   8201: 
                   8202: /*
                   8203:  *     Convert a copy object from object flavor to
                   8204:  *     page list flavor.  For objects containing more
                   8205:  *     than the allowable maximum number of pages, we
                   8206:  *     perform the conversion a piece at a time.
                   8207:  *
                   8208:  *     The object flavor copy object contains a vm_object_t
                   8209:  *     that has all the pages; the type, offset and size
                   8210:  *     fields always present in a vm_map_copy_t; and an
                   8211:  *     index field unique to the object flavor.  This index
                   8212:  *     field MUST be zero when first calling this routine.
                   8213:  *     It is used to record progress converting pages from
                   8214:  *     the object to the page list.
                   8215:  *
                   8216:  *     Assumptions:
                   8217:  *             - This routine always returns KERN_SUCCESS.
                   8218:  */
                   8219: kern_return_t
                   8220: vm_map_object_to_page_list(
                   8221:        vm_map_copy_t   *caller_copy)
                   8222: {
                   8223:        vm_object_t     object;
                   8224:        vm_offset_t     offset;
                   8225:        vm_map_copy_t   copy, new_copy;
                   8226:        vm_size_t       index;
                   8227:        vm_size_t       copy_size;
                   8228:        vm_page_t       m;
                   8229:        vm_prot_t       result_prot;
                   8230:        vm_page_t       top_page;
                   8231:        kern_return_t   kr;
                   8232: 
                   8233:        assert(caller_copy != (vm_map_copy_t *) 0);
                   8234:        assert(*caller_copy != VM_MAP_COPY_NULL);
                   8235:        assert((*caller_copy)->type == VM_MAP_COPY_OBJECT);
                   8236: 
                   8237:        copy = *caller_copy;
                   8238:        object = copy->cpy_object;
                   8239: 
                   8240:        /*
                   8241:         *      Allocate the new copy.  Set its continuation to
                   8242:         *      discard the old one.
                   8243:         */
                   8244:        new_copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
                   8245:        new_copy->type = VM_MAP_COPY_PAGE_LIST;
                   8246:        new_copy->cpy_npages = 0;
                   8247:        new_copy->cpy_page_loose = FALSE;
                   8248:        new_copy->offset = copy->offset - trunc_page(copy->offset);
                   8249:        new_copy->size = copy->size;
                   8250:        assert((long)new_copy->size >= 0);
                   8251:        if (new_copy->size == 0)
                   8252:                printf("vm_object_to_page_list:  zero size\n");
                   8253:        new_copy->cpy_cont = vm_map_copy_discard_cont;
                   8254:        new_copy->cpy_cont_args = (vm_map_copyin_args_t) copy;
                   8255: 
                   8256:        /*
                   8257:         *      Compute range of object to extract.
                   8258:         */
                   8259:        index = (vm_size_t)copy->cpy_index; /* XXX!XXX! */
                   8260:        assert(copy->offset < page_size);
                   8261:        copy_size = round_page(copy->offset + copy->size);
                   8262:        assert(page_aligned(copy_size));
                   8263: 
                   8264:        /*
                   8265:         *      Detect an object larger than the maximum permitted
                   8266:         *      for an individual page list block.  Save the rest
                   8267:         *      for later.
                   8268:         */
                   8269:        if (copy_size > VM_MAP_COPY_PAGE_LIST_MAX_SIZE) {
                   8270:                /*
                   8271:                 *      Only the first copy object in the chain
                   8272:                 *      has the unaligned offset and total size.
                   8273:                 *      Each succeeding copy object has an offset
                   8274:                 *      of zero and a size decreased by the amount
                   8275:                 *      contained in the previous copy object.
                   8276:                 *      These values will be used when creating the
                   8277:                 *      next page list copy object.
                   8278:                 *
                   8279:                 *      Reset the continuation because there are
                   8280:                 *      more pages left to extract.
                   8281:                 */
                   8282:                assert(trunc_page(copy->offset) == 0);
                   8283:                copy->size = copy->size -
                   8284:                        (VM_MAP_COPY_PAGE_LIST_MAX_SIZE - copy->offset);
                   8285:                copy->offset = 0;
                   8286:                copy_size = VM_MAP_COPY_PAGE_LIST_MAX_SIZE;
                   8287:                new_copy->cpy_cont = (vm_map_copy_cont_t)
                   8288:                        vm_map_object_to_page_list_cont;
                   8289:                assert(vm_map_copy_cont_is_valid(new_copy));
                   8290:        }
                   8291: 
                   8292:        /*
                   8293:         *      Fault in all pages that aren't present.
                   8294:         *      Modelled on vm_map_copyin_page_list.
                   8295:         */
                   8296:        for (offset = index; offset < index + copy_size; offset += PAGE_SIZE) {
                   8297:                vm_object_lock(object);
                   8298:                vm_object_paging_begin(object);
                   8299: 
                   8300:                m = vm_page_lookup(object, offset);
                   8301:                if ((m != VM_PAGE_NULL) && !m->busy && !m->fictitious &&
                   8302:                    !m->unusual) {
                   8303:                        m->busy = TRUE;
                   8304:                } else {
                   8305: retry:
                   8306:                        result_prot = VM_PROT_READ;
                   8307:                        XPR(XPR_VM_FAULT,
                   8308:                                "vm_object_to_page_list -> vm_fault_page\n",
                   8309:                                0,0,0,0,0);
                   8310:                        kr = vm_fault_page(object, offset,
                   8311:                                           VM_PROT_READ, FALSE, THREAD_UNINT,
                   8312:                                           offset, index + copy_size,/* XXX ? */
                   8313:                                           VM_BEHAVIOR_SEQUENTIAL,
                   8314:                                           &result_prot, &m, &top_page,
                   8315:                                           (int *)0,
                   8316:                                           0, FALSE, FALSE);
                   8317:                        switch (kr) {
                   8318:                            case VM_FAULT_SUCCESS:
                   8319:                                break;
                   8320:                            case VM_FAULT_MEMORY_SHORTAGE:
                   8321:                                VM_PAGE_WAIT();
                   8322:                                vm_object_lock(object);
                   8323:                                vm_object_paging_begin(object);
                   8324:                                goto retry;
                   8325:                            case VM_FAULT_FICTITIOUS_SHORTAGE:
                   8326:                                vm_page_more_fictitious();
                   8327:                                /* fall through... */
                   8328:                            case VM_FAULT_INTERRUPTED:
                   8329:                            case VM_FAULT_RETRY:
                   8330:                                vm_object_lock(object);
                   8331:                                vm_object_paging_begin(object);
                   8332:                                goto retry;
                   8333:                            case VM_FAULT_MEMORY_ERROR:
                   8334:                                panic("vm_map_object_to_page_list");
                   8335:                                break;
                   8336:                        }
                   8337: 
                   8338:                        if (top_page != VM_PAGE_NULL) {
                   8339:                                VM_PAGE_FREE(top_page);
                   8340:                                vm_object_paging_end(object);
                   8341:                        }
                   8342:                }
                   8343: 
                   8344:                assert(m);
                   8345:                assert(m->busy);
                   8346:                /* assert(m->wire_count == 0); XXX */
                   8347: 
                   8348:                /*
                   8349:                 *      Got the page.  Save it in the page list
                   8350:                 *      and rip it away from the object.
                   8351:                 */
                   8352:                new_copy->cpy_page_list[new_copy->cpy_npages++] = m;
                   8353:                vm_page_lock_queues();
                   8354:                VM_PAGE_QUEUES_REMOVE(m);
                   8355:                vm_page_remove(m);
                   8356:                vm_page_unlock_queues();
                   8357: 
                   8358:                vm_object_paging_end(object);
                   8359:                vm_object_unlock(object);
                   8360:        }
                   8361: 
                   8362:        /*
                   8363:         *      Update index for next pass through the object.
                   8364:         */
                   8365:        copy->cpy_index += copy_size;
                   8366: 
                   8367:        *caller_copy = new_copy;
                   8368:        assert(vm_map_copy_cont_is_valid(new_copy));
                   8369:        return (KERN_SUCCESS);
                   8370: }
                   8371: 
                   8372: /*
                   8373:  *     When allocating a new entry, vm_map_entry_list_from_object must
                   8374:  *     use the pageable v. non-pageable entry zone based on the
                   8375:  *     attribute of the map into which the entry will be pasted.
                   8376:  *     This information must be supplied by the caller, as there is
                   8377:  *     no way to obtain it from the object.
                   8378:  *
                   8379:  *     N.B.  Caller donates a reference.
                   8380:  */
                   8381: vm_map_copy_t
                   8382: vm_map_entry_list_from_object(
                   8383:        vm_object_t             object,
                   8384:        vm_offset_t             offset,
                   8385:        vm_size_t               size,
                   8386:        boolean_t               pageable)
                   8387: {
                   8388:        vm_map_entry_t  new_entry;
                   8389:        vm_map_copy_t   copy;
                   8390: 
                   8391:        assert(object != VM_OBJECT_NULL);
                   8392:        assert(size != 0);
                   8393: 
                   8394:        copy = (vm_map_copy_t) zalloc(vm_map_copy_zone);
                   8395:        assert(copy != VM_MAP_COPY_NULL);
                   8396: 
                   8397:        copy->type = VM_MAP_COPY_ENTRY_LIST;
                   8398:        vm_map_copy_first_entry(copy) =
                   8399:                vm_map_copy_last_entry(copy) = vm_map_copy_to_entry(copy);
                   8400:        copy->cpy_hdr.nentries = 0;
                   8401:        copy->cpy_hdr.entries_pageable = pageable;
                   8402:        copy->offset = offset;
                   8403:        copy->size = size;
                   8404: 
                   8405:        /*
                   8406:         *      Allocate and initialize an entry for the object.
                   8407:         */
                   8408:        new_entry = vm_map_copy_entry_create(copy);
                   8409:        new_entry->vme_start = trunc_page(copy->offset);
                   8410:        new_entry->vme_end = round_page(copy->offset + copy->size);
                   8411:        new_entry->object.vm_object = object;
                   8412:        new_entry->offset = offset;
                   8413:        new_entry->is_shared = FALSE;
                   8414:        new_entry->is_sub_map = FALSE;
                   8415:        new_entry->needs_copy = FALSE;
                   8416:        new_entry->protection = VM_PROT_DEFAULT;
                   8417:        new_entry->max_protection = VM_PROT_ALL;
                   8418:        new_entry->inheritance = VM_INHERIT_DEFAULT;
                   8419:        new_entry->wired_count = 0;
                   8420:        new_entry->user_wired_count = 0;
                   8421:        new_entry->in_transition = FALSE;
                   8422: 
                   8423:        /*
                   8424:         *      Insert entry into copy object, and return.
                   8425:         */
                   8426:        vm_map_copy_entry_link(copy, vm_map_copy_last_entry(copy), new_entry);
                   8427:        assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
                   8428:        return (copy);
                   8429: }
                   8430: 
                   8431: /*
                   8432:  *     Convert a page list copy object to an entry list
                   8433:  *     flavor copy object.
                   8434:  */
                   8435: kern_return_t
                   8436: vm_map_convert_to_entry_list(
                   8437:        vm_map_copy_t   copy,
                   8438:        boolean_t       pageable)
                   8439: {
                   8440:        vm_object_t object;
                   8441:        int i;
                   8442:        vm_map_entry_t  new_entry;
                   8443:        vm_page_t       *page_list;
                   8444:        vm_map_copy_t   cur_copy, new_copy;
                   8445:        vm_offset_t     offset;
                   8446:        kern_return_t   result;
                   8447: 
                   8448:        /*
                   8449:         * Check type of copy object.
                   8450:         */
                   8451:        if (copy->type != VM_MAP_COPY_PAGE_LIST) {
                   8452:                panic("vm_map_convert_to_entry_list 0x%x %d", copy, copy->type);
                   8453:        }
                   8454: 
                   8455:        /*
                   8456:         *      Insert all the pages into a new object.
                   8457:         */
                   8458:        object = vm_object_allocate(round_page(copy->offset + copy->size) -
                   8459:                                    trunc_page(copy->offset));
                   8460:        offset = (vm_offset_t) 0;
                   8461:        cur_copy = copy;
                   8462: 
                   8463:        while (cur_copy) {
                   8464: 
                   8465:                /*
                   8466:                 *      Make sure the pages are loose.  This may be
                   8467:                 *      a "Can't Happen", but just to be safe ...
                   8468:                 */
                   8469:                page_list = &cur_copy->cpy_page_list[0];
                   8470:                if (!copy->cpy_page_loose)
                   8471:                        vm_map_copy_steal_pages(cur_copy);
                   8472: 
                   8473:                /*
                   8474:                 * Stuff this set of pages into the object, removing
                   8475:                 * them from the page list.
                   8476:                 */
                   8477:                vm_object_lock(object);
                   8478:                vm_page_lock_queues();
                   8479:                for (i = 0; i < cur_copy->cpy_npages;
                   8480:                    i++, offset += PAGE_SIZE) {
                   8481:                        register vm_page_t m = *page_list;
                   8482: 
                   8483:                        vm_page_insert(m, object, offset);
                   8484:                        m->busy = FALSE;
                   8485:                        m->dirty = TRUE;
                   8486:                        vm_page_activate(m);
                   8487:                        *page_list++ = VM_PAGE_NULL;
                   8488:                }
                   8489:                vm_page_unlock_queues();
                   8490:                vm_object_unlock(object);
                   8491: 
                   8492:                /*
                   8493:                 *      Invoke continuation if present.
                   8494:                 */
                   8495:                if (vm_map_copy_has_cont(cur_copy)) {
                   8496:                        vm_map_copy_invoke_cont(cur_copy, &new_copy, &result);
                   8497: 
                   8498:                        if (result != KERN_SUCCESS)
                   8499:                                panic("%s:  %s",
                   8500:                                      "vm_map_convert_to_entry_list",
                   8501:                                      "continuation failure");
                   8502:                } else {
                   8503:                        new_copy = VM_MAP_COPY_NULL;
                   8504:                }               
                   8505:                if (cur_copy != copy)
                   8506:                        vm_map_copy_discard(cur_copy);
                   8507: 
                   8508:                cur_copy = new_copy;
                   8509:        }
                   8510: 
                   8511:        /*
                   8512:         * Change type of copy object
                   8513:         */
                   8514:        vm_map_copy_first_entry(copy) =
                   8515:            vm_map_copy_last_entry(copy) = vm_map_copy_to_entry(copy);
                   8516:        copy->type = VM_MAP_COPY_ENTRY_LIST;
                   8517:        copy->cpy_hdr.nentries = 0;
                   8518:        copy->cpy_hdr.entries_pageable = pageable;
                   8519: 
                   8520:        /*
                   8521:         * Allocate and initialize an entry for object
                   8522:         */
                   8523:        new_entry = vm_map_copy_entry_create(copy);
                   8524:        new_entry->vme_start = trunc_page(copy->offset);
                   8525:        new_entry->vme_end = round_page(copy->offset + copy->size);
                   8526:        new_entry->object.vm_object = object;
                   8527:        new_entry->offset = 0;
                   8528:        new_entry->is_shared = FALSE;
                   8529:        new_entry->is_sub_map = FALSE;
                   8530:        new_entry->needs_copy = FALSE;
                   8531:        new_entry->protection = VM_PROT_DEFAULT;
                   8532:        new_entry->max_protection = VM_PROT_ALL;
                   8533:        new_entry->behavior = VM_BEHAVIOR_DEFAULT;
                   8534:        new_entry->inheritance = VM_INHERIT_DEFAULT;
                   8535:        new_entry->wired_count = 0;
                   8536:        new_entry->user_wired_count = 0;
                   8537: 
                   8538:        /*
                   8539:         * Insert entry into copy object, and return.
                   8540:         */
                   8541:        vm_map_copy_entry_link(copy, vm_map_copy_last_entry(copy), new_entry);
                   8542:        return(KERN_SUCCESS);
                   8543: }
                   8544: 
                   8545: #endif /* DIPC */
                   8546: 
                   8547: int
                   8548: vm_map_copy_cont_is_valid(
                   8549:        vm_map_copy_t   copy)
                   8550: {
                   8551:        vm_map_copy_cont_t      cont;
                   8552: 
                   8553:        assert(copy->type == VM_MAP_COPY_PAGE_LIST);
                   8554:        cont = copy->cpy_cont;
                   8555:        if (
                   8556:            cont != vm_map_copy_discard_cont &&
                   8557:            cont != vm_map_copyin_page_list_cont ) {
                   8558:                printf("vm_map_copy_cont_is_valid:  bogus cont 0x%x\n", cont);
                   8559:                assert((integer_t) cont == 0xdeadbeef);
                   8560:        }
                   8561:        return 1;
                   8562: }
                   8563: 
                   8564: #include <mach_kdb.h>
                   8565: #if    MACH_KDB
                   8566: #include <ddb/db_output.h>
                   8567: #include <vm/vm_print.h>
                   8568: 
                   8569: #define        printf  db_printf
                   8570: 
                   8571: /*
                   8572:  * Forward declarations for internal functions.
                   8573:  */
                   8574: extern void vm_map_links_print(
                   8575:                struct vm_map_links     *links);
                   8576: 
                   8577: extern void vm_map_header_print(
                   8578:                struct vm_map_header    *header);
                   8579: 
                   8580: extern void vm_map_entry_print(
                   8581:                vm_map_entry_t          entry);
                   8582: 
                   8583: extern void vm_follow_entry(
                   8584:                vm_map_entry_t          entry);
                   8585: 
                   8586: extern void vm_follow_map(
                   8587:                vm_map_t                map);
                   8588: 
                   8589: /*
                   8590:  *     vm_map_links_print:     [ debug ]
                   8591:  */
                   8592: void
                   8593: vm_map_links_print(
                   8594:        struct vm_map_links     *links)
                   8595: {
                   8596:        iprintf("prev=0x%x, next=0x%x, start=0x%x, end=0x%x\n",
                   8597:                links->prev,
                   8598:                links->next,
                   8599:                links->start,
                   8600:                links->end);
                   8601: }
                   8602: 
                   8603: /*
                   8604:  *     vm_map_header_print:    [ debug ]
                   8605:  */
                   8606: void
                   8607: vm_map_header_print(
                   8608:        struct vm_map_header    *header)
                   8609: {
                   8610:        vm_map_links_print(&header->links);
                   8611:        iprintf("nentries=0x%x, %sentries_pageable\n",
                   8612:                header->nentries,
                   8613:                (header->entries_pageable ? "" : "!"));
                   8614: }
                   8615: 
                   8616: /*
                   8617:  *     vm_follow_entry:        [ debug ]
                   8618:  */
                   8619: void
                   8620: vm_follow_entry(
                   8621:        vm_map_entry_t entry)
                   8622: {
                   8623:        extern int db_indent;
                   8624:        int shadows;
                   8625: 
                   8626:        iprintf("map entry 0x%x:\n", entry);
                   8627: 
                   8628:        db_indent += 2;
                   8629: 
                   8630:        shadows = vm_follow_object(entry->object.vm_object);
                   8631:        iprintf("Total objects : %d\n",shadows);
                   8632: 
                   8633:        db_indent -= 2;
                   8634: }
                   8635: 
                   8636: /*
                   8637:  *     vm_map_entry_print:     [ debug ]
                   8638:  */
                   8639: void
                   8640: vm_map_entry_print(
                   8641:        register vm_map_entry_t entry)
                   8642: {
                   8643:        extern int db_indent;
                   8644:        static char *inheritance_name[4] = { "share", "copy", "none", "?"};
                   8645:        static char *behavior_name[4] = { "dflt", "rand", "seqtl", "rseqntl" };
                   8646:        
                   8647:        iprintf("map entry 0x%x:\n", entry);
                   8648: 
                   8649:        db_indent += 2;
                   8650: 
                   8651:        vm_map_links_print(&entry->links);
                   8652: 
                   8653:        iprintf("start=0x%x, end=0x%x, prot=%x/%x/%s\n",
                   8654:                entry->vme_start,
                   8655:                entry->vme_end,
                   8656:                entry->protection,
                   8657:                entry->max_protection,
                   8658:                inheritance_name[(entry->inheritance & 0x3)]);
                   8659: 
                   8660:        iprintf("behavior=%s, wired_count=%d, user_wired_count=%d\n",
                   8661:                behavior_name[(entry->behavior & 0x3)],
                   8662:                entry->wired_count,
                   8663:                entry->user_wired_count);
                   8664:        iprintf("%sin_transition, %sneeds_wakeup\n",
                   8665:                (entry->in_transition ? "" : "!"),
                   8666:                (entry->needs_wakeup ? "" : "!"));
                   8667: 
                   8668:        if (entry->is_sub_map) {
                   8669:                iprintf("submap=0x%x, offset=0x%x\n",
                   8670:                       entry->object.sub_map,
                   8671:                       entry->offset);
                   8672:        } else {
                   8673:                iprintf("object=0x%x, offset=0x%x, ",
                   8674:                        entry->object.vm_object,
                   8675:                        entry->offset);
                   8676:                printf("%sis_shared, %sneeds_copy\n",
                   8677:                       (entry->is_shared ? "" : "!"),
                   8678:                       (entry->needs_copy ? "" : "!"));
                   8679:        }
                   8680: 
                   8681:        db_indent -= 2;
                   8682: }
                   8683: 
                   8684: /*
                   8685:  *     vm_follow_map:  [ debug ]
                   8686:  */
                   8687: void
                   8688: vm_follow_map(
                   8689:        vm_map_t map)
                   8690: {
                   8691:        register vm_map_entry_t entry;
                   8692:        extern int db_indent;
                   8693: 
                   8694:        iprintf("task map 0x%x:\n", map);
                   8695: 
                   8696:        db_indent += 2;
                   8697: 
                   8698:        for (entry = vm_map_first_entry(map);
                   8699:             entry && entry != vm_map_to_entry(map);
                   8700:             entry = entry->vme_next) {
                   8701:            vm_follow_entry(entry);
                   8702:        }
                   8703: 
                   8704:        db_indent -= 2;
                   8705: }
                   8706: 
                   8707: /*
                   8708:  *     vm_map_print:   [ debug ]
                   8709:  */
                   8710: void
                   8711: vm_map_print(
                   8712:        register vm_map_t       map)
                   8713: {
                   8714:        register vm_map_entry_t entry;
                   8715:        extern int db_indent;
                   8716:        char *swstate;
                   8717: 
                   8718:        iprintf("task map 0x%x:\n", map);
                   8719: 
                   8720:        db_indent += 2;
                   8721: 
                   8722:        vm_map_header_print(&map->hdr);
                   8723: 
                   8724:        iprintf("pmap=0x%x, size=%d, ref=%d, hint=0x%x, first_free=0x%x\n",
                   8725:                map->pmap,
                   8726:                map->size,
                   8727:                map->ref_count,
                   8728:                map->hint,
                   8729:                map->first_free);
                   8730: 
                   8731:        iprintf("%swait_for_space, %swiring_required, timestamp=%d\n",
                   8732:                (map->wait_for_space ? "" : "!"),
                   8733:                (map->wiring_required ? "" : "!"),
                   8734:                map->timestamp);
                   8735: 
                   8736: #if    TASK_SWAPPER
                   8737:        switch (map->sw_state) {
                   8738:            case MAP_SW_IN:
                   8739:                swstate = "SW_IN";
                   8740:                break;
                   8741:            case MAP_SW_OUT:
                   8742:                swstate = "SW_OUT";
                   8743:                break;
                   8744:            default:
                   8745:                swstate = "????";
                   8746:                break;
                   8747:        }
                   8748:        iprintf("res=%d, sw_state=%s\n", map->res_count, swstate);
                   8749: #endif /* TASK_SWAPPER */
                   8750: 
                   8751:        for (entry = vm_map_first_entry(map);
                   8752:             entry && entry != vm_map_to_entry(map);
                   8753:             entry = entry->vme_next) {
                   8754:                vm_map_entry_print(entry);
                   8755:        }
                   8756: 
                   8757:        db_indent -= 2;
                   8758: }
                   8759: 
                   8760: /*
                   8761:  *     Routine:        vm_map_copy_print
                   8762:  *     Purpose:
                   8763:  *             Pretty-print a copy object for ddb.
                   8764:  */
                   8765: 
                   8766: void
                   8767: vm_map_copy_print(
                   8768:        vm_map_copy_t   copy)
                   8769: {
                   8770:        extern int db_indent;
                   8771:        int i, npages;
                   8772:        vm_map_entry_t entry;
                   8773: 
                   8774:        printf("copy object 0x%x\n", copy);
                   8775: 
                   8776:        db_indent += 2;
                   8777: 
                   8778:        iprintf("type=%d", copy->type);
                   8779:        switch (copy->type) {
                   8780:                case VM_MAP_COPY_ENTRY_LIST:
                   8781:                printf("[entry_list]");
                   8782:                break;
                   8783:                
                   8784:                case VM_MAP_COPY_OBJECT:
                   8785:                printf("[object]");
                   8786:                break;
                   8787:                
                   8788:                case VM_MAP_COPY_PAGE_LIST:
                   8789:                printf("[page_list]");
                   8790:                break;
                   8791:                
                   8792:                case VM_MAP_COPY_KERNEL_BUFFER:
                   8793:                printf("[kernel_buffer]");
                   8794:                break;
                   8795: 
                   8796:                default:
                   8797:                printf("[bad type]");
                   8798:                break;
                   8799:        }
                   8800:        printf(", offset=0x%x", copy->offset);
                   8801:        printf(", size=0x%x\n", copy->size);
                   8802: 
                   8803:        switch (copy->type) {
                   8804:                case VM_MAP_COPY_ENTRY_LIST:
                   8805:                vm_map_header_print(&copy->cpy_hdr);
                   8806:                for (entry = vm_map_copy_first_entry(copy);
                   8807:                     entry && entry != vm_map_copy_to_entry(copy);
                   8808:                     entry = entry->vme_next) {
                   8809:                        vm_map_entry_print(entry);
                   8810:                }
                   8811:                break;
                   8812: 
                   8813:                case VM_MAP_COPY_OBJECT:
                   8814:                iprintf("object=0x%x\n", copy->cpy_object);
                   8815:                break;
                   8816: 
                   8817:                case VM_MAP_COPY_KERNEL_BUFFER:
                   8818:                iprintf("kernel buffer=0x%x", copy->cpy_kdata);
                   8819:                printf(", kalloc_size=0x%x\n", copy->cpy_kalloc_size);
                   8820:                break;
                   8821: 
                   8822:                case VM_MAP_COPY_PAGE_LIST:
                   8823:                iprintf("npages=%d", copy->cpy_npages);
                   8824:                printf(", cont=%x", copy->cpy_cont);
                   8825:                printf(", cont_args=%x\n", copy->cpy_cont_args);
                   8826:                if (copy->cpy_npages < 0) {
                   8827:                        npages = 0;
                   8828:                } else if (copy->cpy_npages > VM_MAP_COPY_PAGE_LIST_MAX) {
                   8829:                        npages = VM_MAP_COPY_PAGE_LIST_MAX;
                   8830:                } else {
                   8831:                        npages = copy->cpy_npages;
                   8832:                }
                   8833:                iprintf("copy->cpy_page_list[0..%d] = {", npages);
                   8834:                for (i = 0; i < npages - 1; i++) {
                   8835:                        printf("0x%x, ", copy->cpy_page_list[i]);
                   8836:                }
                   8837:                if (npages > 0) {
                   8838:                        printf("0x%x", copy->cpy_page_list[npages - 1]);
                   8839:                }
                   8840:                printf("}\n");
                   8841:                break;
                   8842:        }
                   8843: 
                   8844:        db_indent -=2;
                   8845: }
                   8846: 
                   8847: /*
                   8848:  *     db_vm_map_total_size(map)       [ debug ]
                   8849:  *
                   8850:  *     return the total virtual size (in bytes) of the map
                   8851:  */
                   8852: vm_size_t
                   8853: db_vm_map_total_size(
                   8854:        vm_map_t        map)
                   8855: {
                   8856:        vm_map_entry_t  entry;
                   8857:        vm_size_t       total;
                   8858: 
                   8859:        total = 0;
                   8860:        for (entry = vm_map_first_entry(map);
                   8861:             entry != vm_map_to_entry(map);
                   8862:             entry = entry->vme_next) {
                   8863:                total += entry->vme_end - entry->vme_start;
                   8864:        }
                   8865: 
                   8866:        return total;
                   8867: }
                   8868: 
                   8869: #endif /* MACH_KDB */
                   8870: 
                   8871: /*
                   8872:  *     Routine:        vm_map_entry_insert
                   8873:  *
                   8874:  *     Descritpion:    This routine inserts a new vm_entry in a locked map.
                   8875:  */
                   8876: vm_map_entry_t
                   8877: vm_map_entry_insert(
                   8878:        vm_map_t        map,
                   8879:        vm_map_entry_t  insp_entry,
                   8880:        vm_offset_t     start,
                   8881:        vm_offset_t     end,
                   8882:        vm_object_t     object,
                   8883:        vm_offset_t     offset,
                   8884:        boolean_t       needs_copy,
                   8885:        boolean_t       is_shared,
                   8886:        boolean_t       in_transition,
                   8887:        vm_prot_t       cur_protection,
                   8888:        vm_prot_t       max_protection,
                   8889:        vm_behavior_t   behavior,
                   8890:        vm_inherit_t    inheritance,
                   8891:        unsigned        wired_count)
                   8892: {
                   8893:        vm_map_entry_t  new_entry;
                   8894: 
                   8895:        assert(insp_entry != (vm_map_entry_t)0);
                   8896: 
                   8897:        new_entry = vm_map_entry_create(map);
                   8898: 
                   8899:        new_entry->vme_start = start;
                   8900:        new_entry->vme_end = end;
                   8901:        assert(page_aligned(new_entry->vme_start));
                   8902:        assert(page_aligned(new_entry->vme_end));
                   8903: 
                   8904:        new_entry->object.vm_object = object;
                   8905:        new_entry->offset = offset;
                   8906:        new_entry->is_shared = is_shared;
                   8907:        new_entry->is_sub_map = FALSE;
                   8908:        new_entry->needs_copy = needs_copy;
                   8909:        new_entry->in_transition = in_transition;
                   8910:        new_entry->needs_wakeup = FALSE;
                   8911:        new_entry->inheritance = inheritance;
                   8912:        new_entry->protection = cur_protection;
                   8913:        new_entry->max_protection = max_protection;
                   8914:        new_entry->behavior = behavior;
                   8915:        new_entry->wired_count = wired_count;
                   8916:        new_entry->user_wired_count = 0;
                   8917: 
                   8918:        /*
                   8919:         *      Insert the new entry into the list.
                   8920:         */
                   8921: 
                   8922:        vm_map_entry_link(map, insp_entry, new_entry);
                   8923:        map->size += end - start;
                   8924: 
                   8925:        /*
                   8926:         *      Update the free space hint and the lookup hint.
                   8927:         */
                   8928: 
                   8929:        SAVE_HINT(map, new_entry);
                   8930:        return new_entry;
                   8931: }
                   8932: 
                   8933: /*
                   8934:  *     Routine:        vm_remap_extract
                   8935:  *
                   8936:  *     Descritpion:    This routine returns a vm_entry list from a map.
                   8937:  */
                   8938: kern_return_t
                   8939: vm_remap_extract(
                   8940:        vm_map_t                map,
                   8941:        vm_offset_t             addr,
                   8942:        vm_size_t               size,
                   8943:        boolean_t               copy,
                   8944:        struct vm_map_header    *map_header,
                   8945:        vm_prot_t               *cur_protection,
                   8946:        vm_prot_t               *max_protection,
                   8947:        /* What, no behavior? */
                   8948:        vm_inherit_t            inheritance,
                   8949:        boolean_t               pageable)
                   8950: {
                   8951:        kern_return_t           result;
                   8952:        vm_size_t               mapped_size;
                   8953:        vm_size_t               tmp_size;
                   8954:        vm_map_entry_t          src_entry;     /* result of last map lookup */
                   8955:        vm_map_entry_t          new_entry;
                   8956:        vm_offset_t             offset;
                   8957:        vm_offset_t             map_address;
                   8958:        vm_offset_t             src_start;     /* start of entry to map */
                   8959:        vm_offset_t             src_end;       /* end of region to be mapped */
                   8960:        vm_object_t             object;    
                   8961:        vm_map_version_t        version;
                   8962:        boolean_t               src_needs_copy;
                   8963:        boolean_t               new_entry_needs_copy;
                   8964: 
                   8965:        assert(map != VM_MAP_NULL);
                   8966:        assert(size != 0 && size == round_page(size));
                   8967:        assert(inheritance == VM_INHERIT_NONE ||
                   8968:               inheritance == VM_INHERIT_COPY ||
                   8969:               inheritance == VM_INHERIT_SHARE);
                   8970: 
                   8971:        /*
                   8972:         *      Compute start and end of region.
                   8973:         */
                   8974:        src_start = trunc_page(addr);
                   8975:        src_end = round_page(src_start + size);
                   8976: 
                   8977:        /*
                   8978:         *      Initialize map_header.
                   8979:         */
                   8980:        map_header->links.next = (struct vm_map_entry *)&map_header->links;
                   8981:        map_header->links.prev = (struct vm_map_entry *)&map_header->links;
                   8982:        map_header->nentries = 0;
                   8983:        map_header->entries_pageable = pageable;
                   8984: 
                   8985:        *cur_protection = VM_PROT_ALL;
                   8986:        *max_protection = VM_PROT_ALL;
                   8987: 
                   8988:        map_address = 0;
                   8989:        mapped_size = 0;
                   8990:        result = KERN_SUCCESS;
                   8991: 
                   8992:        /*  
                   8993:         *      The specified source virtual space might correspond to
                   8994:         *      multiple map entries, need to loop on them.
                   8995:         */
                   8996:        vm_map_lock(map);
                   8997:        while (mapped_size != size) {
                   8998:                vm_size_t       entry_size;
                   8999: 
                   9000:                /*
                   9001:                 *      Find the beginning of the region.
                   9002:                 */ 
                   9003:                if (! vm_map_lookup_entry(map, src_start, &src_entry)) {
                   9004:                        result = KERN_INVALID_ADDRESS;
                   9005:                        break;
                   9006:                }
                   9007: 
                   9008:                if (src_start < src_entry->vme_start ||
                   9009:                    (mapped_size && src_start != src_entry->vme_start)) {
                   9010:                        result = KERN_INVALID_ADDRESS;
                   9011:                        break;
                   9012:                }
                   9013: 
                   9014:                if(src_entry->is_sub_map) {
                   9015:                        result = KERN_INVALID_ADDRESS;
                   9016:                        break;
                   9017:                }
                   9018: 
                   9019:                tmp_size = size - mapped_size;
                   9020:                if (src_end > src_entry->vme_end)
                   9021:                        tmp_size -= (src_end - src_entry->vme_end);
                   9022: 
                   9023:                entry_size = (vm_size_t)(src_entry->vme_end -
                   9024:                                         src_entry->vme_start);
                   9025: 
                   9026:                if(src_entry->is_sub_map) {
                   9027:                        vm_map_reference(src_entry->object.sub_map);
                   9028:                } else {
                   9029:                        object = src_entry->object.vm_object;
                   9030: 
                   9031:                        if (object == VM_OBJECT_NULL) {
                   9032:                                object = vm_object_allocate(entry_size);
                   9033:                                src_entry->offset = 0;
                   9034:                                src_entry->object.vm_object = object;
                   9035:                        } else if (object->copy_strategy !=
                   9036:                                   MEMORY_OBJECT_COPY_SYMMETRIC) {
                   9037:                                /*
                   9038:                                 *      We are already using an asymmetric
                   9039:                                 *      copy, and therefore we already have
                   9040:                                 *      the right object.
                   9041:                                 */
                   9042:                                assert(!src_entry->needs_copy);
                   9043:                        } else if (src_entry->needs_copy || object->shadowed ||
                   9044:                                   (object->internal && !object->true_share &&
                   9045:                                   !src_entry->is_shared &&
                   9046:                                    object->size > entry_size)) {
                   9047: 
                   9048:                                vm_object_shadow(&src_entry->object.vm_object,
                   9049:                                                 &src_entry->offset,
                   9050:                                                 entry_size);
                   9051: 
                   9052:                                if (!src_entry->needs_copy &&
                   9053:                                    (src_entry->protection & VM_PROT_WRITE)) {
                   9054:                                        pmap_protect(vm_map_pmap(map),
                   9055:                                             src_entry->vme_start,
                   9056:                                             src_entry->vme_end,
                   9057:                                             src_entry->protection &
                   9058:                                                     ~VM_PROT_WRITE);
                   9059:                                }
                   9060: 
                   9061:                                object = src_entry->object.vm_object;
                   9062:                                src_entry->needs_copy = FALSE;
                   9063:                        }
                   9064: 
                   9065: 
                   9066:                        vm_object_lock(object);
                   9067:                        object->ref_count++;    /* object ref. for new entry */
                   9068:                        VM_OBJ_RES_INCR(object);
                   9069:                        if (object->copy_strategy == 
                   9070:                                        MEMORY_OBJECT_COPY_SYMMETRIC) {
                   9071:                                object->copy_strategy = 
                   9072:                                        MEMORY_OBJECT_COPY_DELAY;
                   9073:                        }
                   9074:                        vm_object_unlock(object);
                   9075:                }
                   9076: 
                   9077:                offset = src_entry->offset + (src_start - src_entry->vme_start);
                   9078: 
                   9079:                new_entry = _vm_map_entry_create(map_header);
                   9080:                vm_map_entry_copy(new_entry, src_entry);
                   9081: 
                   9082:                new_entry->vme_start = map_address;
                   9083:                new_entry->vme_end = map_address + tmp_size;
                   9084:                new_entry->inheritance = inheritance;
                   9085:                new_entry->offset = offset;
                   9086: 
                   9087:                /*
                   9088:                 * The new region has to be copied now if required.
                   9089:                 */
                   9090:        RestartCopy:
                   9091:                if (!copy) {
                   9092:                        src_entry->is_shared = TRUE;
                   9093:                        new_entry->is_shared = TRUE;
                   9094:                        if (!(new_entry->is_sub_map)) 
                   9095:                                new_entry->needs_copy = FALSE;
                   9096: 
                   9097:                } else if (src_entry->is_sub_map) {
                   9098:                        /* make this a COW sub_map if not already */
                   9099:                        new_entry->needs_copy = TRUE;
                   9100:                } else if (src_entry->wired_count == 0 &&
                   9101:                         vm_object_copy_quickly(&new_entry->object.vm_object,
                   9102:                                                new_entry->offset,
                   9103:                                                (new_entry->vme_end -
                   9104:                                                    new_entry->vme_start),
                   9105:                                                &src_needs_copy,
                   9106:                                                &new_entry_needs_copy)) {
                   9107: 
                   9108:                        new_entry->needs_copy = new_entry_needs_copy;
                   9109:                        new_entry->is_shared = FALSE;
                   9110: 
                   9111:                        /*
                   9112:                         * Handle copy_on_write semantics.
                   9113:                         */
                   9114:                        if (src_needs_copy && !src_entry->needs_copy) {
                   9115:                                vm_object_pmap_protect(object,
                   9116:                                                       offset,
                   9117:                                                       entry_size,
                   9118:                                                       (src_entry->is_shared ?
                   9119:                                                        PMAP_NULL : map->pmap),
                   9120:                                                       src_entry->vme_start,
                   9121:                                                       src_entry->protection &
                   9122:                                                       ~VM_PROT_WRITE);
                   9123: 
                   9124:                                src_entry->needs_copy = TRUE;
                   9125:                        }
                   9126:                        /*
                   9127:                         * Throw away the old object reference of the new entry.
                   9128:                         */
                   9129:                        vm_object_deallocate(object);
                   9130: 
                   9131:                } else {
                   9132:                        new_entry->is_shared = FALSE;
                   9133: 
                   9134:                        /*
                   9135:                         * The map can be safely unlocked since we
                   9136:                         * already hold a reference on the object.
                   9137:                         *
                   9138:                         * Record the timestamp of the map for later
                   9139:                         * verification, and unlock the map.
                   9140:                         */
                   9141:                        version.main_timestamp = map->timestamp;
                   9142:                        vm_map_unlock(map);
                   9143: 
                   9144:                        /*
                   9145:                         * Perform the copy.
                   9146:                         */
                   9147:                        if (src_entry->wired_count > 0) {
                   9148:                                vm_object_lock(object);
                   9149:                                result = vm_object_copy_slowly(
                   9150:                                                object,
                   9151:                                                offset,
                   9152:                                                entry_size,
                   9153:                                                THREAD_UNINT,
                   9154:                                                &new_entry->object.vm_object);
                   9155: 
                   9156:                                new_entry->offset = 0;
                   9157:                                new_entry->needs_copy = FALSE;
                   9158:                        } else {
                   9159:                                result = vm_object_copy_strategically(
                   9160:                                                object,
                   9161:                                                offset,
                   9162:                                                entry_size,
                   9163:                                                &new_entry->object.vm_object,
                   9164:                                                &new_entry->offset,
                   9165:                                                &new_entry_needs_copy);
                   9166: 
                   9167:                                new_entry->needs_copy = new_entry_needs_copy;
                   9168:                        }
                   9169: 
                   9170:                        /*
                   9171:                         * Throw away the old object reference of the new entry.
                   9172:                         */
                   9173:                        vm_object_deallocate(object);
                   9174: 
                   9175:                        if (result != KERN_SUCCESS &&
                   9176:                            result != KERN_MEMORY_RESTART_COPY) {
                   9177:                                _vm_map_entry_dispose(map_header, new_entry);
                   9178:                                break;
                   9179:                        }
                   9180: 
                   9181:                        /*
                   9182:                         * Verify that the map has not substantially
                   9183:                         * changed while the copy was being made.
                   9184:                         */
                   9185: 
                   9186:                        vm_map_lock(map);       /* Increments timestamp once! */
                   9187:                        if (version.main_timestamp + 1 != map->timestamp) {
                   9188:                                /*
                   9189:                                 * Simple version comparison failed.
                   9190:                                 *
                   9191:                                 * Retry the lookup and verify that the
                   9192:                                 * same object/offset are still present.
                   9193:                                 */
                   9194:                                vm_object_deallocate(new_entry->
                   9195:                                                     object.vm_object);
                   9196:                                _vm_map_entry_dispose(map_header, new_entry);
                   9197:                                if (result == KERN_MEMORY_RESTART_COPY)
                   9198:                                        result = KERN_SUCCESS;
                   9199:                                continue;
                   9200:                        }
                   9201: 
                   9202:                        if (result == KERN_MEMORY_RESTART_COPY) {
                   9203:                                vm_object_reference(object);
                   9204:                                goto RestartCopy;
                   9205:                        }
                   9206:                }
                   9207: 
                   9208:                _vm_map_entry_link(map_header,
                   9209:                                   map_header->links.prev, new_entry);
                   9210: 
                   9211:                *cur_protection &= src_entry->protection;
                   9212:                *max_protection &= src_entry->max_protection;
                   9213: 
                   9214:                map_address += tmp_size;
                   9215:                mapped_size += tmp_size;
                   9216:                src_start += tmp_size;
                   9217: 
                   9218:        } /* end while */
                   9219: 
                   9220:        vm_map_unlock(map);
                   9221:        if (result != KERN_SUCCESS) {
                   9222:                /*
                   9223:                 * Free all allocated elements.
                   9224:                 */
                   9225:                for (src_entry = map_header->links.next;
                   9226:                     src_entry != (struct vm_map_entry *)&map_header->links;
                   9227:                     src_entry = new_entry) {
                   9228:                        new_entry = src_entry->vme_next;
                   9229:                        _vm_map_entry_unlink(map_header, src_entry);
                   9230:                        vm_object_deallocate(src_entry->object.vm_object);
                   9231:                        _vm_map_entry_dispose(map_header, src_entry);
                   9232:                }
                   9233:        }
                   9234:        return result;
                   9235: }
                   9236: 
                   9237: /*
                   9238:  *     Routine:        vm_remap
                   9239:  *
                   9240:  *                     Map portion of a task's address space.
                   9241:  *                     Mapped region must not overlap more than
                   9242:  *                     one vm memory object. Protections and
                   9243:  *                     inheritance attributes remain the same
                   9244:  *                     as in the original task and are out parameters.
                   9245:  *                     Source and Target task can be identical
                   9246:  *                     Other attributes are identical as for vm_map()
                   9247:  */
                   9248: kern_return_t
                   9249: vm_remap(
                   9250:        vm_map_t                target_map,
                   9251:        vm_offset_t             *address,
                   9252:        vm_size_t               size,
                   9253:        vm_offset_t             mask,
                   9254:        boolean_t               anywhere,
                   9255:        vm_map_t                src_map,
                   9256:        vm_offset_t             memory_address,
                   9257:        boolean_t               copy,
                   9258:        vm_prot_t               *cur_protection,
                   9259:        vm_prot_t               *max_protection,
                   9260:        vm_inherit_t            inheritance)
                   9261: {
                   9262:        kern_return_t           result;
                   9263:        vm_map_entry_t          entry;
                   9264:        vm_map_entry_t          insp_entry;
                   9265:        vm_map_entry_t          new_entry;
                   9266:        struct vm_map_header    map_header;
                   9267: 
                   9268:        if (target_map == VM_MAP_NULL)
                   9269:                return KERN_INVALID_ARGUMENT;
                   9270: 
                   9271:        switch (inheritance) {
                   9272:            case VM_INHERIT_NONE:
                   9273:            case VM_INHERIT_COPY:
                   9274:            case VM_INHERIT_SHARE:
                   9275:                if (size != 0 && src_map != VM_MAP_NULL)
                   9276:                        break;
                   9277:                /*FALL THRU*/
                   9278:            default:
                   9279:                return KERN_INVALID_ARGUMENT;
                   9280:        }
                   9281: 
                   9282:        size = round_page(size);
                   9283: 
                   9284:        result = vm_remap_extract(src_map, memory_address,
                   9285:                                  size, copy, &map_header,
                   9286:                                  cur_protection,
                   9287:                                  max_protection,
                   9288:                                  inheritance,
                   9289:                                  target_map->hdr.
                   9290:                                  entries_pageable);
                   9291:        vm_map_deallocate(src_map);
                   9292: 
                   9293:        if (result != KERN_SUCCESS) {
                   9294:                return result;
                   9295:        }
                   9296: 
                   9297:        /*
                   9298:         * Allocate/check a range of free virtual address
                   9299:         * space for the target
                   9300:         */
                   9301:        *address = trunc_page(*address);
                   9302:        vm_map_lock(target_map);
                   9303:        result = vm_remap_range_allocate(target_map, address, size,
                   9304:                                         mask, anywhere, &insp_entry);
                   9305: 
                   9306:        for (entry = map_header.links.next;
                   9307:             entry != (struct vm_map_entry *)&map_header.links;
                   9308:             entry = new_entry) {
                   9309:                new_entry = entry->vme_next;
                   9310:                _vm_map_entry_unlink(&map_header, entry);
                   9311:                if (result == KERN_SUCCESS) {
                   9312:                        entry->vme_start += *address;
                   9313:                        entry->vme_end += *address;
                   9314:                        vm_map_entry_link(target_map, insp_entry, entry);
                   9315:                        insp_entry = entry;
                   9316:                } else {
                   9317:                        if (!entry->is_sub_map) {
                   9318:                                vm_object_deallocate(entry->object.vm_object);
                   9319:                        } else {
                   9320:                                vm_map_deallocate(entry->object.sub_map);
                   9321:                           }
                   9322:                        _vm_map_entry_dispose(&map_header, entry);
                   9323:                }
                   9324:        }
                   9325: 
                   9326:        if (result == KERN_SUCCESS) {
                   9327:                target_map->size += size;
                   9328:                SAVE_HINT(target_map, insp_entry);
                   9329:        }
                   9330:        vm_map_unlock(target_map);
                   9331: 
                   9332:        if (result == KERN_SUCCESS && target_map->wiring_required)
                   9333:                result = vm_map_wire(target_map, *address,
                   9334:                                     *address + size, *cur_protection, TRUE);
                   9335:        return result;
                   9336: }
                   9337: 
                   9338: /*
                   9339:  *     Routine:        vm_remap_range_allocate
                   9340:  *
                   9341:  *     Description:
                   9342:  *             Allocate a range in the specified virtual address map.
                   9343:  *             returns the address and the map entry just before the allocated
                   9344:  *             range
                   9345:  *
                   9346:  *     Map must be locked.
                   9347:  */
                   9348: 
                   9349: kern_return_t
                   9350: vm_remap_range_allocate(
                   9351:        vm_map_t        map,
                   9352:        vm_offset_t     *address,       /* IN/OUT */
                   9353:        vm_size_t       size,
                   9354:        vm_offset_t     mask,
                   9355:        boolean_t       anywhere,
                   9356:        vm_map_entry_t  *map_entry)     /* OUT */
                   9357: {
                   9358:        register vm_map_entry_t entry;
                   9359:        register vm_offset_t    start;
                   9360:        register vm_offset_t    end;
                   9361:        kern_return_t           result = KERN_SUCCESS;
                   9362: 
                   9363:  StartAgain: ;
                   9364: 
                   9365:     start = *address;
                   9366: 
                   9367:     if (anywhere)
                   9368:     {
                   9369:        /*
                   9370:         *      Calculate the first possible address.
                   9371:         */
                   9372: 
                   9373:        if (start < map->min_offset)
                   9374:            start = map->min_offset;
                   9375:        if (start > map->max_offset)
                   9376:            return(KERN_NO_SPACE);
                   9377:                
                   9378:        /*
                   9379:         *      Look for the first possible address;
                   9380:         *      if there's already something at this
                   9381:         *      address, we have to start after it.
                   9382:         */
                   9383: 
                   9384:        assert(first_free_is_valid(map));
                   9385:        if (start == map->min_offset) {
                   9386:            if ((entry = map->first_free) != vm_map_to_entry(map))
                   9387:                start = entry->vme_end;
                   9388:        } else {
                   9389:            vm_map_entry_t      tmp_entry;
                   9390:            if (vm_map_lookup_entry(map, start, &tmp_entry))
                   9391:                start = tmp_entry->vme_end;
                   9392:            entry = tmp_entry;
                   9393:        }
                   9394:                
                   9395:        /*
                   9396:         *      In any case, the "entry" always precedes
                   9397:         *      the proposed new region throughout the
                   9398:         *      loop:
                   9399:         */
                   9400: 
                   9401:        while (TRUE) {
                   9402:            register vm_map_entry_t     next;
                   9403: 
                   9404:            /*
                   9405:             *  Find the end of the proposed new region.
                   9406:             *  Be sure we didn't go beyond the end, or
                   9407:             *  wrap around the address.
                   9408:             */
                   9409: 
                   9410:            end = ((start + mask) & ~mask);
                   9411:            if (end < start)
                   9412:                    return(KERN_NO_SPACE);
                   9413:            start = end;
                   9414:            end += size;
                   9415: 
                   9416:            if ((end > map->max_offset) || (end < start)) {
                   9417:                if (map->wait_for_space) {
                   9418:                    if (size <= (map->max_offset -
                   9419:                                 map->min_offset)) {
                   9420:                        assert_wait((event_t) map, THREAD_INTERRUPTIBLE);
                   9421:                        vm_map_unlock(map);
                   9422:                        thread_block((void (*)(void))0);
                   9423:                        vm_map_lock(map);
                   9424:                        goto StartAgain;
                   9425:                    }
                   9426:                }
                   9427:                
                   9428:                return(KERN_NO_SPACE);
                   9429:            }
                   9430: 
                   9431:            /*
                   9432:             *  If there are no more entries, we must win.
                   9433:             */
                   9434: 
                   9435:            next = entry->vme_next;
                   9436:            if (next == vm_map_to_entry(map))
                   9437:                break;
                   9438: 
                   9439:            /*
                   9440:             *  If there is another entry, it must be
                   9441:             *  after the end of the potential new region.
                   9442:             */
                   9443: 
                   9444:            if (next->vme_start >= end)
                   9445:                break;
                   9446: 
                   9447:            /*
                   9448:             *  Didn't fit -- move to the next entry.
                   9449:             */
                   9450: 
                   9451:            entry = next;
                   9452:            start = entry->vme_end;
                   9453:        }
                   9454:        *address = start;
                   9455:     } else {
                   9456:        vm_map_entry_t          temp_entry;
                   9457:        
                   9458:        /*
                   9459:         *      Verify that:
                   9460:         *              the address doesn't itself violate
                   9461:         *              the mask requirement.
                   9462:         */
                   9463: 
                   9464:        if ((start & mask) != 0)
                   9465:            return(KERN_NO_SPACE);
                   9466: 
                   9467: 
                   9468:        /*
                   9469:         *      ...     the address is within bounds
                   9470:         */
                   9471: 
                   9472:        end = start + size;
                   9473: 
                   9474:        if ((start < map->min_offset) ||
                   9475:            (end > map->max_offset) ||
                   9476:            (start >= end)) {
                   9477:            return(KERN_INVALID_ADDRESS);
                   9478:        }
                   9479: 
                   9480:        /*
                   9481:         *      ...     the starting address isn't allocated
                   9482:         */
                   9483: 
                   9484:        if (vm_map_lookup_entry(map, start, &temp_entry))
                   9485:            return(KERN_NO_SPACE);
                   9486: 
                   9487:        entry = temp_entry;
                   9488: 
                   9489:        /*
                   9490:         *      ...     the next region doesn't overlap the
                   9491:         *              end point.
                   9492:         */
                   9493: 
                   9494:        if ((entry->vme_next != vm_map_to_entry(map)) &&
                   9495:            (entry->vme_next->vme_start < end))
                   9496:            return(KERN_NO_SPACE);
                   9497:     }
                   9498:     *map_entry = entry;
                   9499:     return(KERN_SUCCESS);
                   9500: }
                   9501: 
                   9502: /*
                   9503:  *     vm_map_switch:
                   9504:  *
                   9505:  *     Set the address map for the current thr_act to the specified map
                   9506:  */
                   9507: 
                   9508: vm_map_t
                   9509: vm_map_switch(
                   9510:        vm_map_t        map)
                   9511: {
                   9512:        int             mycpu;
                   9513:        thread_act_t    thr_act = current_act();
                   9514:        vm_map_t        oldmap = thr_act->map;
                   9515: 
                   9516:        mp_disable_preemption();
                   9517:        mycpu = cpu_number();
                   9518: 
                   9519:        /*
                   9520:         *      Deactivate the current map and activate the requested map
                   9521:         */
                   9522:        PMAP_SWITCH_USER(thr_act, map, mycpu);
                   9523: 
                   9524:        mp_enable_preemption();
                   9525:        return(oldmap);
                   9526: }
                   9527: 
                   9528: 
                   9529: /*
                   9530:  *     Routine:        vm_map_write_user
                   9531:  *
                   9532:  *     Description:
                   9533:  *             Copy out data from a kernel space into space in the
                   9534:  *             destination map. The space must already exist in the
                   9535:  *             destination map.
                   9536:  *             NOTE:  This routine should only be called by threads
                   9537:  *             which can block on a page fault. i.e. kernel mode user
                   9538:  *             threads.
                   9539:  *
                   9540:  */
                   9541: kern_return_t
                   9542: vm_map_write_user(
                   9543:        vm_map_t        map,
                   9544:        vm_offset_t     src_addr,
                   9545:        vm_offset_t     dst_addr,
                   9546:        vm_size_t       size)
                   9547: {
                   9548:        thread_act_t    thr_act = current_act();
                   9549:        kern_return_t   kr = KERN_SUCCESS;
                   9550: 
                   9551:        if(thr_act->map == map) {
                   9552:                if (copyout((char *)src_addr, (char *)dst_addr, size)) {
                   9553:                        kr = KERN_INVALID_ADDRESS;
                   9554:                }
                   9555:        } else {
                   9556:                vm_map_t        oldmap;
                   9557: 
                   9558:                /* take on the identity of the target map while doing */
                   9559:                /* the transfer */
                   9560: 
                   9561:                vm_map_reference(map);
                   9562:                oldmap = vm_map_switch(map);
                   9563:                if (copyout((char *)src_addr, (char *)dst_addr, size)) {
                   9564:                        kr = KERN_INVALID_ADDRESS;
                   9565:                }
                   9566:                vm_map_switch(oldmap);
                   9567:                vm_map_deallocate(map);
                   9568:        }
                   9569:        return kr;
                   9570: }
                   9571: 
                   9572: /*
                   9573:  *     Routine:        vm_map_read_user
                   9574:  *
                   9575:  *     Description:
                   9576:  *             Copy in data from a user space source map into the
                   9577:  *             kernel map. The space must already exist in the
                   9578:  *             kernel map.
                   9579:  *             NOTE:  This routine should only be called by threads
                   9580:  *             which can block on a page fault. i.e. kernel mode user
                   9581:  *             threads.
                   9582:  *
                   9583:  */
                   9584: kern_return_t
                   9585: vm_map_read_user(
                   9586:        vm_map_t        map,
                   9587:        vm_offset_t     src_addr,
                   9588:        vm_offset_t     dst_addr,
                   9589:        vm_size_t       size)
                   9590: {
                   9591:        thread_act_t    thr_act = current_act();
                   9592:        kern_return_t   kr = KERN_SUCCESS;
                   9593: 
                   9594:        if(thr_act->map == map) {
                   9595:                if (copyin((char *)src_addr, (char *)dst_addr, size)) {
                   9596:                        kr = KERN_INVALID_ADDRESS;
                   9597:                }
                   9598:        } else {
                   9599:                vm_map_t        oldmap;
                   9600: 
                   9601:                /* take on the identity of the target map while doing */
                   9602:                /* the transfer */
                   9603: 
                   9604:                vm_map_reference(map);
                   9605:                oldmap = vm_map_switch(map);
                   9606:                if (copyin((char *)src_addr, (char *)dst_addr, size)) {
                   9607:                        kr = KERN_INVALID_ADDRESS;
                   9608:                }
                   9609:                vm_map_switch(oldmap);
                   9610:                vm_map_deallocate(map);
                   9611:        }
                   9612:        return kr;
                   9613: }
                   9614: 
                   9615: /*
                   9616:  * Export routines to other components for the things we access locally through
                   9617:  * macros.
                   9618:  */
                   9619: #undef current_map
                   9620: vm_map_t
                   9621: current_map(void)
                   9622: {
                   9623:        return (current_map_fast());
                   9624: }

unix.superglobalmegacorp.com

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