Annotation of XNU/osfmk/vm/vm_map.c, revision 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.