]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/vm/vm_user.c
xnu-2782.40.9.tar.gz
[apple/xnu.git] / osfmk / vm / vm_user.c
index a1f18add39aa57a7952c63af7de707082df70939..024140fb53562e8137fb76b73c08ee3894973366 100644 (file)
@@ -1,16 +1,19 @@
 /*
- * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
  * This file contains Original Code and/or Modifications of Original Code
  * as defined in and that are subject to the Apple Public Source License
  * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
  * 
  * The Original Code and all software distributed under the License are
  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
@@ -20,7 +23,7 @@
  * Please see the License for the specific language governing rights and
  * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  * @OSF_COPYRIGHT@
  *     User-exported virtual memory functions.
  */
 
+/*
+ * There are three implementations of the "XXX_allocate" functionality in
+ * the kernel: mach_vm_allocate (for any task on the platform), vm_allocate
+ * (for a task with the same address space size, especially the current task),
+ * and vm32_vm_allocate (for the specific case of a 32-bit task). vm_allocate
+ * in the kernel should only be used on the kernel_task. vm32_vm_allocate only
+ * makes sense on platforms where a user task can either be 32 or 64, or the kernel
+ * task can be 32 or 64. mach_vm_allocate makes sense everywhere, and is preferred
+ * for new code.
+ *
+ * The entrypoints into the kernel are more complex. All platforms support a
+ * mach_vm_allocate-style API (subsystem 4800) which operates with the largest
+ * size types for the platform. On platforms that only support U32/K32,
+ * subsystem 4800 is all you need. On platforms that support both U32 and U64,
+ * subsystem 3800 is used disambiguate the size of parameters, and they will
+ * always be 32-bit and call into the vm32_vm_allocate APIs. On non-U32/K32 platforms,
+ * the MIG glue should never call into vm_allocate directly, because the calling
+ * task and kernel_task are unlikely to use the same size parameters
+ *
+ * New VM call implementations should be added here and to mach_vm.defs
+ * (subsystem 4800), and use mach_vm_* "wide" types.
+ */
+
+#include <debug.h>
+
 #include <vm_cpm.h>
 #include <mach/boolean.h>
 #include <mach/kern_return.h>
 #include <mach/mach_types.h>   /* to get vm_address_t */
 #include <mach/memory_object.h>
 #include <mach/std_types.h>    /* to get pointer_t */
+#include <mach/upl.h>
 #include <mach/vm_attributes.h>
 #include <mach/vm_param.h>
 #include <mach/vm_statistics.h>
-#include <mach/vm_map_server.h>
 #include <mach/mach_syscalls.h>
 
-#include <mach/shared_memory_server.h>
-#include <vm/vm_shared_memory_server.h>
+#include <mach/host_priv_server.h>
+#include <mach/mach_vm_server.h>
+#include <mach/vm_map_server.h>
 
 #include <kern/host.h>
+#include <kern/kalloc.h>
 #include <kern/task.h>
 #include <kern/misc_protos.h>
+#include <vm/vm_fault.h>
 #include <vm/vm_map.h>
 #include <vm/vm_object.h>
 #include <vm/vm_page.h>
 #include <vm/memory_object.h>
 #include <vm/vm_pageout.h>
-
-__private_extern__ load_struct_t *
-lsf_remove_regions_mappings_lock(
-       shared_region_mapping_t region,
-       shared_region_task_mappings_t   sm_info,
-       int need_lock);
-
+#include <vm/vm_protos.h>
+#include <vm/vm_purgeable_internal.h>
 
 vm_size_t        upl_offset_to_pagelist = 0;
 
@@ -99,18 +125,24 @@ vm_size_t        upl_offset_to_pagelist = 0;
 ipc_port_t     dynamic_pager_control_port=NULL;
 
 /*
- *     vm_allocate allocates "zero fill" memory in the specfied
+ *     mach_vm_allocate allocates "zero fill" memory in the specfied
  *     map.
  */
 kern_return_t
-vm_allocate(
-       register vm_map_t       map,
-       register vm_offset_t    *addr,
-       register vm_size_t      size,
+mach_vm_allocate(
+       vm_map_t                map,
+       mach_vm_offset_t        *addr,
+       mach_vm_size_t  size,
        int                     flags)
 {
+       vm_map_offset_t map_addr;
+       vm_map_size_t   map_size;
        kern_return_t   result;
-       boolean_t       anywhere = VM_FLAGS_ANYWHERE & flags;
+       boolean_t       anywhere;
+
+       /* filter out any kernel-only flags */
+       if (flags & ~VM_FLAGS_USER_ALLOCATE)
+               return KERN_INVALID_ARGUMENT;
 
        if (map == VM_MAP_NULL)
                return(KERN_INVALID_ARGUMENT);
@@ -119,20 +151,104 @@ vm_allocate(
                return(KERN_SUCCESS);
        }
 
-       if (anywhere)
-               *addr = vm_map_min(map);
-       else
-               *addr = trunc_page_32(*addr);
-       size = round_page_32(size);
+       anywhere = ((VM_FLAGS_ANYWHERE & flags) != 0);
+       if (anywhere) {
+               /*
+                * No specific address requested, so start candidate address
+                * search at the minimum address in the map.  However, if that
+                * minimum is 0, bump it up by PAGE_SIZE.  We want to limit
+                * allocations of PAGEZERO to explicit requests since its
+                * normal use is to catch dereferences of NULL and many
+                * applications also treat pointers with a value of 0 as
+                * special and suddenly having address 0 contain useable
+                * memory would tend to confuse those applications.
+                */
+               map_addr = vm_map_min(map);
+               if (map_addr == 0)
+                       map_addr += VM_MAP_PAGE_SIZE(map);
+       } else
+               map_addr = vm_map_trunc_page(*addr,
+                                            VM_MAP_PAGE_MASK(map));
+       map_size = vm_map_round_page(size,
+                                    VM_MAP_PAGE_MASK(map));
+       if (map_size == 0) {
+         return(KERN_INVALID_ARGUMENT);
+       }
+
+       result = vm_map_enter(
+                       map,
+                       &map_addr,
+                       map_size,
+                       (vm_map_offset_t)0,
+                       flags,
+                       VM_OBJECT_NULL,
+                       (vm_object_offset_t)0,
+                       FALSE,
+                       VM_PROT_DEFAULT,
+                       VM_PROT_ALL,
+                       VM_INHERIT_DEFAULT);
+
+       *addr = map_addr;
+       return(result);
+}
+
+/*
+ *     vm_allocate 
+ *     Legacy routine that allocates "zero fill" memory in the specfied
+ *     map (which is limited to the same size as the kernel).
+ */
+kern_return_t
+vm_allocate(
+       vm_map_t        map,
+       vm_offset_t     *addr,
+       vm_size_t       size,
+       int             flags)
+{
+       vm_map_offset_t map_addr;
+       vm_map_size_t   map_size;
+       kern_return_t   result;
+       boolean_t       anywhere;
+
+       /* filter out any kernel-only flags */
+       if (flags & ~VM_FLAGS_USER_ALLOCATE)
+               return KERN_INVALID_ARGUMENT;
+
+       if (map == VM_MAP_NULL)
+               return(KERN_INVALID_ARGUMENT);
        if (size == 0) {
+               *addr = 0;
+               return(KERN_SUCCESS);
+       }
+
+       anywhere = ((VM_FLAGS_ANYWHERE & flags) != 0);
+       if (anywhere) {
+               /*
+                * No specific address requested, so start candidate address
+                * search at the minimum address in the map.  However, if that
+                * minimum is 0, bump it up by PAGE_SIZE.  We want to limit
+                * allocations of PAGEZERO to explicit requests since its
+                * normal use is to catch dereferences of NULL and many
+                * applications also treat pointers with a value of 0 as
+                * special and suddenly having address 0 contain useable
+                * memory would tend to confuse those applications.
+                */
+               map_addr = vm_map_min(map);
+               if (map_addr == 0)
+                       map_addr += VM_MAP_PAGE_SIZE(map);
+       } else
+               map_addr = vm_map_trunc_page(*addr,
+                                            VM_MAP_PAGE_MASK(map));
+       map_size = vm_map_round_page(size,
+                                    VM_MAP_PAGE_MASK(map));
+       if (map_size == 0) {
          return(KERN_INVALID_ARGUMENT);
        }
 
        result = vm_map_enter(
                        map,
-                       addr,
-                       size,
-                       (vm_offset_t)0,
+                       &map_addr,
+                       map_size,
+                       (vm_map_offset_t)0,
                        flags,
                        VM_OBJECT_NULL,
                        (vm_object_offset_t)0,
@@ -141,98 +257,293 @@ vm_allocate(
                        VM_PROT_ALL,
                        VM_INHERIT_DEFAULT);
 
+       *addr = CAST_DOWN(vm_offset_t, map_addr);
        return(result);
 }
 
 /*
- *     vm_deallocate deallocates the specified range of addresses in the
+ *     mach_vm_deallocate -
+ *     deallocates the specified range of addresses in the
  *     specified address map.
  */
 kern_return_t
+mach_vm_deallocate(
+       vm_map_t                map,
+       mach_vm_offset_t        start,
+       mach_vm_size_t  size)
+{
+       if ((map == VM_MAP_NULL) || (start + size < start))
+               return(KERN_INVALID_ARGUMENT);
+
+       if (size == (mach_vm_offset_t) 0)
+               return(KERN_SUCCESS);
+
+       return(vm_map_remove(map,
+                            vm_map_trunc_page(start,
+                                              VM_MAP_PAGE_MASK(map)),
+                            vm_map_round_page(start+size,
+                                              VM_MAP_PAGE_MASK(map)),
+                            VM_MAP_NO_FLAGS));
+}
+
+/*
+ *     vm_deallocate -
+ *     deallocates the specified range of addresses in the
+ *     specified address map (limited to addresses the same
+ *     size as the kernel).
+ */
+kern_return_t
 vm_deallocate(
        register vm_map_t       map,
        vm_offset_t             start,
        vm_size_t               size)
 {
-       if (map == VM_MAP_NULL)
+       if ((map == VM_MAP_NULL) || (start + size < start))
                return(KERN_INVALID_ARGUMENT);
 
        if (size == (vm_offset_t) 0)
                return(KERN_SUCCESS);
 
-       return(vm_map_remove(map, trunc_page_32(start),
-                            round_page_32(start+size), VM_MAP_NO_FLAGS));
+       return(vm_map_remove(map,
+                            vm_map_trunc_page(start,
+                                              VM_MAP_PAGE_MASK(map)),
+                            vm_map_round_page(start+size,
+                                              VM_MAP_PAGE_MASK(map)),
+                            VM_MAP_NO_FLAGS));
 }
 
 /*
- *     vm_inherit sets the inheritance of the specified range in the
+ *     mach_vm_inherit -
+ *     Sets the inheritance of the specified range in the
  *     specified map.
  */
 kern_return_t
+mach_vm_inherit(
+       vm_map_t                map,
+       mach_vm_offset_t        start,
+       mach_vm_size_t  size,
+       vm_inherit_t            new_inheritance)
+{
+       if ((map == VM_MAP_NULL) || (start + size < start) ||
+           (new_inheritance > VM_INHERIT_LAST_VALID))
+                return(KERN_INVALID_ARGUMENT);
+
+       if (size == 0)
+               return KERN_SUCCESS;
+
+       return(vm_map_inherit(map,
+                             vm_map_trunc_page(start,
+                                               VM_MAP_PAGE_MASK(map)),
+                             vm_map_round_page(start+size,
+                                               VM_MAP_PAGE_MASK(map)),
+                             new_inheritance));
+}
+
+/*
+ *     vm_inherit -
+ *     Sets the inheritance of the specified range in the
+ *     specified map (range limited to addresses
+ */
+kern_return_t
 vm_inherit(
        register vm_map_t       map,
        vm_offset_t             start,
        vm_size_t               size,
        vm_inherit_t            new_inheritance)
 {
-       if (map == VM_MAP_NULL)
-               return(KERN_INVALID_ARGUMENT);
-
-       if (new_inheritance > VM_INHERIT_LAST_VALID)
+       if ((map == VM_MAP_NULL) || (start + size < start) ||
+           (new_inheritance > VM_INHERIT_LAST_VALID))
                 return(KERN_INVALID_ARGUMENT);
 
+       if (size == 0)
+               return KERN_SUCCESS;
+
        return(vm_map_inherit(map,
-                             trunc_page_32(start),
-                             round_page_32(start+size),
+                             vm_map_trunc_page(start,
+                                               VM_MAP_PAGE_MASK(map)),
+                             vm_map_round_page(start+size,
+                                               VM_MAP_PAGE_MASK(map)),
                              new_inheritance));
 }
 
 /*
- *     vm_protect sets the protection of the specified range in the
+ *     mach_vm_protect -
+ *     Sets the protection of the specified range in the
  *     specified map.
  */
 
+kern_return_t
+mach_vm_protect(
+       vm_map_t                map,
+       mach_vm_offset_t        start,
+       mach_vm_size_t  size,
+       boolean_t               set_maximum,
+       vm_prot_t               new_protection)
+{
+       if ((map == VM_MAP_NULL) || (start + size < start) ||
+           (new_protection & ~(VM_PROT_ALL | VM_PROT_COPY)))
+               return(KERN_INVALID_ARGUMENT);
+
+       if (size == 0)
+               return KERN_SUCCESS;
+
+       return(vm_map_protect(map,
+                             vm_map_trunc_page(start,
+                                               VM_MAP_PAGE_MASK(map)),
+                             vm_map_round_page(start+size,
+                                               VM_MAP_PAGE_MASK(map)),
+                             new_protection,
+                             set_maximum));
+}
+
+/*
+ *     vm_protect -
+ *     Sets the protection of the specified range in the
+ *     specified map. Addressability of the range limited
+ *     to the same size as the kernel.
+ */
+
 kern_return_t
 vm_protect(
-       register vm_map_t       map,
+       vm_map_t                map,
        vm_offset_t             start,
        vm_size_t               size,
        boolean_t               set_maximum,
        vm_prot_t               new_protection)
 {
-       if ((map == VM_MAP_NULL) || 
-                       (new_protection & ~(VM_PROT_ALL | VM_PROT_COPY)))
+       if ((map == VM_MAP_NULL) || (start + size < start) ||
+           (new_protection & ~(VM_PROT_ALL | VM_PROT_COPY)))
                return(KERN_INVALID_ARGUMENT);
 
+       if (size == 0)
+               return KERN_SUCCESS;
+
        return(vm_map_protect(map,
-                             trunc_page_32(start),
-                             round_page_32(start+size),
+                             vm_map_trunc_page(start,
+                                               VM_MAP_PAGE_MASK(map)),
+                             vm_map_round_page(start+size,
+                                               VM_MAP_PAGE_MASK(map)),
                              new_protection,
                              set_maximum));
 }
 
 /*
+ * mach_vm_machine_attributes -
  * Handle machine-specific attributes for a mapping, such
  * as cachability, migrability, etc.
  */
 kern_return_t
+mach_vm_machine_attribute(
+       vm_map_t                        map,
+       mach_vm_address_t               addr,
+       mach_vm_size_t          size,
+       vm_machine_attribute_t  attribute,
+       vm_machine_attribute_val_t* value)              /* IN/OUT */
+{
+       if ((map == VM_MAP_NULL) || (addr + size < addr))
+               return(KERN_INVALID_ARGUMENT);
+
+       if (size == 0)
+               return KERN_SUCCESS;
+
+       return vm_map_machine_attribute(
+               map, 
+               vm_map_trunc_page(addr,
+                                 VM_MAP_PAGE_MASK(map)),
+               vm_map_round_page(addr+size,
+                                 VM_MAP_PAGE_MASK(map)),
+               attribute,
+               value);
+}
+
+/*
+ * vm_machine_attribute -
+ * Handle machine-specific attributes for a mapping, such
+ * as cachability, migrability, etc. Limited addressability
+ * (same range limits as for the native kernel map).
+ */
+kern_return_t
 vm_machine_attribute(
        vm_map_t        map,
-       vm_address_t    address,
+       vm_address_t    addr,
        vm_size_t       size,
        vm_machine_attribute_t  attribute,
        vm_machine_attribute_val_t* value)              /* IN/OUT */
 {
+       if ((map == VM_MAP_NULL) || (addr + size < addr))
+               return(KERN_INVALID_ARGUMENT);
+
+       if (size == 0)
+               return KERN_SUCCESS;
+
+       return vm_map_machine_attribute(
+               map, 
+               vm_map_trunc_page(addr,
+                                 VM_MAP_PAGE_MASK(map)),
+               vm_map_round_page(addr+size,
+                                 VM_MAP_PAGE_MASK(map)),
+               attribute,
+               value);
+}
+
+/*
+ * mach_vm_read -
+ * Read/copy a range from one address space and return it to the caller.
+ *
+ * It is assumed that the address for the returned memory is selected by
+ * the IPC implementation as part of receiving the reply to this call.
+ * If IPC isn't used, the caller must deal with the vm_map_copy_t object
+ * that gets returned.
+ * 
+ * JMM - because of mach_msg_type_number_t, this call is limited to a
+ * single 4GB region at this time.
+ *
+ */
+kern_return_t
+mach_vm_read(
+       vm_map_t                map,
+       mach_vm_address_t       addr,
+       mach_vm_size_t  size,
+       pointer_t               *data,
+       mach_msg_type_number_t  *data_size)
+{
+       kern_return_t   error;
+       vm_map_copy_t   ipc_address;
+
        if (map == VM_MAP_NULL)
                return(KERN_INVALID_ARGUMENT);
 
-       return vm_map_machine_attribute(map, address, size, attribute, value);
+       if ((mach_msg_type_number_t) size != size)
+               return KERN_INVALID_ARGUMENT;
+       
+       error = vm_map_copyin(map,
+                       (vm_map_address_t)addr,
+                       (vm_map_size_t)size,
+                       FALSE,  /* src_destroy */
+                       &ipc_address);
+
+       if (KERN_SUCCESS == error) {
+               *data = (pointer_t) ipc_address;
+               *data_size = (mach_msg_type_number_t) size;
+               assert(*data_size == size);
+       }
+       return(error);
 }
 
+/*
+ * vm_read -
+ * Read/copy a range from one address space and return it to the caller.
+ * Limited addressability (same range limits as for the native kernel map).
+ * 
+ * It is assumed that the address for the returned memory is selected by
+ * the IPC implementation as part of receiving the reply to this call.
+ * If IPC isn't used, the caller must deal with the vm_map_copy_t object
+ * that gets returned.
+ */
 kern_return_t
 vm_read(
        vm_map_t                map,
-       vm_address_t            address,
+       vm_address_t            addr,
        vm_size_t               size,
        pointer_t               *data,
        mach_msg_type_number_t  *data_size)
@@ -243,442 +554,415 @@ vm_read(
        if (map == VM_MAP_NULL)
                return(KERN_INVALID_ARGUMENT);
 
-       if ((error = vm_map_copyin(map,
-                               address,
-                               size,
-                               FALSE,  /* src_destroy */
-                               &ipc_address)) == KERN_SUCCESS) {
+       if (size > (unsigned)(mach_msg_type_number_t) -1) {
+               /*
+                * The kernel could handle a 64-bit "size" value, but
+                * it could not return the size of the data in "*data_size"
+                * without overflowing.
+                * Let's reject this "size" as invalid.
+                */
+               return KERN_INVALID_ARGUMENT;
+       }
+
+       error = vm_map_copyin(map,
+                       (vm_map_address_t)addr,
+                       (vm_map_size_t)size,
+                       FALSE,  /* src_destroy */
+                       &ipc_address);
+
+       if (KERN_SUCCESS == error) {
                *data = (pointer_t) ipc_address;
-               *data_size = size;
+               *data_size = (mach_msg_type_number_t) size;
+               assert(*data_size == size);
        }
        return(error);
 }
 
+/* 
+ * mach_vm_read_list -
+ * Read/copy a list of address ranges from specified map.
+ *
+ * MIG does not know how to deal with a returned array of
+ * vm_map_copy_t structures, so we have to do the copyout
+ * manually here.
+ */
 kern_return_t
-vm_read_list(
-       vm_map_t                map,
-       vm_read_entry_t         data_list,
-       mach_msg_type_number_t  count)
+mach_vm_read_list(
+       vm_map_t                        map,
+       mach_vm_read_entry_t            data_list,
+       natural_t                       count)
 {
        mach_msg_type_number_t  i;
        kern_return_t   error;
-       vm_map_copy_t   ipc_address;
+       vm_map_copy_t   copy;
 
-       if (map == VM_MAP_NULL)
+       if (map == VM_MAP_NULL ||
+           count > VM_MAP_ENTRY_MAX)
                return(KERN_INVALID_ARGUMENT);
 
+       error = KERN_SUCCESS;
        for(i=0; i<count; i++) {
-               error = vm_map_copyin(map,
-                               data_list[i].address,
-                               data_list[i].size,
-                               FALSE,  /* src_destroy */
-                               &ipc_address);
-               if(error != KERN_SUCCESS) {
-                       data_list[i].address = (vm_address_t)0;
-                       data_list[i].size = (vm_size_t)0;
-                       break;
-               }
-               if(data_list[i].size != 0) {
-                       error = vm_map_copyout(current_task()->map, 
-                                               &(data_list[i].address),
-                                                (vm_map_copy_t) ipc_address);
-                       if(error != KERN_SUCCESS) {
-                               data_list[i].address = (vm_address_t)0;
-                               data_list[i].size = (vm_size_t)0;
-                               break;
+               vm_map_address_t map_addr;
+               vm_map_size_t map_size;
+
+               map_addr = (vm_map_address_t)(data_list[i].address);
+               map_size = (vm_map_size_t)(data_list[i].size);
+
+               if(map_size != 0) {
+                       error = vm_map_copyin(map,
+                                       map_addr,
+                                       map_size,
+                                       FALSE,  /* src_destroy */
+                                       &copy);
+                       if (KERN_SUCCESS == error) {
+                               error = vm_map_copyout(
+                                               current_task()->map, 
+                                               &map_addr,
+                                               copy);
+                               if (KERN_SUCCESS == error) {
+                                       data_list[i].address = map_addr;
+                                       continue;
+                               }
+                               vm_map_copy_discard(copy);
                        }
                }
+               data_list[i].address = (mach_vm_address_t)0;
+               data_list[i].size = (mach_vm_size_t)0;
        }
        return(error);
 }
 
-/*
- * This routine reads from the specified map and overwrites part of the current
- * activation's map.  In making an assumption that the current thread is local,
- * it is no longer cluster-safe without a fully supportive local proxy thread/
- * task (but we don't support cluster's anymore so this is moot).
+/* 
+ * vm_read_list -
+ * Read/copy a list of address ranges from specified map.
+ *
+ * MIG does not know how to deal with a returned array of
+ * vm_map_copy_t structures, so we have to do the copyout
+ * manually here.
+ *
+ * The source and destination ranges are limited to those
+ * that can be described with a vm_address_t (i.e. same
+ * size map as the kernel).
+ *
+ * JMM - If the result of the copyout is an address range
+ * that cannot be described with a vm_address_t (i.e. the
+ * caller had a larger address space but used this call
+ * anyway), it will result in a truncated address being
+ * returned (and a likely confused caller).
  */
 
-#define VM_OVERWRITE_SMALL 512
-
 kern_return_t
-vm_read_overwrite(
-                 vm_map_t      map,
-                 vm_address_t  address,
-                 vm_size_t     size,
-                 vm_address_t  data,
-                 vm_size_t     *data_size)
-{
-       struct {
-           long        align;
-           char        buf[VM_OVERWRITE_SMALL];
-       } inbuf;
-       vm_map_t        oldmap;
-       kern_return_t   error = KERN_SUCCESS;
+vm_read_list(
+       vm_map_t                map,
+       vm_read_entry_t data_list,
+       natural_t               count)
+{
+       mach_msg_type_number_t  i;
+       kern_return_t   error;
        vm_map_copy_t   copy;
 
-       if (map == VM_MAP_NULL)
+       if (map == VM_MAP_NULL ||
+           count > VM_MAP_ENTRY_MAX)
                return(KERN_INVALID_ARGUMENT);
 
-       if (size <= VM_OVERWRITE_SMALL) {
-               if(vm_map_read_user(map, (vm_offset_t)address, 
-                                       (vm_offset_t)&inbuf, size)) {
-                       error = KERN_INVALID_ADDRESS;
-               } else {
-                       if(vm_map_write_user(current_map(), 
-                               (vm_offset_t)&inbuf, (vm_offset_t)data, size))
-                       error = KERN_INVALID_ADDRESS;
-               }
-       }
-       else {
-               if ((error = vm_map_copyin(map,
-                                       address,
-                                       size,
+       error = KERN_SUCCESS;
+       for(i=0; i<count; i++) {
+               vm_map_address_t map_addr;
+               vm_map_size_t map_size;
+
+               map_addr = (vm_map_address_t)(data_list[i].address);
+               map_size = (vm_map_size_t)(data_list[i].size);
+
+               if(map_size != 0) {
+                       error = vm_map_copyin(map,
+                                       map_addr,
+                                       map_size,
                                        FALSE,  /* src_destroy */
-                                       &copy)) == KERN_SUCCESS) {
-                       if ((error = vm_map_copy_overwrite(
-                                       current_act()->map,
-                                       data, 
-                                       copy,
-                                       FALSE)) == KERN_SUCCESS) {
-                       }
-                       else {
+                                       &copy);
+                       if (KERN_SUCCESS == error) {
+                               error = vm_map_copyout(current_task()->map, 
+                                               &map_addr,
+                                               copy);
+                               if (KERN_SUCCESS == error) {
+                                       data_list[i].address =
+                                               CAST_DOWN(vm_offset_t, map_addr);
+                                       continue;
+                               }
                                vm_map_copy_discard(copy);
                        }
                }
+               data_list[i].address = (mach_vm_address_t)0;
+               data_list[i].size = (mach_vm_size_t)0;
        }
-       *data_size = size;
        return(error);
 }
 
+/*
+ * mach_vm_read_overwrite -
+ * Overwrite a range of the current map with data from the specified
+ * map/address range.
+ * 
+ * In making an assumption that the current thread is local, it is
+ * no longer cluster-safe without a fully supportive local proxy
+ * thread/task (but we don't support cluster's anymore so this is moot).
+ */
 
-
-
-/*ARGSUSED*/
 kern_return_t
-vm_write(
+mach_vm_read_overwrite(
        vm_map_t                map,
-       vm_address_t            address,
-       vm_offset_t             data,
-       mach_msg_type_number_t  size)
+       mach_vm_address_t       address,
+       mach_vm_size_t  size,
+       mach_vm_address_t       data,
+       mach_vm_size_t  *data_size)
 {
+       kern_return_t   error;
+       vm_map_copy_t   copy;
+
        if (map == VM_MAP_NULL)
-               return KERN_INVALID_ARGUMENT;
+               return(KERN_INVALID_ARGUMENT);
+
+       error = vm_map_copyin(map, (vm_map_address_t)address,
+                               (vm_map_size_t)size, FALSE, &copy);
 
-       return vm_map_copy_overwrite(map, address, (vm_map_copy_t) data,
-                                    FALSE /* interruptible XXX */);
+       if (KERN_SUCCESS == error) {
+               error = vm_map_copy_overwrite(current_thread()->map,
+                                       (vm_map_address_t)data, 
+                                       copy, FALSE);
+               if (KERN_SUCCESS == error) {
+                       *data_size = size;
+                       return error;
+               }
+               vm_map_copy_discard(copy);
+       }
+       return(error);
 }
 
+/*
+ * vm_read_overwrite -
+ * Overwrite a range of the current map with data from the specified
+ * map/address range.
+ * 
+ * This routine adds the additional limitation that the source and
+ * destination ranges must be describable with vm_address_t values
+ * (i.e. the same size address spaces as the kernel, or at least the
+ * the ranges are in that first portion of the respective address
+ * spaces).
+ */
+
 kern_return_t
-vm_copy(
+vm_read_overwrite(
        vm_map_t        map,
-       vm_address_t    source_address,
+       vm_address_t    address,
        vm_size_t       size,
-       vm_address_t    dest_address)
+       vm_address_t    data,
+       vm_size_t       *data_size)
 {
-       vm_map_copy_t copy;
-       kern_return_t kr;
+       kern_return_t   error;
+       vm_map_copy_t   copy;
 
        if (map == VM_MAP_NULL)
-               return KERN_INVALID_ARGUMENT;
+               return(KERN_INVALID_ARGUMENT);
 
-       kr = vm_map_copyin(map, source_address, size,
-                          FALSE, &copy);
-       if (kr != KERN_SUCCESS)
-               return kr;
+       error = vm_map_copyin(map, (vm_map_address_t)address,
+                               (vm_map_size_t)size, FALSE, &copy);
 
-       kr = vm_map_copy_overwrite(map, dest_address, copy,
-                                  FALSE /* interruptible XXX */);
-       if (kr != KERN_SUCCESS) {
+       if (KERN_SUCCESS == error) {
+               error = vm_map_copy_overwrite(current_thread()->map,
+                                       (vm_map_address_t)data, 
+                                       copy, FALSE);
+               if (KERN_SUCCESS == error) {
+                       *data_size = size;
+                       return error;
+               }
                vm_map_copy_discard(copy);
-               return kr;
        }
-
-       return KERN_SUCCESS;
+       return(error);
 }
 
+
 /*
- *     Routine:        vm_map
+ * mach_vm_write -
+ * Overwrite the specified address range with the data provided
+ * (from the current map).
  */
 kern_return_t
-vm_map_64(
-       vm_map_t                target_map,
-       vm_offset_t             *address,
-       vm_size_t               initial_size,
-       vm_offset_t             mask,
-       int                     flags,
-       ipc_port_t              port,
-       vm_object_offset_t      offset,
-       boolean_t               copy,
-       vm_prot_t               cur_protection,
-       vm_prot_t               max_protection,
-       vm_inherit_t            inheritance)
+mach_vm_write(
+       vm_map_t                        map,
+       mach_vm_address_t               address,
+       pointer_t                       data,
+       __unused mach_msg_type_number_t size)
 {
-       register
-       vm_object_t             object;
-       vm_prot_t               prot;
-       vm_object_size_t        size = (vm_object_size_t)initial_size;
-       kern_return_t           result;
+       if (map == VM_MAP_NULL)
+               return KERN_INVALID_ARGUMENT;
 
-       /*
-        * Check arguments for validity
-        */
-       if ((target_map == VM_MAP_NULL) ||
-               (cur_protection & ~VM_PROT_ALL) ||
-               (max_protection & ~VM_PROT_ALL) ||
-               (inheritance > VM_INHERIT_LAST_VALID) ||
-               size == 0)
-               return(KERN_INVALID_ARGUMENT);
+       return vm_map_copy_overwrite(map, (vm_map_address_t)address,
+               (vm_map_copy_t) data, FALSE /* interruptible XXX */);
+}
 
-       /*
-        * Find the vm object (if any) corresponding to this port.
-        */
-       if (!IP_VALID(port)) {
-               object = VM_OBJECT_NULL;
-               offset = 0;
-               copy = FALSE;
-       } else if (ip_kotype(port) == IKOT_NAMED_ENTRY) {
-               vm_named_entry_t        named_entry;
-
-               named_entry = (vm_named_entry_t)port->ip_kobject;
-               /* a few checks to make sure user is obeying rules */
-               if(size == 0) {
-                       if(offset >= named_entry->size)
-                               return(KERN_INVALID_RIGHT);
-                       size = named_entry->size - offset;
-               }
-               if((named_entry->protection & max_protection) != max_protection)
-                       return(KERN_INVALID_RIGHT);
-               if((named_entry->protection & cur_protection) != cur_protection)
-                       return(KERN_INVALID_RIGHT);
-               if(named_entry->size < (offset + size))
-                       return(KERN_INVALID_ARGUMENT);
+/*
+ * vm_write -
+ * Overwrite the specified address range with the data provided
+ * (from the current map).
+ *
+ * The addressability of the range of addresses to overwrite is
+ * limited bu the use of a vm_address_t (same size as kernel map).
+ * Either the target map is also small, or the range is in the
+ * low addresses within it.
+ */
+kern_return_t
+vm_write(
+       vm_map_t                        map,
+       vm_address_t                    address,
+       pointer_t                       data,
+       __unused mach_msg_type_number_t size)
+{
+       if (map == VM_MAP_NULL)
+               return KERN_INVALID_ARGUMENT;
 
-               /* the callers parameter offset is defined to be the */
-               /* offset from beginning of named entry offset in object */
-               offset = offset + named_entry->offset;
-               
-               named_entry_lock(named_entry);
-               if(named_entry->is_sub_map) {
-                       vm_map_entry_t          map_entry;
+       return vm_map_copy_overwrite(map, (vm_map_address_t)address,
+               (vm_map_copy_t) data, FALSE /* interruptible XXX */);
+}
 
-                       named_entry_unlock(named_entry);
-                       *address = trunc_page_32(*address);
-                       size = round_page_64(size);
-                       vm_object_reference(vm_submap_object);
-                       if ((result = vm_map_enter(target_map,
-                               address, size, mask, flags,
-                               vm_submap_object, 0,
-                               FALSE,
-                               cur_protection, max_protection, inheritance
-                               )) != KERN_SUCCESS) {
-                                       vm_object_deallocate(vm_submap_object);
-                       } else {
-                               char    alias;
-
-                               VM_GET_FLAGS_ALIAS(flags, alias);
-                               if ((alias == VM_MEMORY_SHARED_PMAP) &&
-                                       !copy) {
-                                       vm_map_submap(target_map, *address, 
-                                               (*address) + size, 
-                                               named_entry->backing.map,
-                                               (vm_offset_t)offset, TRUE);
-                               } else {
-                                       vm_map_submap(target_map, *address, 
-                                               (*address) + size, 
-                                               named_entry->backing.map,
-                                               (vm_offset_t)offset, FALSE);
-                               }
-                               if(copy) {
-                                       if(vm_map_lookup_entry(
-                                          target_map, *address, &map_entry)) {
-                                               map_entry->needs_copy = TRUE;
-                                       }
-                               }
-                       }
-                       return(result);
-
-               } else if(named_entry->object) {
-                       /* This is the case where we are going to map */
-                       /* an already mapped object.  If the object is */
-                       /* not ready it is internal.  An external     */
-                       /* object cannot be mapped until it is ready  */
-                       /* we can therefore avoid the ready check     */
-                       /* in this case.  */
-                       named_entry_unlock(named_entry);
-                       vm_object_reference(named_entry->object);
-                       object = named_entry->object;
-               } else {
-                       unsigned int            access;
-                       vm_prot_t               protections;
-                       unsigned int            wimg_mode;
-                       boolean_t       cache_attr;
-
-                       protections = named_entry->protection 
-                                                       & VM_PROT_ALL;
-                       access = GET_MAP_MEM(named_entry->protection);
-
-                       object = vm_object_enter(
-                               named_entry->backing.pager, 
-                               named_entry->size, 
-                               named_entry->internal, 
-                               FALSE,
-                               FALSE);
-                       if (object == VM_OBJECT_NULL) {
-                               named_entry_unlock(named_entry);
-                               return(KERN_INVALID_OBJECT);
-                       }
+/*
+ * mach_vm_copy -
+ * Overwrite one range of the specified map with the contents of
+ * another range within that same map (i.e. both address ranges
+ * are "over there").
+ */
+kern_return_t
+mach_vm_copy(
+       vm_map_t                map,
+       mach_vm_address_t       source_address,
+       mach_vm_size_t  size,
+       mach_vm_address_t       dest_address)
+{
+       vm_map_copy_t copy;
+       kern_return_t kr;
 
-                       vm_object_lock(object);
+       if (map == VM_MAP_NULL)
+               return KERN_INVALID_ARGUMENT;
 
-                       /* create an extra ref for the named entry */
-                       vm_object_reference_locked(object);
-                       named_entry->object = object;
-                       named_entry_unlock(named_entry);
+       kr = vm_map_copyin(map, (vm_map_address_t)source_address,
+                          (vm_map_size_t)size, FALSE, &copy);
 
-                       wimg_mode = object->wimg_bits;
-                       if(access == MAP_MEM_IO) {
-                               wimg_mode = VM_WIMG_IO;
-                       } else if (access == MAP_MEM_COPYBACK) {
-                               wimg_mode = VM_WIMG_USE_DEFAULT;
-                       } else if (access == MAP_MEM_WTHRU) {
-                               wimg_mode = VM_WIMG_WTHRU;
-                       } else if (access == MAP_MEM_WCOMB) {
-                               wimg_mode = VM_WIMG_WCOMB;
-                       }
-                       if ((wimg_mode == VM_WIMG_IO)
-                               || (wimg_mode == VM_WIMG_WCOMB))
-                               cache_attr = TRUE;
-                       else 
-                               cache_attr = FALSE;
-
-                       if (named_entry->backing.pager) {
-                               /* wait for object (if any) to be ready */
-                               while (!object->pager_ready) {
-                                       vm_object_wait(object,
-                                                  VM_OBJECT_EVENT_PAGER_READY,
-                                                  THREAD_UNINT);
-                                       vm_object_lock(object);
-                               }
-                       }
-                       if(object->wimg_bits != wimg_mode) {
-                               vm_page_t p;
-
-                               vm_object_paging_wait(object, THREAD_UNINT);
-
-                               object->wimg_bits = wimg_mode;
-                               queue_iterate(&object->memq, p, vm_page_t, listq) {
-                                       if (!p->fictitious) {
-                                               pmap_page_protect(
-                                                       p->phys_page, 
-                                                       VM_PROT_NONE);
-                                               if(cache_attr)
-                                                       pmap_sync_caches_phys(
-                                                               p->phys_page);
-                                       }
-                               }
-                       }
-                       object->true_share = TRUE;
-                       if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC)
-                               object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
-                       vm_object_unlock(object);
-               }
-       } else if (ip_kotype(port) == IKOT_MEMORY_OBJECT) {
-               /*
-                * JMM - This is temporary until we unify named entries
-                * and raw memory objects.
-                *
-                * Detected fake ip_kotype for a memory object.  In
-                * this case, the port isn't really a port at all, but
-                * instead is just a raw memory object.
-                */
-                
-               if ((object = vm_object_enter((memory_object_t)port,
-                                             size, FALSE, FALSE, FALSE))
-                       == VM_OBJECT_NULL)
-                       return(KERN_INVALID_OBJECT);
+       if (KERN_SUCCESS == kr) {
+               kr = vm_map_copy_overwrite(map,
+                               (vm_map_address_t)dest_address,
+                               copy, FALSE /* interruptible XXX */);
 
-               /* wait for object (if any) to be ready */
-               if (object != VM_OBJECT_NULL) {
-                       if(object == kernel_object) {
-                               printf("Warning: Attempt to map kernel object"
-                                       " by a non-private kernel entity\n");
-                               return(KERN_INVALID_OBJECT);
-                       }
-                       vm_object_lock(object);
-                       while (!object->pager_ready) {
-                               vm_object_wait(object,
-                                       VM_OBJECT_EVENT_PAGER_READY,
-                                       THREAD_UNINT);
-                               vm_object_lock(object);
-                       }
-                       vm_object_unlock(object);
-               }
-       } else {
-               return (KERN_INVALID_OBJECT);
+               if (KERN_SUCCESS != kr)
+                       vm_map_copy_discard(copy);
        }
+       return kr;
+}
+
+kern_return_t
+vm_copy(
+       vm_map_t        map,
+       vm_address_t    source_address,
+       vm_size_t       size,
+       vm_address_t    dest_address)
+{
+       vm_map_copy_t copy;
+       kern_return_t kr;
 
-       *address = trunc_page_32(*address);
-       size = round_page_64(size);
+       if (map == VM_MAP_NULL)
+               return KERN_INVALID_ARGUMENT;
 
-       /*
-        *      Perform the copy if requested
-        */
+       kr = vm_map_copyin(map, (vm_map_address_t)source_address,
+                          (vm_map_size_t)size, FALSE, &copy);
 
-       if (copy) {
-               vm_object_t             new_object;
-               vm_object_offset_t      new_offset;
+       if (KERN_SUCCESS == kr) {
+               kr = vm_map_copy_overwrite(map,
+                               (vm_map_address_t)dest_address,
+                               copy, FALSE /* interruptible XXX */);
 
-               result = vm_object_copy_strategically(object, offset, size,
-                               &new_object, &new_offset,
-                               &copy);
+               if (KERN_SUCCESS != kr)
+                       vm_map_copy_discard(copy);
+       }
+       return kr;
+}
 
+/*
+ * mach_vm_map -
+ * Map some range of an object into an address space.
+ *
+ * The object can be one of several types of objects:
+ *     NULL - anonymous memory
+ *     a named entry - a range within another address space
+ *                     or a range within a memory object
+ *     a whole memory object
+ *
+ */
+kern_return_t
+mach_vm_map(
+       vm_map_t                target_map,
+       mach_vm_offset_t        *address,
+       mach_vm_size_t  initial_size,
+       mach_vm_offset_t        mask,
+       int                     flags,
+       ipc_port_t              port,
+       vm_object_offset_t      offset,
+       boolean_t               copy,
+       vm_prot_t               cur_protection,
+       vm_prot_t               max_protection,
+       vm_inherit_t            inheritance)
+{
+       kern_return_t           kr;
+       vm_map_offset_t         vmmaddr;
 
-               if (result == KERN_MEMORY_RESTART_COPY) {
-                       boolean_t success;
-                       boolean_t src_needs_copy;
+       vmmaddr = (vm_map_offset_t) *address;
 
-                       /*
-                        * XXX
-                        * We currently ignore src_needs_copy.
-                        * This really is the issue of how to make
-                        * MEMORY_OBJECT_COPY_SYMMETRIC safe for
-                        * non-kernel users to use. Solution forthcoming.
-                        * In the meantime, since we don't allow non-kernel
-                        * memory managers to specify symmetric copy,
-                        * we won't run into problems here.
-                        */
-                       new_object = object;
-                       new_offset = offset;
-                       success = vm_object_copy_quickly(&new_object,
-                                                        new_offset, size,
-                                                        &src_needs_copy,
-                                                        &copy);
-                       assert(success);
-                       result = KERN_SUCCESS;
-               }
-               /*
-                *      Throw away the reference to the
-                *      original object, as it won't be mapped.
-                */
+       /* filter out any kernel-only flags */
+       if (flags & ~VM_FLAGS_USER_MAP)
+               return KERN_INVALID_ARGUMENT;
 
-               vm_object_deallocate(object);
+       kr = vm_map_enter_mem_object(target_map,
+                                      &vmmaddr,
+                                      initial_size,
+                                      mask,
+                                      flags,
+                                      port,
+                                      offset,
+                                      copy,
+                                      cur_protection,
+                                      max_protection,
+                                      inheritance);
+
+       *address = vmmaddr;
+       return kr;
+}
 
-               if (result != KERN_SUCCESS)
-                       return (result);
 
-               object = new_object;
-               offset = new_offset;
-       }
+/* legacy interface */
+kern_return_t
+vm_map_64(
+       vm_map_t                target_map,
+       vm_offset_t             *address,
+       vm_size_t               size,
+       vm_offset_t             mask,
+       int                     flags,
+       ipc_port_t              port,
+       vm_object_offset_t      offset,
+       boolean_t               copy,
+       vm_prot_t               cur_protection,
+       vm_prot_t               max_protection,
+       vm_inherit_t            inheritance)
+{
+       mach_vm_address_t map_addr;
+       mach_vm_size_t map_size;
+       mach_vm_offset_t map_mask;
+       kern_return_t kr;
 
-       if ((result = vm_map_enter(target_map,
-                               address, size, mask, flags,
-                               object, offset,
-                               copy,
-                               cur_protection, max_protection, inheritance
-                               )) != KERN_SUCCESS)
-       vm_object_deallocate(object);
-       return(result);
+       map_addr = (mach_vm_address_t)*address;
+       map_size = (mach_vm_size_t)size;
+       map_mask = (mach_vm_offset_t)mask;
+
+       kr = mach_vm_map(target_map, &map_addr, map_size, map_mask, flags,
+                        port, offset, copy, 
+                        cur_protection, max_protection, inheritance);
+       *address = CAST_DOWN(vm_offset_t, map_addr);
+       return kr;
 }
 
 /* temporary, until world build */
@@ -696,18 +980,180 @@ vm_map(
        vm_prot_t               max_protection,
        vm_inherit_t            inheritance)
 {
-       return vm_map_64(target_map, address, size, mask, flags, 
-                       port, (vm_object_offset_t)offset, copy,
-                       cur_protection, max_protection, inheritance);
+       mach_vm_address_t map_addr;
+       mach_vm_size_t map_size;
+       mach_vm_offset_t map_mask;
+       vm_object_offset_t obj_offset;
+       kern_return_t kr;
+
+       map_addr = (mach_vm_address_t)*address;
+       map_size = (mach_vm_size_t)size;
+       map_mask = (mach_vm_offset_t)mask;
+       obj_offset = (vm_object_offset_t)offset;
+
+       kr = mach_vm_map(target_map, &map_addr, map_size, map_mask, flags,
+                        port, obj_offset, copy, 
+                        cur_protection, max_protection, inheritance);
+       *address = CAST_DOWN(vm_offset_t, map_addr);
+       return kr;
+}
+
+/*
+ * mach_vm_remap -
+ * Remap a range of memory from one task into another,
+ * to another address range within the same task, or
+ * over top of itself (with altered permissions and/or
+ * as an in-place copy of itself).
+ */
+
+kern_return_t
+mach_vm_remap(
+       vm_map_t                target_map,
+       mach_vm_offset_t        *address,
+       mach_vm_size_t  size,
+       mach_vm_offset_t        mask,
+       int                     flags,
+       vm_map_t                src_map,
+       mach_vm_offset_t        memory_address,
+       boolean_t               copy,
+       vm_prot_t               *cur_protection,
+       vm_prot_t               *max_protection,
+       vm_inherit_t            inheritance)
+{
+       vm_map_offset_t         map_addr;
+       kern_return_t           kr;
+
+       if (VM_MAP_NULL == target_map || VM_MAP_NULL == src_map)
+               return KERN_INVALID_ARGUMENT;
+
+       /* filter out any kernel-only flags */
+       if (flags & ~VM_FLAGS_USER_REMAP)
+               return KERN_INVALID_ARGUMENT;
+
+       map_addr = (vm_map_offset_t)*address;
+
+       kr = vm_map_remap(target_map,
+                         &map_addr,
+                         size,
+                         mask,
+                         flags,
+                         src_map,
+                         memory_address,
+                         copy,
+                         cur_protection,
+                         max_protection,
+                         inheritance);
+       *address = map_addr;
+       return kr;
 }
 
+/*
+ * vm_remap -
+ * Remap a range of memory from one task into another,
+ * to another address range within the same task, or
+ * over top of itself (with altered permissions and/or
+ * as an in-place copy of itself).
+ *
+ * The addressability of the source and target address
+ * range is limited by the size of vm_address_t (in the
+ * kernel context).
+ */
+kern_return_t
+vm_remap(
+       vm_map_t                target_map,
+       vm_offset_t             *address,
+       vm_size_t               size,
+       vm_offset_t             mask,
+       int                     flags,
+       vm_map_t                src_map,
+       vm_offset_t             memory_address,
+       boolean_t               copy,
+       vm_prot_t               *cur_protection,
+       vm_prot_t               *max_protection,
+       vm_inherit_t            inheritance)
+{
+       vm_map_offset_t         map_addr;
+       kern_return_t           kr;
+
+       if (VM_MAP_NULL == target_map || VM_MAP_NULL == src_map)
+               return KERN_INVALID_ARGUMENT;
+
+       /* filter out any kernel-only flags */
+       if (flags & ~VM_FLAGS_USER_REMAP)
+               return KERN_INVALID_ARGUMENT;
+
+       map_addr = (vm_map_offset_t)*address;
+
+       kr = vm_map_remap(target_map,
+                         &map_addr,
+                         size,
+                         mask,
+                         flags,
+                         src_map,
+                         memory_address,
+                         copy,
+                         cur_protection,
+                         max_protection,
+                         inheritance);
+       *address = CAST_DOWN(vm_offset_t, map_addr);
+       return kr;
+}
 
 /*
- * NOTE: this routine (and this file) will no longer require mach_host_server.h
- * when vm_wire is changed to use ledgers.
+ * NOTE: these routine (and this file) will no longer require mach_host_server.h
+ * when mach_vm_wire and vm_wire are changed to use ledgers.
  */
 #include <mach/mach_host_server.h>
 /*
+ *     mach_vm_wire
+ *     Specify that the range of the virtual address space
+ *     of the target task must not cause page faults for
+ *     the indicated accesses.
+ *
+ *     [ To unwire the pages, specify VM_PROT_NONE. ]
+ */
+kern_return_t
+mach_vm_wire(
+       host_priv_t             host_priv,
+       vm_map_t                map,
+       mach_vm_offset_t        start,
+       mach_vm_size_t  size,
+       vm_prot_t               access)
+{
+       kern_return_t           rc;
+
+       if (host_priv == HOST_PRIV_NULL)
+               return KERN_INVALID_HOST;
+
+       assert(host_priv == &realhost);
+
+       if (map == VM_MAP_NULL)
+               return KERN_INVALID_TASK;
+
+       if (access & ~VM_PROT_ALL || (start + size < start))
+               return KERN_INVALID_ARGUMENT;
+
+       if (access != VM_PROT_NONE) {
+               rc = vm_map_wire(map,
+                                vm_map_trunc_page(start,
+                                                  VM_MAP_PAGE_MASK(map)),
+                                vm_map_round_page(start+size,
+                                                  VM_MAP_PAGE_MASK(map)),
+                                access,
+                                TRUE);
+       } else {
+               rc = vm_map_unwire(map,
+                                  vm_map_trunc_page(start,
+                                                    VM_MAP_PAGE_MASK(map)),
+                                  vm_map_round_page(start+size,
+                                                    VM_MAP_PAGE_MASK(map)),
+                                  TRUE);
+       }
+       return rc;
+}
+
+/*
+ *     vm_wire -
  *     Specify that the range of the virtual address space
  *     of the target task must not cause page faults for
  *     the indicated accesses.
@@ -732,15 +1178,26 @@ vm_wire(
        if (map == VM_MAP_NULL)
                return KERN_INVALID_TASK;
 
-       if (access & ~VM_PROT_ALL)
+       if ((access & ~VM_PROT_ALL) || (start + size < start))
                return KERN_INVALID_ARGUMENT;
 
-       if (access != VM_PROT_NONE) {
-               rc = vm_map_wire(map, trunc_page_32(start),
-                                round_page_32(start+size), access, TRUE);
+       if (size == 0) {
+               rc = KERN_SUCCESS;
+       } else if (access != VM_PROT_NONE) {
+               rc = vm_map_wire(map,
+                                vm_map_trunc_page(start,
+                                                  VM_MAP_PAGE_MASK(map)),
+                                vm_map_round_page(start+size,
+                                                  VM_MAP_PAGE_MASK(map)),
+                                access,
+                                TRUE);
        } else {
-               rc = vm_map_unwire(map, trunc_page_32(start),
-                                  round_page_32(start+size), TRUE);
+               rc = vm_map_unwire(map,
+                                  vm_map_trunc_page(start,
+                                                    VM_MAP_PAGE_MASK(map)),
+                                  vm_map_round_page(start+size,
+                                                    VM_MAP_PAGE_MASK(map)),
+                                  TRUE);
        }
        return rc;
 }
@@ -750,10 +1207,53 @@ vm_wire(
  *
  *     Synchronises the memory range specified with its backing store
  *     image by either flushing or cleaning the contents to the appropriate
- *     memory manager engaging in a memory object synchronize dialog with
- *     the manager.  The client doesn't return until the manager issues
- *     m_o_s_completed message.  MIG Magically converts user task parameter
- *     to the task's address map.
+ *     memory manager.
+ *
+ *     interpretation of sync_flags
+ *     VM_SYNC_INVALIDATE      - discard pages, only return precious
+ *                               pages to manager.
+ *
+ *     VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
+ *                             - discard pages, write dirty or precious
+ *                               pages back to memory manager.
+ *
+ *     VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
+ *                             - write dirty or precious pages back to
+ *                               the memory manager.
+ *
+ *     VM_SYNC_CONTIGUOUS      - does everything normally, but if there
+ *                               is a hole in the region, and we would
+ *                               have returned KERN_SUCCESS, return
+ *                               KERN_INVALID_ADDRESS instead.
+ *
+ *     RETURNS
+ *     KERN_INVALID_TASK               Bad task parameter
+ *     KERN_INVALID_ARGUMENT           both sync and async were specified.
+ *     KERN_SUCCESS                    The usual.
+ *     KERN_INVALID_ADDRESS            There was a hole in the region.
+ */
+
+kern_return_t
+mach_vm_msync(
+       vm_map_t                map,
+       mach_vm_address_t       address,
+       mach_vm_size_t  size,
+       vm_sync_t               sync_flags)
+{
+
+       if (map == VM_MAP_NULL)
+               return(KERN_INVALID_TASK);
+
+       return vm_map_msync(map, (vm_map_address_t)address,
+                       (vm_map_size_t)size, sync_flags);
+}
+      
+/*
+ *     vm_msync
+ *
+ *     Synchronises the memory range specified with its backing store
+ *     image by either flushing or cleaning the contents to the appropriate
+ *     memory manager.
  *
  *     interpretation of sync_flags
  *     VM_SYNC_INVALIDATE      - discard pages, only return precious
@@ -767,14 +1267,19 @@ vm_wire(
  *                             - write dirty or precious pages back to
  *                               the memory manager.
  *
- *     NOTE
- *     The memory object attributes have not yet been implemented, this
- *     function will have to deal with the invalidate attribute
+ *     VM_SYNC_CONTIGUOUS      - does everything normally, but if there
+ *                               is a hole in the region, and we would
+ *                               have returned KERN_SUCCESS, return
+ *                               KERN_INVALID_ADDRESS instead.
+ *
+ *     The addressability of the range is limited to that which can
+ *     be described by a vm_address_t.
  *
  *     RETURNS
  *     KERN_INVALID_TASK               Bad task parameter
  *     KERN_INVALID_ARGUMENT           both sync and async were specified.
  *     KERN_SUCCESS                    The usual.
+ *     KERN_INVALID_ADDRESS            There was a hole in the region.
  */
 
 kern_return_t
@@ -784,298 +1289,406 @@ vm_msync(
        vm_size_t       size,
        vm_sync_t       sync_flags)
 {
-       msync_req_t             msr;
-       msync_req_t             new_msr;
-       queue_chain_t           req_q;  /* queue of requests for this msync */
-       vm_map_entry_t          entry;
-       vm_size_t               amount_left;
-       vm_object_offset_t      offset;
-       boolean_t               do_sync_req;
-       boolean_t               modifiable;
-       
-
-       if ((sync_flags & VM_SYNC_ASYNCHRONOUS) &&
-           (sync_flags & VM_SYNC_SYNCHRONOUS))
-               return(KERN_INVALID_ARGUMENT);
 
-       /*
-        * align address and size on page boundaries
-        */
-       size = round_page_32(address + size) - trunc_page_32(address);
-       address = trunc_page_32(address);
-
-        if (map == VM_MAP_NULL)
-                return(KERN_INVALID_TASK);
-
-       if (size == 0)
-               return(KERN_SUCCESS);
+       if (map == VM_MAP_NULL)
+               return(KERN_INVALID_TASK);
 
-       queue_init(&req_q);
-       amount_left = size;
+       return vm_map_msync(map, (vm_map_address_t)address,
+                       (vm_map_size_t)size, sync_flags);
+}
 
-       while (amount_left > 0) {
-               vm_size_t               flush_size;
-               vm_object_t             object;
 
-               vm_map_lock(map);
-               if (!vm_map_lookup_entry(map, address, &entry)) {
-                       vm_size_t       skip;
+int
+vm_toggle_entry_reuse(int toggle, int *old_value)
+{
+       vm_map_t map = current_map();
+       
+       if(toggle == VM_TOGGLE_GETVALUE && old_value != NULL){
+               *old_value = map->disable_vmentry_reuse;
+       } else if(toggle == VM_TOGGLE_SET){
+               vm_map_lock(map);
+               map->disable_vmentry_reuse = TRUE;
+               if (map->first_free == vm_map_to_entry(map)) {
+                       map->highest_entry_end = vm_map_min(map);
+               } else {
+                       map->highest_entry_end = map->first_free->vme_end;
+               }
+               vm_map_unlock(map);
+       } else if (toggle == VM_TOGGLE_CLEAR){
+               vm_map_lock(map);
+               map->disable_vmentry_reuse = FALSE;
+               vm_map_unlock(map);
+       } else
+               return KERN_INVALID_ARGUMENT;
 
-                       /*
-                        * hole in the address map.
-                        */
+       return KERN_SUCCESS;
+}
 
-                       /*
-                        * Check for empty map.
-                        */
-                       if (entry == vm_map_to_entry(map) &&
-                           entry->vme_next == entry) {
-                               vm_map_unlock(map);
-                               break;
-                       }
-                       /*
-                        * Check that we don't wrap and that
-                        * we have at least one real map entry.
-                        */
-                       if ((map->hdr.nentries == 0) ||
-                           (entry->vme_next->vme_start < address)) {
-                               vm_map_unlock(map);
-                               break;
-                       }
-                       /*
-                        * Move up to the next entry if needed
-                        */
-                       skip = (entry->vme_next->vme_start - address);
-                       if (skip >= amount_left)
-                               amount_left = 0;
-                       else
-                               amount_left -= skip;
-                       address = entry->vme_next->vme_start;
-                       vm_map_unlock(map);
-                       continue;
-               }
+/*
+ *     mach_vm_behavior_set 
+ *
+ *     Sets the paging behavior attribute for the  specified range
+ *     in the specified map.
+ *
+ *     This routine will fail with KERN_INVALID_ADDRESS if any address
+ *     in [start,start+size) is not a valid allocated memory region.
+ */
+kern_return_t 
+mach_vm_behavior_set(
+       vm_map_t                map,
+       mach_vm_offset_t        start,
+       mach_vm_size_t  size,
+       vm_behavior_t           new_behavior)
+{
+       if ((map == VM_MAP_NULL) || (start + size < start))
+               return(KERN_INVALID_ARGUMENT);
 
-               offset = address - entry->vme_start;
+       if (size == 0)
+               return KERN_SUCCESS;
 
-               /*
-                * do we have more to flush than is contained in this
-                * entry ?
-                */
-               if (amount_left + entry->vme_start + offset > entry->vme_end) {
-                       flush_size = entry->vme_end -
-                                                (entry->vme_start + offset);
-               } else {
-                       flush_size = amount_left;
-               }
-               amount_left -= flush_size;
-               address += flush_size;
+       return(vm_map_behavior_set(map,
+                                  vm_map_trunc_page(start,
+                                                    VM_MAP_PAGE_MASK(map)), 
+                                  vm_map_round_page(start+size,
+                                                    VM_MAP_PAGE_MASK(map)),
+                                  new_behavior));
+}
 
-               if (entry->is_sub_map == TRUE) {
-                       vm_map_t        local_map;
-                       vm_offset_t     local_offset;
+/*
+ *     vm_behavior_set 
+ *
+ *     Sets the paging behavior attribute for the  specified range
+ *     in the specified map.
+ *
+ *     This routine will fail with KERN_INVALID_ADDRESS if any address
+ *     in [start,start+size) is not a valid allocated memory region.
+ *
+ *     This routine is potentially limited in addressibility by the
+ *     use of vm_offset_t (if the map provided is larger than the
+ *     kernel's).
+ */
+kern_return_t 
+vm_behavior_set(
+       vm_map_t                map,
+       vm_offset_t             start,
+       vm_size_t               size,
+       vm_behavior_t           new_behavior)
+{
+       if ((map == VM_MAP_NULL) || (start + size < start))
+               return(KERN_INVALID_ARGUMENT);
 
-                       local_map = entry->object.sub_map;
-                       local_offset = entry->offset;
-                       vm_map_unlock(map);
-                       vm_msync(
-                               local_map,
-                               local_offset,
-                               flush_size,
-                               sync_flags);
-                       continue;
-               }
-               object = entry->object.vm_object;
+       if (size == 0)
+               return KERN_SUCCESS;
 
-               /*
-                * We can't sync this object if the object has not been
-                * created yet
-                */
-               if (object == VM_OBJECT_NULL) {
-                       vm_map_unlock(map);
-                       continue;
-               }
-               offset += entry->offset;
-               modifiable = (entry->protection & VM_PROT_WRITE)
-                               != VM_PROT_NONE;
+       return(vm_map_behavior_set(map,
+                                  vm_map_trunc_page(start,
+                                                    VM_MAP_PAGE_MASK(map)), 
+                                  vm_map_round_page(start+size,
+                                                    VM_MAP_PAGE_MASK(map)),
+                                  new_behavior));
+}
 
-                vm_object_lock(object);
+/*
+ *     mach_vm_region:
+ *
+ *     User call to obtain information about a region in
+ *     a task's address map. Currently, only one flavor is
+ *     supported.
+ *
+ *     XXX The reserved and behavior fields cannot be filled
+ *         in until the vm merge from the IK is completed, and
+ *         vm_reserve is implemented.
+ *
+ *     XXX Dependency: syscall_vm_region() also supports only one flavor.
+ */
 
-               if (sync_flags & (VM_SYNC_KILLPAGES | VM_SYNC_DEACTIVATE)) {
-                       boolean_t kill_pages = 0;
+kern_return_t
+mach_vm_region(
+       vm_map_t                 map,
+       mach_vm_offset_t        *address,               /* IN/OUT */
+       mach_vm_size_t  *size,                  /* OUT */
+       vm_region_flavor_t       flavor,                /* IN */
+       vm_region_info_t         info,                  /* OUT */
+       mach_msg_type_number_t  *count,                 /* IN/OUT */
+       mach_port_t             *object_name)           /* OUT */
+{
+       vm_map_offset_t         map_addr;
+       vm_map_size_t           map_size;
+       kern_return_t           kr;
 
-                       if (sync_flags & VM_SYNC_KILLPAGES) {
-                               if (object->ref_count == 1 && !entry->needs_copy && !object->shadow)
-                                       kill_pages = 1;
-                               else
-                                       kill_pages = -1;
-                       }
-                       if (kill_pages != -1)
-                               vm_object_deactivate_pages(object, offset, 
-                                                              (vm_object_size_t)flush_size, kill_pages);
-                       vm_object_unlock(object);
-                       vm_map_unlock(map);
-                       continue;
-               }
-               /*
-                * We can't sync this object if there isn't a pager.
-                * Don't bother to sync internal objects, since there can't
-                * be any "permanent" storage for these objects anyway.
-                */
-               if ((object->pager == MEMORY_OBJECT_NULL) ||
-                   (object->internal) || (object->private)) {
-                       vm_object_unlock(object);
-                       vm_map_unlock(map);
-                       continue;
-               }
-               /*
-                * keep reference on the object until syncing is done
-                */
-               assert(object->ref_count > 0);
-               object->ref_count++;
-               vm_object_res_reference(object);
-               vm_object_unlock(object);
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
 
-               vm_map_unlock(map);
+       map_addr = (vm_map_offset_t)*address;
+       map_size = (vm_map_size_t)*size;
 
-               do_sync_req = vm_object_sync(object,
-                                       offset,
-                                       flush_size,
-                                       sync_flags & VM_SYNC_INVALIDATE,
-                                       (modifiable &&
-                                       (sync_flags & VM_SYNC_SYNCHRONOUS ||
-                                        sync_flags & VM_SYNC_ASYNCHRONOUS)));
+       /* legacy conversion */
+       if (VM_REGION_BASIC_INFO == flavor)
+               flavor = VM_REGION_BASIC_INFO_64;
 
-               /*
-                * only send a m_o_s if we returned pages or if the entry
-                * is writable (ie dirty pages may have already been sent back)
-                */
-               if (!do_sync_req && !modifiable) {
-                       vm_object_deallocate(object);
-                       continue;
-               }
-               msync_req_alloc(new_msr);
+       kr = vm_map_region(map,
+                          &map_addr, &map_size,
+                          flavor, info, count,
+                          object_name);
 
-                vm_object_lock(object);
-               offset += object->paging_offset;
+       *address = map_addr;
+       *size = map_size;
+       return kr;
+}
 
-               new_msr->offset = offset;
-               new_msr->length = flush_size;
-               new_msr->object = object;
-               new_msr->flag = VM_MSYNC_SYNCHRONIZING;
-re_iterate:
-               queue_iterate(&object->msr_q, msr, msync_req_t, msr_q) {
-                       /*
-                        * need to check for overlapping entry, if found, wait
-                        * on overlapping msr to be done, then reiterate
-                        */
-                       msr_lock(msr);
-                       if (msr->flag == VM_MSYNC_SYNCHRONIZING &&
-                           ((offset >= msr->offset && 
-                             offset < (msr->offset + msr->length)) ||
-                            (msr->offset >= offset &&
-                             msr->offset < (offset + flush_size))))
-                       {
-                               assert_wait((event_t) msr,THREAD_INTERRUPTIBLE);
-                               msr_unlock(msr);
-                               vm_object_unlock(object);
-                               thread_block((void (*)(void))0);
-                               vm_object_lock(object);
-                               goto re_iterate;
-                       }
-                       msr_unlock(msr);
-               }/* queue_iterate */
+/*
+ *     vm_region_64 and vm_region:
+ *
+ *     User call to obtain information about a region in
+ *     a task's address map. Currently, only one flavor is
+ *     supported.
+ *
+ *     XXX The reserved and behavior fields cannot be filled
+ *         in until the vm merge from the IK is completed, and
+ *         vm_reserve is implemented.
+ *
+ *     XXX Dependency: syscall_vm_region() also supports only one flavor.
+ */
 
-               queue_enter(&object->msr_q, new_msr, msync_req_t, msr_q);
-               vm_object_unlock(object);
+kern_return_t
+vm_region_64(
+       vm_map_t                 map,
+       vm_offset_t             *address,               /* IN/OUT */
+       vm_size_t               *size,                  /* OUT */
+       vm_region_flavor_t       flavor,                /* IN */
+       vm_region_info_t         info,                  /* OUT */
+       mach_msg_type_number_t  *count,                 /* IN/OUT */
+       mach_port_t             *object_name)           /* OUT */
+{
+       vm_map_offset_t         map_addr;
+       vm_map_size_t           map_size;
+       kern_return_t           kr;
 
-               queue_enter(&req_q, new_msr, msync_req_t, req_q);
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
 
-               (void) memory_object_synchronize(
-                               object->pager,
-                               offset,
-                               flush_size,
-                               sync_flags);
-       }/* while */
+       map_addr = (vm_map_offset_t)*address;
+       map_size = (vm_map_size_t)*size;
 
-       /*
-        * wait for memory_object_sychronize_completed messages from pager(s)
-        */
+       /* legacy conversion */
+       if (VM_REGION_BASIC_INFO == flavor)
+               flavor = VM_REGION_BASIC_INFO_64;
 
-       while (!queue_empty(&req_q)) {
-               msr = (msync_req_t)queue_first(&req_q);
-               msr_lock(msr);
-               while(msr->flag != VM_MSYNC_DONE) {
-                       assert_wait((event_t) msr, THREAD_INTERRUPTIBLE);
-                       msr_unlock(msr);
-                       thread_block((void (*)(void))0);
-                       msr_lock(msr);
-               }/* while */
-               queue_remove(&req_q, msr, msync_req_t, req_q);
-               msr_unlock(msr);
-               vm_object_deallocate(msr->object);
-               msync_req_free(msr);
-       }/* queue_iterate */
+       kr = vm_map_region(map,
+                          &map_addr, &map_size,
+                          flavor, info, count,
+                          object_name);
 
-       return(KERN_SUCCESS);
-}/* vm_msync */
+       *address = CAST_DOWN(vm_offset_t, map_addr);
+       *size = CAST_DOWN(vm_size_t, map_size);
+
+       if (KERN_SUCCESS == kr && map_addr + map_size > VM_MAX_ADDRESS)
+               return KERN_INVALID_ADDRESS;
+       return kr;
+}
+
+kern_return_t
+vm_region(
+       vm_map_t                        map,
+       vm_address_t                    *address,       /* IN/OUT */
+       vm_size_t                       *size,          /* OUT */
+       vm_region_flavor_t              flavor, /* IN */
+       vm_region_info_t                info,           /* OUT */
+       mach_msg_type_number_t  *count, /* IN/OUT */
+       mach_port_t                     *object_name)   /* OUT */
+{
+       vm_map_address_t        map_addr;
+       vm_map_size_t           map_size;
+       kern_return_t           kr;
+
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
+
+       map_addr = (vm_map_address_t)*address;
+       map_size = (vm_map_size_t)*size;
 
+       kr = vm_map_region(map,
+                          &map_addr, &map_size,
+                          flavor, info, count,
+                          object_name);
+
+       *address = CAST_DOWN(vm_address_t, map_addr);
+       *size = CAST_DOWN(vm_size_t, map_size);
+
+       if (KERN_SUCCESS == kr && map_addr + map_size > VM_MAX_ADDRESS)
+               return KERN_INVALID_ADDRESS;
+       return kr;
+}
 
 /*
- *     task_wire
+ *     vm_region_recurse: A form of vm_region which follows the
+ *     submaps in a target map
  *
- *     Set or clear the map's wiring_required flag.  This flag, if set,
- *     will cause all future virtual memory allocation to allocate
- *     user wired memory.  Unwiring pages wired down as a result of
- *     this routine is done with the vm_wire interface.
  */
 kern_return_t
-task_wire(
-       vm_map_t        map,
-       boolean_t       must_wire)
+mach_vm_region_recurse(
+       vm_map_t                        map,
+       mach_vm_address_t               *address,
+       mach_vm_size_t          *size,
+       uint32_t                        *depth,
+       vm_region_recurse_info_t        info,
+       mach_msg_type_number_t  *infoCnt)
 {
-       if (map == VM_MAP_NULL)
-               return(KERN_INVALID_ARGUMENT);
+       vm_map_address_t        map_addr;
+       vm_map_size_t           map_size;
+       kern_return_t           kr;
 
-       if (must_wire)
-               map->wiring_required = TRUE;
-       else
-               map->wiring_required = FALSE;
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
 
-       return(KERN_SUCCESS);
+       map_addr = (vm_map_address_t)*address;
+       map_size = (vm_map_size_t)*size;
+
+       kr = vm_map_region_recurse_64(
+                       map,
+                       &map_addr,
+                       &map_size,
+                       depth,
+                       (vm_region_submap_info_64_t)info,
+                       infoCnt);
+
+       *address = map_addr;
+       *size = map_size;
+       return kr;
 }
 
 /*
- *     vm_behavior_set sets the paging behavior attribute for the 
- *     specified range in the specified map. This routine will fail
- *     with KERN_INVALID_ADDRESS if any address in [start,start+size)
- *     is not a valid allocated or reserved memory region.
+ *     vm_region_recurse: A form of vm_region which follows the
+ *     submaps in a target map
+ *
  */
-kern_return_t 
-vm_behavior_set(
+kern_return_t
+vm_region_recurse_64(
+       vm_map_t                        map,
+       vm_address_t                    *address,
+       vm_size_t                       *size,
+       uint32_t                        *depth,
+       vm_region_recurse_info_64_t     info,
+       mach_msg_type_number_t  *infoCnt)
+{
+       vm_map_address_t        map_addr;
+       vm_map_size_t           map_size;
+       kern_return_t           kr;
+
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
+
+       map_addr = (vm_map_address_t)*address;
+       map_size = (vm_map_size_t)*size;
+
+       kr = vm_map_region_recurse_64(
+                       map,
+                       &map_addr,
+                       &map_size,
+                       depth,
+                       (vm_region_submap_info_64_t)info,
+                       infoCnt);
+
+       *address = CAST_DOWN(vm_address_t, map_addr);
+       *size = CAST_DOWN(vm_size_t, map_size);
+
+       if (KERN_SUCCESS == kr && map_addr + map_size > VM_MAX_ADDRESS)
+               return KERN_INVALID_ADDRESS;
+       return kr;
+}
+
+kern_return_t
+vm_region_recurse(
+       vm_map_t                        map,
+       vm_offset_t             *address,       /* IN/OUT */
+       vm_size_t                       *size,          /* OUT */
+       natural_t                       *depth, /* IN/OUT */
+       vm_region_recurse_info_t        info32, /* IN/OUT */
+       mach_msg_type_number_t  *infoCnt)       /* IN/OUT */
+{
+       vm_region_submap_info_data_64_t info64;
+       vm_region_submap_info_t info;
+       vm_map_address_t        map_addr;
+       vm_map_size_t           map_size;
+       kern_return_t           kr;
+
+       if (VM_MAP_NULL == map || *infoCnt < VM_REGION_SUBMAP_INFO_COUNT)
+               return KERN_INVALID_ARGUMENT;
+
+       
+       map_addr = (vm_map_address_t)*address;
+       map_size = (vm_map_size_t)*size;
+       info = (vm_region_submap_info_t)info32;
+       *infoCnt = VM_REGION_SUBMAP_INFO_COUNT_64;
+
+       kr = vm_map_region_recurse_64(map, &map_addr,&map_size,
+                                     depth, &info64, infoCnt);
+
+       info->protection = info64.protection;
+       info->max_protection = info64.max_protection;
+       info->inheritance = info64.inheritance;
+       info->offset = (uint32_t)info64.offset; /* trouble-maker */
+        info->user_tag = info64.user_tag;
+        info->pages_resident = info64.pages_resident;
+        info->pages_shared_now_private = info64.pages_shared_now_private;
+        info->pages_swapped_out = info64.pages_swapped_out;
+        info->pages_dirtied = info64.pages_dirtied;
+        info->ref_count = info64.ref_count;
+        info->shadow_depth = info64.shadow_depth;
+        info->external_pager = info64.external_pager;
+        info->share_mode = info64.share_mode;
+       info->is_submap = info64.is_submap;
+       info->behavior = info64.behavior;
+       info->object_id = info64.object_id;
+       info->user_wired_count = info64.user_wired_count; 
+
+       *address = CAST_DOWN(vm_address_t, map_addr);
+       *size = CAST_DOWN(vm_size_t, map_size);
+       *infoCnt = VM_REGION_SUBMAP_INFO_COUNT;
+
+       if (KERN_SUCCESS == kr && map_addr + map_size > VM_MAX_ADDRESS)
+               return KERN_INVALID_ADDRESS;
+       return kr;
+}
+
+kern_return_t
+mach_vm_purgable_control(
        vm_map_t                map,
-       vm_offset_t             start,
-       vm_size_t               size,
-       vm_behavior_t           new_behavior)
+       mach_vm_offset_t        address,
+       vm_purgable_t           control,
+       int                     *state)
 {
-       if (map == VM_MAP_NULL)
-               return(KERN_INVALID_ARGUMENT);
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
 
-       return(vm_map_behavior_set(map, trunc_page_32(start), 
-                                  round_page_32(start+size), new_behavior));
+       return vm_map_purgable_control(map,
+                                      vm_map_trunc_page(address, PAGE_MASK),
+                                      control,
+                                      state);
 }
 
-#if    VM_CPM
-/*
- *     Control whether the kernel will permit use of
- *     vm_allocate_cpm at all.
- */
-unsigned int   vm_allocate_cpm_enabled = 1;
+kern_return_t
+vm_purgable_control(
+       vm_map_t                map,
+       vm_offset_t             address,
+       vm_purgable_t           control,
+       int                     *state)
+{
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
+
+       return vm_map_purgable_control(map,
+                                      vm_map_trunc_page(address, PAGE_MASK),
+                                      control,
+                                      state);
+}
+                                       
 
 /*
  *     Ordinarily, the right to allocate CPM is restricted
  *     to privileged applications (those that can gain access
- *     to the host port).  Set this variable to zero if you
- *     want to let any application allocate CPM.
+ *     to the host priv port).  Set this variable to zero if
+ *     you want to let any application allocate CPM.
  */
 unsigned int   vm_allocate_cpm_privileged = 0;
 
@@ -1092,472 +1705,557 @@ unsigned int  vm_allocate_cpm_privileged = 0;
 kern_return_t
 vm_allocate_cpm(
        host_priv_t             host_priv,
-       register vm_map_t       map,
-       register vm_offset_t    *addr,
-       register vm_size_t      size,
+       vm_map_t                map,
+       vm_address_t            *addr,
+       vm_size_t               size,
        int                     flags)
 {
-       vm_object_t             cpm_obj;
-       pmap_t                  pmap;
-       vm_page_t               m, pages;
+       vm_map_address_t        map_addr;
+       vm_map_size_t           map_size;
        kern_return_t           kr;
-       vm_offset_t             va, start, end, offset;
-#if    MACH_ASSERT
-       extern vm_offset_t      avail_start, avail_end;
-       vm_offset_t             prev_addr;
-#endif /* MACH_ASSERT */
 
-       boolean_t               anywhere = VM_FLAGS_ANYWHERE & flags;
-
-       if (!vm_allocate_cpm_enabled)
-               return KERN_FAILURE;
-
-       if (vm_allocate_cpm_privileged && host_priv == HOST_PRIV_NULL)
+       if (vm_allocate_cpm_privileged && HOST_PRIV_NULL == host_priv)
                return KERN_INVALID_HOST;
 
-       if (map == VM_MAP_NULL)
+       if (VM_MAP_NULL == map)
                return KERN_INVALID_ARGUMENT;
-       
-       assert(host_priv == &realhost);
-
-       if (size == 0) {
-               *addr = 0;
-               return KERN_SUCCESS;
-       }
-
-       if (anywhere)
-               *addr = vm_map_min(map);
-       else
-               *addr = trunc_page_32(*addr);
-       size = round_page_32(size);
-
-       if ((kr = cpm_allocate(size, &pages, TRUE)) != KERN_SUCCESS)
-               return kr;
-
-       cpm_obj = vm_object_allocate(size);
-       assert(cpm_obj != VM_OBJECT_NULL);
-       assert(cpm_obj->internal);
-       assert(cpm_obj->size == size);
-       assert(cpm_obj->can_persist == FALSE);
-       assert(cpm_obj->pager_created == FALSE);
-       assert(cpm_obj->pageout == FALSE);
-       assert(cpm_obj->shadow == VM_OBJECT_NULL);
-
-       /*
-        *      Insert pages into object.
-        */
-
-       vm_object_lock(cpm_obj);
-       for (offset = 0; offset < size; offset += PAGE_SIZE) {
-               m = pages;
-               pages = NEXT_PAGE(m);
-
-               assert(!m->gobbled);
-               assert(!m->wanted);
-               assert(!m->pageout);
-               assert(!m->tabled);
-               assert(m->busy);
-               assert(m->phys_page>=avail_start && m->phys_page<=avail_end);
-
-               m->busy = FALSE;
-               vm_page_insert(m, cpm_obj, offset);
-       }
-       assert(cpm_obj->resident_page_count == size / PAGE_SIZE);
-       vm_object_unlock(cpm_obj);
-
-       /*
-        *      Hang onto a reference on the object in case a
-        *      multi-threaded application for some reason decides
-        *      to deallocate the portion of the address space into
-        *      which we will insert this object.
-        *
-        *      Unfortunately, we must insert the object now before
-        *      we can talk to the pmap module about which addresses
-        *      must be wired down.  Hence, the race with a multi-
-        *      threaded app.
-        */
-       vm_object_reference(cpm_obj);
-
-       /*
-        *      Insert object into map.
-        */
-
-       kr = vm_map_enter(
-                         map,
-                         addr,
-                         size,
-                         (vm_offset_t)0,
-                         flags,
-                         cpm_obj,
-                         (vm_object_offset_t)0,
-                         FALSE,
-                         VM_PROT_ALL,
-                         VM_PROT_ALL,
-                         VM_INHERIT_DEFAULT);
-
-       if (kr != KERN_SUCCESS) {
-               /*
-                *      A CPM object doesn't have can_persist set,
-                *      so all we have to do is deallocate it to
-                *      free up these pages.
-                */
-               assert(cpm_obj->pager_created == FALSE);
-               assert(cpm_obj->can_persist == FALSE);
-               assert(cpm_obj->pageout == FALSE);
-               assert(cpm_obj->shadow == VM_OBJECT_NULL);
-               vm_object_deallocate(cpm_obj); /* kill acquired ref */
-               vm_object_deallocate(cpm_obj); /* kill creation ref */
-       }
-
-       /*
-        *      Inform the physical mapping system that the
-        *      range of addresses may not fault, so that
-        *      page tables and such can be locked down as well.
-        */
-       start = *addr;
-       end = start + size;
-       pmap = vm_map_pmap(map);
-       pmap_pageable(pmap, start, end, FALSE);
-
-       /*
-        *      Enter each page into the pmap, to avoid faults.
-        *      Note that this loop could be coded more efficiently,
-        *      if the need arose, rather than looking up each page
-        *      again.
-        */
-       for (offset = 0, va = start; offset < size;
-            va += PAGE_SIZE, offset += PAGE_SIZE) {
-               vm_object_lock(cpm_obj);
-               m = vm_page_lookup(cpm_obj, (vm_object_offset_t)offset);
-               vm_object_unlock(cpm_obj);
-               assert(m != VM_PAGE_NULL);
-               PMAP_ENTER(pmap, va, m, VM_PROT_ALL,    
-                       ((unsigned int)(m->object->wimg_bits)) & VM_WIMG_MASK,
-                       TRUE);
-       }
 
-#if    MACH_ASSERT
-       /*
-        *      Verify ordering in address space.
-        */
-       for (offset = 0; offset < size; offset += PAGE_SIZE) {
-               vm_object_lock(cpm_obj);
-               m = vm_page_lookup(cpm_obj, (vm_object_offset_t)offset);
-               vm_object_unlock(cpm_obj);
-               if (m == VM_PAGE_NULL)
-                       panic("vm_allocate_cpm:  obj 0x%x off 0x%x no page",
-                             cpm_obj, offset);
-               assert(m->tabled);
-               assert(!m->busy);
-               assert(!m->wanted);
-               assert(!m->fictitious);
-               assert(!m->private);
-               assert(!m->absent);
-               assert(!m->error);
-               assert(!m->cleaning);
-               assert(!m->precious);
-               assert(!m->clustered);
-               if (offset != 0) {
-                       if (m->phys_page != prev_addr + 1) {
-                               printf("start 0x%x end 0x%x va 0x%x\n",
-                                      start, end, va);
-                               printf("obj 0x%x off 0x%x\n", cpm_obj, offset);
-                               printf("m 0x%x prev_address 0x%x\n", m,
-                                      prev_addr);
-                               panic("vm_allocate_cpm:  pages not contig!");
-                       }
-               }
-               prev_addr = m->phys_page;
-       }
-#endif /* MACH_ASSERT */
+       map_addr = (vm_map_address_t)*addr;
+       map_size = (vm_map_size_t)size;
 
-       vm_object_deallocate(cpm_obj); /* kill extra ref */
+       kr = vm_map_enter_cpm(map,
+                             &map_addr,
+                             map_size,
+                             flags);
 
+       *addr = CAST_DOWN(vm_address_t, map_addr);
        return kr;
 }
 
 
-#else  /* VM_CPM */
+kern_return_t
+mach_vm_page_query(
+       vm_map_t                map,
+       mach_vm_offset_t        offset,
+       int                     *disposition,
+       int                     *ref_count)
+{
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
 
-/*
- *     Interface is defined in all cases, but unless the kernel
- *     is built explicitly for this option, the interface does
- *     nothing.
- */
+       return vm_map_page_query_internal(
+               map,
+               vm_map_trunc_page(offset, PAGE_MASK),
+               disposition, ref_count);
+}
 
 kern_return_t
-vm_allocate_cpm(
-       host_priv_t             host_priv,
-       register vm_map_t       map,
-       register vm_offset_t    *addr,
-       register vm_size_t      size,
-       int                     flags)
+vm_map_page_query(
+       vm_map_t                map,
+       vm_offset_t             offset,
+       int                     *disposition,
+       int                     *ref_count)
 {
-       return KERN_FAILURE;
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
+
+       return vm_map_page_query_internal(
+               map,
+               vm_map_trunc_page(offset, PAGE_MASK),
+               disposition, ref_count);
 }
 
-/*
- */
 kern_return_t
-mach_memory_object_memory_entry_64(
-       host_t                  host,
-       boolean_t               internal,
-       vm_object_offset_t      size,
-       vm_prot_t               permission,
-       memory_object_t         pager,
-       ipc_port_t              *entry_handle)
+mach_vm_page_info(
+       vm_map_t                map,
+       mach_vm_address_t       address,
+       vm_page_info_flavor_t   flavor,
+       vm_page_info_t          info,
+       mach_msg_type_number_t  *count)
 {
-       unsigned int            access;
-       vm_named_entry_t        user_object;
-       ipc_port_t              user_handle;
-       ipc_port_t              previous;
-       kern_return_t           kr;
+       kern_return_t   kr;
 
-        if (host == HOST_NULL)
-                return(KERN_INVALID_HOST);
+       if (map == VM_MAP_NULL) {
+               return KERN_INVALID_ARGUMENT;
+       }
 
-       user_object = (vm_named_entry_t) 
-                       kalloc(sizeof (struct vm_named_entry));
-       if(user_object == NULL)
-               return KERN_FAILURE;
-       named_entry_lock_init(user_object);
-       user_handle = ipc_port_alloc_kernel();
-       ip_lock(user_handle);
+       kr = vm_map_page_info(map, address, flavor, info, count);
+       return kr;
+}
 
-       /* make a sonce right */
-       user_handle->ip_sorights++;
-       ip_reference(user_handle);
+/* map a (whole) upl into an address space */
+kern_return_t
+vm_upl_map(
+       vm_map_t                map, 
+       upl_t                   upl, 
+       vm_address_t            *dst_addr)
+{
+       vm_map_offset_t         map_addr;
+       kern_return_t           kr;
 
-       user_handle->ip_destination = IP_NULL;
-       user_handle->ip_receiver_name = MACH_PORT_NULL;
-       user_handle->ip_receiver = ipc_space_kernel;
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
 
-       /* make a send right */
-        user_handle->ip_mscount++;
-        user_handle->ip_srights++;
-        ip_reference(user_handle);
+       kr = vm_map_enter_upl(map, upl, &map_addr);
+       *dst_addr = CAST_DOWN(vm_address_t, map_addr);
+       return kr;
+}
 
-       ipc_port_nsrequest(user_handle, 1, user_handle, &previous);
-       /* nsrequest unlocks user_handle */
+kern_return_t
+vm_upl_unmap(
+       vm_map_t                map,
+       upl_t                   upl)
+{
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
 
-       user_object->object = NULL;
-       user_object->size = size;
-       user_object->offset = 0;
-       user_object->backing.pager = pager;
-       user_object->protection = permission & VM_PROT_ALL;
-       access = GET_MAP_MEM(permission);
-       SET_MAP_MEM(access, user_object->protection);
-       user_object->internal = internal;
-       user_object->is_sub_map = FALSE;
-       user_object->ref_count = 1;
+       return (vm_map_remove_upl(map, upl));
+}
 
-       ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
-                                                       IKOT_NAMED_ENTRY);
-       *entry_handle = user_handle;
-       return KERN_SUCCESS;
-}      
+/* Retrieve a upl for an object underlying an address range in a map */
 
 kern_return_t
-mach_memory_object_memory_entry(
-       host_t          host,
-       boolean_t       internal,
-       vm_size_t       size,
-       vm_prot_t       permission,
-       memory_object_t pager,
-       ipc_port_t      *entry_handle)
+vm_map_get_upl(
+       vm_map_t                map,
+       vm_map_offset_t         map_offset,
+       upl_size_t              *upl_size,
+       upl_t                   *upl,
+       upl_page_info_array_t   page_list,
+       unsigned int            *count,
+       int                     *flags,
+       int                     force_data_sync)
 {
-       return mach_memory_object_memory_entry_64( host, internal, 
-               (vm_object_offset_t)size, permission, pager, entry_handle);
-}
+       int             map_flags;
+       kern_return_t   kr;
+
+       if (VM_MAP_NULL == map)
+               return KERN_INVALID_ARGUMENT;
+
+       map_flags = *flags & ~UPL_NOZEROFILL;
+       if (force_data_sync)
+               map_flags |= UPL_FORCE_DATA_SYNC;
 
+       kr = vm_map_create_upl(map,
+                              map_offset,
+                              upl_size,
+                              upl,
+                              page_list,
+                              count,
+                              &map_flags);
 
+       *flags = (map_flags & ~UPL_FORCE_DATA_SYNC);
+       return kr;
+}
 
 /*
+ * mach_make_memory_entry_64
+ *
+ * Think of it as a two-stage vm_remap() operation.  First
+ * you get a handle.  Second, you get map that handle in
+ * somewhere else. Rather than doing it all at once (and
+ * without needing access to the other whole map).
  */
 
 kern_return_t
 mach_make_memory_entry_64(
        vm_map_t                target_map,
-       vm_object_size_t        *size,
-       vm_object_offset_t      offset,
+       memory_object_size_t    *size,
+       memory_object_offset_t offset,
        vm_prot_t               permission,
        ipc_port_t              *object_handle,
-       ipc_port_t              parent_entry)
+       ipc_port_t              parent_handle)
 {
        vm_map_version_t        version;
-       vm_named_entry_t        user_object;
+       vm_named_entry_t        parent_entry;
+       vm_named_entry_t        user_entry;
        ipc_port_t              user_handle;
-       ipc_port_t              previous;
        kern_return_t           kr;
-       vm_map_t                pmap_map;
+       vm_map_t                real_map;
 
        /* needed for call to vm_map_lookup_locked */
-       boolean_t                       wired;
+       boolean_t               wired;
        vm_object_offset_t      obj_off;
-       vm_prot_t                       prot;
-       vm_object_offset_t      lo_offset, hi_offset;
-       vm_behavior_t           behavior;
-       vm_object_t                     object;
-       vm_object_t                     shadow_object;
+       vm_prot_t               prot;
+       struct vm_object_fault_info     fault_info;
+       vm_object_t             object;
+       vm_object_t             shadow_object;
 
        /* needed for direct map entry manipulation */
        vm_map_entry_t          map_entry;
        vm_map_entry_t          next_entry;
-       vm_map_t                        local_map;
-       vm_map_t                        original_map = target_map;
-       vm_offset_t                     local_offset;
+       vm_map_t                local_map;
+       vm_map_t                original_map = target_map;
+       vm_map_size_t           total_size;
+       vm_map_size_t           map_size;
+       vm_map_offset_t         map_offset;
+       vm_map_offset_t         local_offset;
        vm_object_size_t        mappable_size;
-       vm_object_size_t        total_size;
 
-       unsigned int                    access;
-       vm_prot_t                       protections;
-       unsigned int                    wimg_mode;
-       boolean_t                       cache_attr;
+       /* 
+        * Stash the offset in the page for use by vm_map_enter_mem_object()
+        * in the VM_FLAGS_RETURN_DATA_ADDR/MAP_MEM_USE_DATA_ADDR case.
+        */
+       vm_object_offset_t      offset_in_page;
+
+       unsigned int            access;
+       vm_prot_t               protections;
+       vm_prot_t               original_protections, mask_protections;
+       unsigned int            wimg_mode;
+
+       boolean_t               force_shadow = FALSE;
+       boolean_t               use_data_addr;
+
+       if (((permission & 0x00FF0000) &
+            ~(MAP_MEM_ONLY |
+              MAP_MEM_NAMED_CREATE |
+              MAP_MEM_PURGABLE | 
+              MAP_MEM_NAMED_REUSE |
+              MAP_MEM_USE_DATA_ADDR |
+              MAP_MEM_VM_COPY |
+              MAP_MEM_VM_SHARE))) {
+               /*
+                * Unknown flag: reject for forward compatibility.
+                */
+               return KERN_INVALID_VALUE;
+       }
 
-       protections = permission & VM_PROT_ALL;
+       if (parent_handle != IP_NULL &&
+           ip_kotype(parent_handle) == IKOT_NAMED_ENTRY) {
+               parent_entry = (vm_named_entry_t) parent_handle->ip_kobject;
+       } else {
+               parent_entry = NULL;
+       }
+
+       if (parent_entry && parent_entry->is_copy) {
+               return KERN_INVALID_ARGUMENT;
+       }
+
+       original_protections = permission & VM_PROT_ALL;
+       protections = original_protections;
+       mask_protections = permission & VM_PROT_IS_MASK;
        access = GET_MAP_MEM(permission);
+       use_data_addr = ((permission & MAP_MEM_USE_DATA_ADDR) != 0);
 
+       user_handle = IP_NULL;
+       user_entry = NULL;
 
-       offset = trunc_page_64(offset);
-       *size = round_page_64(*size);
+       map_offset = vm_map_trunc_page(offset, PAGE_MASK);
 
-       if((parent_entry != NULL)
-               && (permission & MAP_MEM_ONLY)) {
-               vm_named_entry_t        parent_object;
-               if(ip_kotype(parent_entry) != IKOT_NAMED_ENTRY) {
+       if (permission & MAP_MEM_ONLY) {
+               boolean_t               parent_is_object;
+
+               map_size = vm_map_round_page(*size, PAGE_MASK);
+               
+               if (use_data_addr || parent_entry == NULL) {
                        return KERN_INVALID_ARGUMENT;
                }
-               parent_object = (vm_named_entry_t)parent_entry->ip_kobject;
-               object = parent_object->object;
-               if(object != VM_OBJECT_NULL)
+
+               parent_is_object = !(parent_entry->is_sub_map ||
+                                    parent_entry->is_pager);
+               object = parent_entry->backing.object;
+               if(parent_is_object && object != VM_OBJECT_NULL)
                        wimg_mode = object->wimg_bits;
-               if((access != GET_MAP_MEM(parent_object->protection)) &&
-                               !(parent_object->protection & VM_PROT_WRITE)) { 
+               else
+                       wimg_mode = VM_WIMG_USE_DEFAULT;
+               if((access != GET_MAP_MEM(parent_entry->protection)) &&
+                               !(parent_entry->protection & VM_PROT_WRITE)) { 
                        return KERN_INVALID_RIGHT;
                }
                if(access == MAP_MEM_IO) {
-                  SET_MAP_MEM(access, parent_object->protection);
+                  SET_MAP_MEM(access, parent_entry->protection);
                   wimg_mode = VM_WIMG_IO;
                } else if (access == MAP_MEM_COPYBACK) {
-                  SET_MAP_MEM(access, parent_object->protection);
-                  wimg_mode = VM_WIMG_DEFAULT;
+                  SET_MAP_MEM(access, parent_entry->protection);
+                  wimg_mode = VM_WIMG_USE_DEFAULT;
+               } else if (access == MAP_MEM_INNERWBACK) {
+                  SET_MAP_MEM(access, parent_entry->protection);
+                  wimg_mode = VM_WIMG_INNERWBACK;
                } else if (access == MAP_MEM_WTHRU) {
-                  SET_MAP_MEM(access, parent_object->protection);
+                  SET_MAP_MEM(access, parent_entry->protection);
                   wimg_mode = VM_WIMG_WTHRU;
                } else if (access == MAP_MEM_WCOMB) {
-                  SET_MAP_MEM(access, parent_object->protection);
+                  SET_MAP_MEM(access, parent_entry->protection);
                   wimg_mode = VM_WIMG_WCOMB;
                }
-               if(object &&
+               if (parent_is_object && object &&
                        (access != MAP_MEM_NOOP) && 
                        (!(object->nophyscache))) {
-                       if(object->wimg_bits != wimg_mode) {
-                          vm_page_t p;
-                          if ((wimg_mode == VM_WIMG_IO)
-                               || (wimg_mode == VM_WIMG_WCOMB))
-                               cache_attr = TRUE;
-                          else 
-                               cache_attr = FALSE;
-                          vm_object_lock(object);
-                          while(object->paging_in_progress) {
-                               vm_object_unlock(object);
-                               vm_object_wait(object,
-                                  VM_OBJECT_EVENT_PAGING_IN_PROGRESS,
-                                  THREAD_UNINT);
-                               vm_object_lock(object);
-                          }
-                          object->wimg_bits = wimg_mode;
-                          queue_iterate(&object->memq, 
-                                               p, vm_page_t, listq) {
-                               if (!p->fictitious) {
-                                       pmap_page_protect(
-                                               p->phys_page, 
-                                               VM_PROT_NONE);
-                                        if(cache_attr)
-                                           pmap_sync_caches_phys(
-                                                       p->phys_page);
-                               }
-                          }
-                          vm_object_unlock(object);
+
+                       if (object->wimg_bits != wimg_mode) {
+                               vm_object_lock(object);
+                               vm_object_change_wimg_mode(object, wimg_mode);
+                               vm_object_unlock(object);
                        }
                }
+               if (object_handle)
+                       *object_handle = IP_NULL;
                return KERN_SUCCESS;
-       }
+       } else if (permission & MAP_MEM_NAMED_CREATE) {
+               map_size = vm_map_round_page(*size, PAGE_MASK);
 
-       if(permission & MAP_MEM_ONLY) {
-               return KERN_INVALID_ARGUMENT;
-       }
+               if (use_data_addr) {
+                       return KERN_INVALID_ARGUMENT;
+               }
 
-       user_object = (vm_named_entry_t) 
-                       kalloc(sizeof (struct vm_named_entry));
-       if(user_object == NULL)
-               return KERN_FAILURE;
-       named_entry_lock_init(user_object);
-       user_handle = ipc_port_alloc_kernel();
-       ip_lock(user_handle);
+               kr = mach_memory_entry_allocate(&user_entry, &user_handle);
+               if (kr != KERN_SUCCESS) {
+                       return KERN_FAILURE;
+               }
 
-       /* make a sonce right */
-       user_handle->ip_sorights++;
-       ip_reference(user_handle);
+               /*
+                * Force the creation of the VM object now.
+                */
+               if (map_size > (vm_map_size_t) ANON_MAX_SIZE) {
+                       /*
+                        * LP64todo - for now, we can only allocate 4GB-4096
+                        * internal objects because the default pager can't
+                        * page bigger ones.  Remove this when it can.
+                        */
+                       kr = KERN_FAILURE;
+                       goto make_mem_done;
+               }
 
-       user_handle->ip_destination = IP_NULL;
-       user_handle->ip_receiver_name = MACH_PORT_NULL;
-       user_handle->ip_receiver = ipc_space_kernel;
+               object = vm_object_allocate(map_size);
+               assert(object != VM_OBJECT_NULL);
 
-       /* make a send right */
-        user_handle->ip_mscount++;
-        user_handle->ip_srights++;
-        ip_reference(user_handle);
+               if (permission & MAP_MEM_PURGABLE) {
+                       if (! (permission & VM_PROT_WRITE)) {
+                               /* if we can't write, we can't purge */
+                               vm_object_deallocate(object);
+                               kr = KERN_INVALID_ARGUMENT;
+                               goto make_mem_done;
+                       }
+                       object->purgable = VM_PURGABLE_NONVOLATILE;
+                       assert(object->vo_purgeable_owner == NULL);
+                       assert(object->resident_page_count == 0);
+                       assert(object->wired_page_count == 0);
+                       vm_object_lock(object);
+                       vm_purgeable_nonvolatile_enqueue(object,
+                                                        current_task());
+                       vm_object_unlock(object);
+               }
 
-       ipc_port_nsrequest(user_handle, 1, user_handle, &previous);
-       /* nsrequest unlocks user_handle */
+               /*
+                * The VM object is brand new and nobody else knows about it,
+                * so we don't need to lock it.
+                */
 
-       user_object->backing.pager = NULL;
-       user_object->ref_count = 1;
+               wimg_mode = object->wimg_bits;
+               if (access == MAP_MEM_IO) {
+                       wimg_mode = VM_WIMG_IO;
+               } else if (access == MAP_MEM_COPYBACK) {
+                       wimg_mode = VM_WIMG_USE_DEFAULT;
+               } else if (access == MAP_MEM_INNERWBACK) {
+                       wimg_mode = VM_WIMG_INNERWBACK;
+               } else if (access == MAP_MEM_WTHRU) {
+                       wimg_mode = VM_WIMG_WTHRU;
+               } else if (access == MAP_MEM_WCOMB) {
+                       wimg_mode = VM_WIMG_WCOMB;
+               }
+               if (access != MAP_MEM_NOOP) {
+                       object->wimg_bits = wimg_mode;
+               }
+               /* the object has no pages, so no WIMG bits to update here */
 
-       if(permission & MAP_MEM_NAMED_CREATE) {
-               user_object->object = NULL;
-               user_object->internal = TRUE;
-               user_object->is_sub_map = FALSE;
-               user_object->offset = 0;
-               user_object->protection = protections;
-               SET_MAP_MEM(access, user_object->protection);
-               user_object->size = *size;
+               /*
+                * XXX
+                * We use this path when we want to make sure that
+                * nobody messes with the object (coalesce, for
+                * example) before we map it.
+                * We might want to use these objects for transposition via
+                * vm_object_transpose() too, so we don't want any copy or
+                * shadow objects either...
+                */
+               object->copy_strategy = MEMORY_OBJECT_COPY_NONE;
+               object->true_share = TRUE;
+
+               user_entry->backing.object = object;
+               user_entry->internal = TRUE;
+               user_entry->is_sub_map = FALSE;
+               user_entry->is_pager = FALSE;
+               user_entry->offset = 0;
+               user_entry->data_offset = 0;
+               user_entry->protection = protections;
+               SET_MAP_MEM(access, user_entry->protection);
+               user_entry->size = map_size;
 
                /* user_object pager and internal fields are not used */
                /* when the object field is filled in.                */
 
-               ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
-                                                       IKOT_NAMED_ENTRY);
+               *size = CAST_DOWN(vm_size_t, map_size);
+               *object_handle = user_handle;
+               return KERN_SUCCESS;
+       }
+
+       if (permission & MAP_MEM_VM_COPY) {
+               vm_map_copy_t   copy;
+
+               if (target_map == VM_MAP_NULL) {
+                       return KERN_INVALID_TASK;
+               }
+
+               if (use_data_addr) {
+                       map_size = (vm_map_round_page(offset + *size,
+                                                     PAGE_MASK) -
+                                   map_offset);
+                       offset_in_page = offset - map_offset;
+               } else {
+                       map_size = vm_map_round_page(*size, PAGE_MASK);
+                       offset_in_page = 0;
+               }
+
+               kr = vm_map_copyin(target_map,
+                                  map_offset,
+                                  map_size,
+                                  FALSE,
+                                  &copy);
+               if (kr != KERN_SUCCESS) {
+                       return kr;
+               }
+                                  
+               kr = mach_memory_entry_allocate(&user_entry, &user_handle);
+               if (kr != KERN_SUCCESS) {
+                       vm_map_copy_discard(copy);
+                       return KERN_FAILURE;
+               }
+
+               user_entry->backing.copy = copy;
+               user_entry->internal = FALSE;
+               user_entry->is_sub_map = FALSE;
+               user_entry->is_pager = FALSE;
+               user_entry->is_copy = TRUE;
+               user_entry->offset = 0;
+               user_entry->protection = protections;
+               user_entry->size = map_size;
+               user_entry->data_offset = offset_in_page;
+
+               *size = CAST_DOWN(vm_size_t, map_size);
+               *object_handle = user_handle;
+               return KERN_SUCCESS;
+       }
+
+       if (permission & MAP_MEM_VM_SHARE) {
+               vm_map_copy_t   copy;
+               vm_prot_t       cur_prot, max_prot;
+
+               if (target_map == VM_MAP_NULL) {
+                       return KERN_INVALID_TASK;
+               }
+
+               if (use_data_addr) {
+                       map_size = (vm_map_round_page(offset + *size,
+                                                     PAGE_MASK) -
+                                   map_offset);
+                       offset_in_page = offset - map_offset;
+               } else {
+                       map_size = vm_map_round_page(*size, PAGE_MASK);
+                       offset_in_page = 0;
+               }
+
+               kr = vm_map_copy_extract(target_map,
+                                        map_offset,
+                                        map_size,
+                                        &copy,
+                                        &cur_prot,
+                                        &max_prot);
+               if (kr != KERN_SUCCESS) {
+                       return kr;
+               }
+
+               if (mask_protections) {
+                       /*
+                        * We just want as much of "original_protections" 
+                        * as we can get out of the actual "cur_prot".
+                        */
+                       protections &= cur_prot;
+                       if (protections == VM_PROT_NONE) {
+                               /* no access at all: fail */
+                               vm_map_copy_discard(copy);
+                               return KERN_PROTECTION_FAILURE;
+                       }
+               } else {
+                       /*
+                        * We want exactly "original_protections"
+                        * out of "cur_prot".
+                        */
+                       if ((cur_prot & protections) != protections) {
+                               vm_map_copy_discard(copy);
+                               return KERN_PROTECTION_FAILURE;
+                       }
+               }
+
+               kr = mach_memory_entry_allocate(&user_entry, &user_handle);
+               if (kr != KERN_SUCCESS) {
+                       vm_map_copy_discard(copy);
+                       return KERN_FAILURE;
+               }
+
+               user_entry->backing.copy = copy;
+               user_entry->internal = FALSE;
+               user_entry->is_sub_map = FALSE;
+               user_entry->is_pager = FALSE;
+               user_entry->is_copy = TRUE;
+               user_entry->offset = 0;
+               user_entry->protection = protections;
+               user_entry->size = map_size;
+               user_entry->data_offset = offset_in_page;
+
+               *size = CAST_DOWN(vm_size_t, map_size);
                *object_handle = user_handle;
                return KERN_SUCCESS;
        }
 
-       if(parent_entry == NULL) {
-       /* Create a named object based on address range within the task map */
-       /* Go find the object at given address */
+       if (parent_entry == NULL ||
+           (permission & MAP_MEM_NAMED_REUSE)) {
+
+               if (use_data_addr) {
+                       map_size = vm_map_round_page(offset + *size, PAGE_MASK) - map_offset;
+                       offset_in_page = offset - map_offset;
+               } else {
+                       map_size = vm_map_round_page(*size, PAGE_MASK);
+                       offset_in_page = 0;
+               }
 
+               /* Create a named object based on address range within the task map */
+               /* Go find the object at given address */
+
+               if (target_map == VM_MAP_NULL) {
+                       return KERN_INVALID_TASK;
+               }
+
+redo_lookup:
+               protections = original_protections;
                vm_map_lock_read(target_map);
 
                /* get the object associated with the target address */
                /* note we check the permission of the range against */
                /* that requested by the caller */
 
-               kr = vm_map_lookup_locked(&target_map, offset, 
-                               protections, &version,
-                               &object, &obj_off, &prot, &wired, &behavior,
-                               &lo_offset, &hi_offset, &pmap_map);
+               kr = vm_map_lookup_locked(&target_map, map_offset, 
+                                         protections | mask_protections,
+                                         OBJECT_LOCK_EXCLUSIVE, &version,
+                                         &object, &obj_off, &prot, &wired,
+                                         &fault_info,
+                                         &real_map);
                if (kr != KERN_SUCCESS) {
                        vm_map_unlock_read(target_map);
                        goto make_mem_done;
                }
+               if (mask_protections) {
+                       /*
+                        * The caller asked us to use the "protections" as
+                        * a mask, so restrict "protections" to what this
+                        * mapping actually allows.
+                        */
+                       protections &= prot;
+               }
                if (((prot & protections) != protections) 
                                        || (object == kernel_object)) {
                        kr = KERN_INVALID_RIGHT;
                        vm_object_unlock(object);
                        vm_map_unlock_read(target_map);
-                       if(pmap_map != target_map)
-                               vm_map_unlock_read(pmap_map);
+                       if(real_map != target_map)
+                               vm_map_unlock_read(real_map);
                        if(object == kernel_object) {
                                printf("Warning: Attempt to create a named"
                                        " entry from the kernel_object\n");
@@ -1567,41 +2265,52 @@ mach_make_memory_entry_64(
 
                /* We have an object, now check to see if this object */
                /* is suitable.  If not, create a shadow and share that */
-               
-redo_lookup:
+
+               /*
+                * We have to unlock the VM object to avoid deadlocking with
+                * a VM map lock (the lock ordering is map, the object), if we
+                * need to modify the VM map to create a shadow object.  Since
+                * we might release the VM map lock below anyway, we have
+                * to release the VM map lock now.
+                * XXX FBDP There must be a way to avoid this double lookup...
+                *
+                * Take an extra reference on the VM object to make sure it's
+                * not going to disappear.
+                */
+               vm_object_reference_locked(object); /* extra ref to hold obj */
+               vm_object_unlock(object);
+
                local_map = original_map;
-               local_offset = offset;
+               local_offset = map_offset;
                if(target_map != local_map) {
                        vm_map_unlock_read(target_map);
-                       if(pmap_map != target_map)
-                               vm_map_unlock_read(pmap_map);
+                       if(real_map != target_map)
+                               vm_map_unlock_read(real_map);
                        vm_map_lock_read(local_map);
                        target_map = local_map;
-                       pmap_map = local_map;
+                       real_map = local_map;
                }
                while(TRUE) {
                   if(!vm_map_lookup_entry(local_map, 
                                                local_offset, &map_entry)) {
                        kr = KERN_INVALID_ARGUMENT;
-                        vm_object_unlock(object);
                         vm_map_unlock_read(target_map);
-                       if(pmap_map != target_map)
-                               vm_map_unlock_read(pmap_map);
+                       if(real_map != target_map)
+                               vm_map_unlock_read(real_map);
+                        vm_object_deallocate(object); /* release extra ref */
+                       object = VM_OBJECT_NULL;
                         goto make_mem_done;
                   }
                   if(!(map_entry->is_sub_map)) {
                      if(map_entry->object.vm_object != object) {
                         kr = KERN_INVALID_ARGUMENT;
-                         vm_object_unlock(object);
                          vm_map_unlock_read(target_map);
-                        if(pmap_map != target_map)
-                               vm_map_unlock_read(pmap_map);
+                        if(real_map != target_map)
+                               vm_map_unlock_read(real_map);
+                         vm_object_deallocate(object); /* release extra ref */
+                        object = VM_OBJECT_NULL;
                          goto make_mem_done;
                      }
-                     if(map_entry->wired_count) {
-                        /* JMM - The check below should be reworked instead. */
-                        object->true_share = TRUE;
-                     }
                      break;
                   } else {
                        vm_map_t        tmap;
@@ -1611,30 +2320,49 @@ redo_lookup:
                        vm_map_lock_read(local_map);
                        vm_map_unlock_read(tmap);
                        target_map = local_map;
-                       pmap_map = local_map;
+                       real_map = local_map;
                        local_offset = local_offset - map_entry->vme_start;
                        local_offset += map_entry->offset;
                   }
                }
+
+               /*
+                * We found the VM map entry, lock the VM object again.
+                */
+               vm_object_lock(object);
+               if(map_entry->wired_count) {
+                        /* JMM - The check below should be reworked instead. */
+                        object->true_share = TRUE;
+                     }
+               if (mask_protections) {
+                       /*
+                        * The caller asked us to use the "protections" as
+                        * a mask, so restrict "protections" to what this
+                        * mapping actually allows.
+                        */
+                       protections &= map_entry->max_protection;
+               }
                if(((map_entry->max_protection) & protections) != protections) {
                         kr = KERN_INVALID_RIGHT;
                          vm_object_unlock(object);
                          vm_map_unlock_read(target_map);
-                        if(pmap_map != target_map)
-                               vm_map_unlock_read(pmap_map);
+                        if(real_map != target_map)
+                               vm_map_unlock_read(real_map);
+                        vm_object_deallocate(object);
+                        object = VM_OBJECT_NULL;
                          goto make_mem_done;
                }
 
-               mappable_size  =  hi_offset - obj_off;
+               mappable_size = fault_info.hi_offset - obj_off;
                total_size = map_entry->vme_end - map_entry->vme_start;
-               if(*size > mappable_size) {
+               if(map_size > mappable_size) {
                        /* try to extend mappable size if the entries */
                        /* following are from the same object and are */
                        /* compatible */
                        next_entry = map_entry->vme_next;
                        /* lets see if the next map entry is still   */
                        /* pointing at this object and is contiguous */
-                       while(*size > mappable_size) {
+                       while(map_size > mappable_size) {
                                if((next_entry->object.vm_object == object) &&
                                        (next_entry->vme_start == 
                                                next_entry->vme_prev->vme_end) &&
@@ -1642,6 +2370,20 @@ redo_lookup:
                                           next_entry->vme_prev->offset + 
                                           (next_entry->vme_prev->vme_end - 
                                           next_entry->vme_prev->vme_start))) {
+                                       if (mask_protections) {
+                                               /*
+                                                * The caller asked us to use
+                                                * the "protections" as a mask,
+                                                * so restrict "protections" to
+                                                * what this mapping actually
+                                                * allows.
+                                                */
+                                               protections &= next_entry->max_protection;
+                                       }
+                                       if ((next_entry->wired_count) &&
+                                           (map_entry->wired_count == 0)) {
+                                               break;
+                                       }
                                        if(((next_entry->max_protection) 
                                                & protections) != protections) {
                                                break;
@@ -1661,20 +2403,84 @@ redo_lookup:
                        }
                }
 
-               if(object->internal) {
+               if (vm_map_entry_should_cow_for_true_share(map_entry) &&
+                   object->vo_size > map_size &&
+                   map_size != 0) {
+                       /*
+                        * Set up the targeted range for copy-on-write to
+                        * limit the impact of "true_share"/"copy_delay" to
+                        * that range instead of the entire VM object...
+                        */
+                       
+                       vm_object_unlock(object);
+                       if (vm_map_lock_read_to_write(target_map)) {
+                               vm_object_deallocate(object);
+                               target_map = original_map;
+                               goto redo_lookup;
+                       }
+
+                       vm_map_clip_start(target_map,
+                                         map_entry,
+                                         vm_map_trunc_page(offset,
+                                                           VM_MAP_PAGE_MASK(target_map)));
+                       vm_map_clip_end(target_map,
+                                       map_entry,
+                                       (vm_map_round_page(offset + map_size,
+                                                          VM_MAP_PAGE_MASK(target_map))));
+                       force_shadow = TRUE;
+
+                       if ((map_entry->vme_end - offset) < map_size) {
+                               map_size = map_entry->vme_end - offset;
+                       }
+                       total_size = map_entry->vme_end - map_entry->vme_start;
+
+                       vm_map_lock_write_to_read(target_map);
+                       vm_object_lock(object);
+               }
+
+               if (object->internal) {
                        /* vm_map_lookup_locked will create a shadow if   */
                        /* needs_copy is set but does not check for the   */
                        /* other two conditions shown. It is important to */ 
                        /* set up an object which will not be pulled from */
                        /* under us.  */
 
-                       if ((map_entry->needs_copy  || object->shadowed ||
-                            (object->size > total_size))
-                                       && !object->true_share) {
+                       if (force_shadow ||
+                           ((map_entry->needs_copy  ||
+                             object->shadowed ||
+                             (object->vo_size > total_size &&
+                              (map_entry->offset != 0 ||
+                               object->vo_size >
+                               vm_map_round_page(total_size,
+                                                 VM_MAP_PAGE_MASK(target_map)))))
+                            && !object->true_share)) {
+                               /*
+                                * We have to unlock the VM object before
+                                * trying to upgrade the VM map lock, to
+                                * honor lock ordering (map then object).
+                                * Otherwise, we would deadlock if another
+                                * thread holds a read lock on the VM map and
+                                * is trying to acquire the VM object's lock.
+                                * We still hold an extra reference on the
+                                * VM object, guaranteeing that it won't
+                                * disappear.
+                                */
+                               vm_object_unlock(object);
+
                                if (vm_map_lock_read_to_write(target_map)) {
-                                       vm_map_lock_read(target_map);
+                                       /*
+                                        * We couldn't upgrade our VM map lock
+                                        * from "read" to "write" and we lost
+                                        * our "read" lock.
+                                        * Start all over again...
+                                        */
+                                       vm_object_deallocate(object); /* extra ref */
+                                       target_map = original_map;
                                        goto redo_lookup;
                                }
+#if 00
+                               vm_object_lock(object);
+#endif
 
                                /* 
                                 * JMM - We need to avoid coming here when the object
@@ -1685,26 +2491,38 @@ redo_lookup:
                                 
                                /* create a shadow object */
                                vm_object_shadow(&map_entry->object.vm_object,
-                                               &map_entry->offset, total_size);
+                                                &map_entry->offset, total_size);
                                shadow_object = map_entry->object.vm_object;
+#if 00
                                vm_object_unlock(object);
+#endif
+
+                               prot = map_entry->protection & ~VM_PROT_WRITE;
+
+                               if (override_nx(target_map, map_entry->alias) && prot)
+                                       prot |= VM_PROT_EXECUTE;
+
                                vm_object_pmap_protect(
                                        object, map_entry->offset,
                                        total_size,
                                        ((map_entry->is_shared 
-                                               || target_map->mapped)
+                                         || target_map->mapped_in_other_pmaps)
                                                        ? PMAP_NULL :
                                                        target_map->pmap),
                                        map_entry->vme_start,
-                                       map_entry->protection & ~VM_PROT_WRITE);
+                                       prot);
                                total_size -= (map_entry->vme_end 
                                                - map_entry->vme_start);
                                next_entry = map_entry->vme_next;
                                map_entry->needs_copy = FALSE;
+
+                               vm_object_lock(shadow_object);
                                while (total_size) {
+                                   assert((next_entry->wired_count == 0) ||
+                                          (map_entry->wired_count));
+
                                   if(next_entry->object.vm_object == object) {
-                                       shadow_object->ref_count++; 
-                                       vm_object_res_reference(shadow_object);
+                                       vm_object_reference_locked(shadow_object);
                                        next_entry->object.vm_object 
                                                        = shadow_object;
                                        vm_object_deallocate(object);
@@ -1723,13 +2541,18 @@ redo_lookup:
                                        next_entry = next_entry->vme_next;
                                }
 
+                               /*
+                                * Transfer our extra reference to the
+                                * shadow object.
+                                */
+                               vm_object_reference_locked(shadow_object);
+                               vm_object_deallocate(object); /* extra ref */
                                object = shadow_object;
-                               vm_object_lock(object);
+
                                obj_off = (local_offset - map_entry->vme_start)
                                                         + map_entry->offset;
-                               vm_map_lock_write_to_read(target_map);
-
 
+                               vm_map_lock_write_to_read(target_map);
                        }
                }
 
@@ -1749,6 +2572,8 @@ redo_lookup:
                                wimg_mode = VM_WIMG_IO;
                        } else if (access == MAP_MEM_COPYBACK) {
                                wimg_mode = VM_WIMG_USE_DEFAULT;
+                       } else if (access == MAP_MEM_INNERWBACK) {
+                               wimg_mode = VM_WIMG_INNERWBACK;
                        } else if (access == MAP_MEM_WTHRU) {
                                wimg_mode = VM_WIMG_WTHRU;
                        } else if (access == MAP_MEM_WCOMB) {
@@ -1756,39 +2581,39 @@ redo_lookup:
                        }
                }
 
+#if VM_OBJECT_TRACKING_OP_TRUESHARE
+               if (!object->true_share &&
+                   vm_object_tracking_inited) {
+                       void *bt[VM_OBJECT_TRACKING_BTDEPTH];
+                       int num = 0;
+
+                       num = OSBacktrace(bt,
+                                         VM_OBJECT_TRACKING_BTDEPTH);
+                       btlog_add_entry(vm_object_tracking_btlog,
+                                       object,
+                                       VM_OBJECT_TRACKING_OP_TRUESHARE,
+                                       bt,
+                                       num);
+               }
+#endif /* VM_OBJECT_TRACKING_OP_TRUESHARE */
+
                object->true_share = TRUE;
                if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC)
                        object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
 
-               /* we now point to this object, hold on to it */
-               vm_object_reference_locked(object);
+               /*
+                * The memory entry now points to this VM object and we
+                * need to hold a reference on the VM object.  Use the extra
+                * reference we took earlier to keep the object alive when we
+                * had to unlock it.
+                */
+
                vm_map_unlock_read(target_map);
-               if(pmap_map != target_map)
-                       vm_map_unlock_read(pmap_map);
-
-               if(object->wimg_bits != wimg_mode) {
-                       vm_page_t p;
-
-                       vm_object_paging_wait(object, THREAD_UNINT);
-
-                       queue_iterate(&object->memq, 
-                                               p, vm_page_t, listq) {
-                               if (!p->fictitious) {
-                                       pmap_page_protect(
-                                               p->phys_page, 
-                                               VM_PROT_NONE);
-                                        if(cache_attr)
-                                           pmap_sync_caches_phys(
-                                                       p->phys_page);
-                               }
-                       }
-                       object->wimg_bits = wimg_mode;
-               }
-               user_object->object = object;
-               user_object->internal = object->internal;
-               user_object->is_sub_map = FALSE;
-               user_object->offset = obj_off;
-               user_object->protection = permission;
+               if(real_map != target_map)
+                       vm_map_unlock_read(real_map);
+
+               if (object->wimg_bits != wimg_mode)
+                       vm_object_change_wimg_mode(object, wimg_mode);
 
                /* the size of mapped entry that overlaps with our region */
                /* which is targeted for share.                           */
@@ -1796,77 +2621,211 @@ redo_lookup:
                /*                   offset of our beg addr within entry  */
                /* it corresponds to this:                                */
 
-               if(*size > mappable_size)
-                       *size = mappable_size;
+               if(map_size > mappable_size)
+                       map_size = mappable_size;
 
-               user_object->size = *size;
+               if (permission & MAP_MEM_NAMED_REUSE) {
+                       /*
+                        * Compare what we got with the "parent_entry".
+                        * If they match, re-use the "parent_entry" instead
+                        * of creating a new one.
+                        */
+                       if (parent_entry != NULL &&
+                           parent_entry->backing.object == object &&
+                           parent_entry->internal == object->internal &&
+                           parent_entry->is_sub_map == FALSE &&
+                           parent_entry->is_pager == FALSE &&
+                           parent_entry->offset == obj_off &&
+                           parent_entry->protection == protections &&
+                           parent_entry->size == map_size &&
+                           ((!use_data_addr && (parent_entry->data_offset == 0)) ||  
+                            (use_data_addr && (parent_entry->data_offset == offset_in_page)))) {
+                               /*
+                                * We have a match: re-use "parent_entry".
+                                */
+                               /* release our extra reference on object */
+                               vm_object_unlock(object);
+                               vm_object_deallocate(object);
+                               /* parent_entry->ref_count++; XXX ? */
+                               /* Get an extra send-right on handle */
+                               ipc_port_copy_send(parent_handle);
+
+                               *size = CAST_DOWN(vm_size_t, map_size);
+                               *object_handle = parent_handle;
+                               return KERN_SUCCESS;
+                       } else {
+                               /*
+                                * No match: we need to create a new entry.
+                                * fall through...
+                                */
+                       }
+               }
+
+               vm_object_unlock(object);
+               if (mach_memory_entry_allocate(&user_entry, &user_handle)
+                   != KERN_SUCCESS) {
+                       /* release our unused reference on the object */
+                       vm_object_deallocate(object);
+                       return KERN_FAILURE;
+               }
+
+               user_entry->backing.object = object;
+               user_entry->internal = object->internal;
+               user_entry->is_sub_map = FALSE;
+               user_entry->is_pager = FALSE;
+               user_entry->offset = obj_off;
+               user_entry->data_offset = offset_in_page;
+               user_entry->protection = protections;
+               SET_MAP_MEM(GET_MAP_MEM(permission), user_entry->protection);
+               user_entry->size = map_size;
 
                /* user_object pager and internal fields are not used */
                /* when the object field is filled in.                */
 
-               vm_object_unlock(object);
-               ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
-                                                       IKOT_NAMED_ENTRY);
+               *size = CAST_DOWN(vm_size_t, map_size);
                *object_handle = user_handle;
                return KERN_SUCCESS;
-       } else {
-
-               vm_named_entry_t        parent_object;
 
+       } else {
                /* The new object will be base on an existing named object */
-               if(ip_kotype(parent_entry) != IKOT_NAMED_ENTRY) {
+               if (parent_entry == NULL) {
                        kr = KERN_INVALID_ARGUMENT;
                        goto make_mem_done;
                }
-               parent_object =  (vm_named_entry_t)parent_entry->ip_kobject;
-               if((offset + *size) > parent_object->size) {
-                       kr = KERN_INVALID_ARGUMENT;
+
+               if (use_data_addr) {
+                       /*
+                        * submaps and pagers should only be accessible from within
+                        * the kernel, which shouldn't use the data address flag, so can fail here.
+                        */
+                       if (parent_entry->is_pager || parent_entry->is_sub_map) {
+                               panic("Shouldn't be using data address with a parent entry that is a submap or pager.");
+                       }
+                       /*
+                        * Account for offset to data in parent entry and
+                        * compute our own offset to data.
+                        */
+                       if((offset + *size + parent_entry->data_offset) > parent_entry->size) {
+                               kr = KERN_INVALID_ARGUMENT;
+                               goto make_mem_done;
+                       }
+
+                       map_offset = vm_map_trunc_page(offset + parent_entry->data_offset, PAGE_MASK);
+                       offset_in_page = (offset + parent_entry->data_offset) - map_offset;
+                       map_size = vm_map_round_page(offset + parent_entry->data_offset + *size, PAGE_MASK) - map_offset;
+               } else {
+                       map_size = vm_map_round_page(*size, PAGE_MASK);
+                       offset_in_page = 0;
+
+                       if((offset + map_size) > parent_entry->size) {
+                               kr = KERN_INVALID_ARGUMENT;
+                               goto make_mem_done;
+                       }
+               }
+
+               if (mask_protections) {
+                       /*
+                        * The caller asked us to use the "protections" as
+                        * a mask, so restrict "protections" to what this
+                        * mapping actually allows.
+                        */
+                       protections &= parent_entry->protection;
+               }
+               if((protections & parent_entry->protection) != protections) {
+                       kr = KERN_PROTECTION_FAILURE;
+                       goto make_mem_done;
+               }
+
+               if (mach_memory_entry_allocate(&user_entry, &user_handle)
+                   != KERN_SUCCESS) {
+                       kr = KERN_FAILURE;
                        goto make_mem_done;
                }
 
-               user_object->object = parent_object->object;
-               user_object->size = *size;
-               user_object->offset = parent_object->offset + offset;
-               user_object->protection = parent_object->protection;
-               user_object->protection &= ~VM_PROT_ALL;
-               user_object->protection = permission & VM_PROT_ALL;
+               user_entry->size = map_size;
+               user_entry->offset = parent_entry->offset + map_offset;
+               user_entry->data_offset = offset_in_page; 
+               user_entry->is_sub_map = parent_entry->is_sub_map;
+               user_entry->is_pager = parent_entry->is_pager;
+               user_entry->is_copy = parent_entry->is_copy;
+               user_entry->internal = parent_entry->internal;
+               user_entry->protection = protections;
+
                if(access != MAP_MEM_NOOP) {
-                       SET_MAP_MEM(access, user_object->protection);
+                  SET_MAP_MEM(access, user_entry->protection);
                }
-               if(parent_object->is_sub_map) {
-                  user_object->backing.map = parent_object->backing.map;
-                  vm_map_lock(user_object->backing.map);
-                  user_object->backing.map->ref_count++;
-                  vm_map_unlock(user_object->backing.map);
+
+               if(parent_entry->is_sub_map) {
+                  user_entry->backing.map = parent_entry->backing.map;
+                  vm_map_lock(user_entry->backing.map);
+                  user_entry->backing.map->ref_count++;
+                  vm_map_unlock(user_entry->backing.map);
                }
-               else {
-                  user_object->backing.pager = parent_object->backing.pager;
+               else if (parent_entry->is_pager) {
+                  user_entry->backing.pager = parent_entry->backing.pager;
+                  /* JMM - don't we need a reference here? */
+               } else {
+                  object = parent_entry->backing.object;
+                  assert(object != VM_OBJECT_NULL);
+                  user_entry->backing.object = object;
+                  /* we now point to this object, hold on */
+                  vm_object_reference(object); 
+                  vm_object_lock(object);
+#if VM_OBJECT_TRACKING_OP_TRUESHARE
+               if (!object->true_share &&
+                   vm_object_tracking_inited) {
+                       void *bt[VM_OBJECT_TRACKING_BTDEPTH];
+                       int num = 0;
+
+                       num = OSBacktrace(bt,
+                                         VM_OBJECT_TRACKING_BTDEPTH);
+                       btlog_add_entry(vm_object_tracking_btlog,
+                                       object,
+                                       VM_OBJECT_TRACKING_OP_TRUESHARE,
+                                       bt,
+                                       num);
                }
-               user_object->internal = parent_object->internal;
-               user_object->is_sub_map = parent_object->is_sub_map;
-
-               if(parent_object->object != NULL) {
-                       /* we now point to this object, hold on */
-                       vm_object_reference(parent_object->object); 
-                       vm_object_lock(parent_object->object);
-                       parent_object->object->true_share = TRUE;
-                       if (parent_object->object->copy_strategy == 
-                           MEMORY_OBJECT_COPY_SYMMETRIC)
-                               parent_object->object->copy_strategy =
-                                       MEMORY_OBJECT_COPY_DELAY;
-                       vm_object_unlock(parent_object->object);
+#endif /* VM_OBJECT_TRACKING_OP_TRUESHARE */
+
+                  object->true_share = TRUE;
+                  if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC)
+                       object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
+                  vm_object_unlock(object);
                }
-               ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
-                                                       IKOT_NAMED_ENTRY);
+               *size = CAST_DOWN(vm_size_t, map_size);
                *object_handle = user_handle;
                return KERN_SUCCESS;
        }
 
-
-
 make_mem_done:
-       ipc_port_dealloc_kernel(user_handle);
-       kfree((vm_offset_t)user_object, sizeof (struct vm_named_entry));
+       if (user_handle != IP_NULL) {
+               /*
+                * Releasing "user_handle" causes the kernel object
+                * associated with it ("user_entry" here) to also be
+                * released and freed.
+                */
+               mach_memory_entry_port_release(user_handle);
+       }
+       return kr;
+}
+
+kern_return_t
+_mach_make_memory_entry(
+       vm_map_t                target_map,
+       memory_object_size_t    *size,
+       memory_object_offset_t  offset,
+       vm_prot_t               permission,
+       ipc_port_t              *object_handle,
+       ipc_port_t              parent_entry)
+{
+       memory_object_size_t    mo_size;
+       kern_return_t           kr;
+       
+       mo_size = (memory_object_size_t)*size;
+       kr = mach_make_memory_entry_64(target_map, &mo_size, 
+                       (memory_object_offset_t)offset, permission, object_handle,
+                       parent_entry);
+       *size = mo_size;
        return kr;
 }
 
@@ -1878,43 +2837,62 @@ mach_make_memory_entry(
        vm_prot_t               permission,
        ipc_port_t              *object_handle,
        ipc_port_t              parent_entry)
-{
-       vm_object_offset_t      size_64;
+{      
+       memory_object_size_t    mo_size;
        kern_return_t           kr;
        
-       size_64 = (vm_object_offset_t)*size;
-       kr = mach_make_memory_entry_64(target_map, &size_64
-                       (vm_object_offset_t)offset, permission, object_handle,
+       mo_size = (memory_object_size_t)*size;
+       kr = mach_make_memory_entry_64(target_map, &mo_size
+                       (memory_object_offset_t)offset, permission, object_handle,
                        parent_entry);
-       *size = (vm_size_t)size_64;
+       *size = CAST_DOWN(vm_size_t, mo_size);
        return kr;
 }
 
 /*
+ *     task_wire
+ *
+ *     Set or clear the map's wiring_required flag.  This flag, if set,
+ *     will cause all future virtual memory allocation to allocate
+ *     user wired memory.  Unwiring pages wired down as a result of
+ *     this routine is done with the vm_wire interface.
  */
-
 kern_return_t
-vm_region_object_create(
-       vm_map_t                target_map,
-       vm_size_t               size,
-       ipc_port_t              *object_handle)
+task_wire(
+       vm_map_t        map,
+       boolean_t       must_wire)
+{
+       if (map == VM_MAP_NULL)
+               return(KERN_INVALID_ARGUMENT);
+
+       if (must_wire)
+               map->wiring_required = TRUE;
+       else
+               map->wiring_required = FALSE;
+
+       return(KERN_SUCCESS);
+}
+
+__private_extern__ kern_return_t
+mach_memory_entry_allocate(
+       vm_named_entry_t        *user_entry_p,
+       ipc_port_t              *user_handle_p)
 {
-       vm_named_entry_t        user_object;
+       vm_named_entry_t        user_entry;
        ipc_port_t              user_handle;
-       kern_return_t           kr;
+       ipc_port_t              previous;
 
-       ipc_port_t      previous;
-       vm_map_t        new_map;
-       
-       user_object = (vm_named_entry_t) 
-                       kalloc(sizeof (struct vm_named_entry));
-       if(user_object == NULL) {
+       user_entry = (vm_named_entry_t) kalloc(sizeof *user_entry);
+       if (user_entry == NULL)
                return KERN_FAILURE;
-       }
-       named_entry_lock_init(user_object);
-       user_handle = ipc_port_alloc_kernel();
 
+       named_entry_lock_init(user_entry);
 
+       user_handle = ipc_port_alloc_kernel();
+       if (user_handle == IP_NULL) {
+               kfree(user_entry, sizeof *user_entry);
+               return KERN_FAILURE;
+       }
        ip_lock(user_handle);
 
        /* make a sonce right */
@@ -1933,126 +2911,217 @@ vm_region_object_create(
        ipc_port_nsrequest(user_handle, 1, user_handle, &previous);
        /* nsrequest unlocks user_handle */
 
-       /* Create a named object based on a submap of specified size */
+       user_entry->backing.pager = NULL;
+       user_entry->is_sub_map = FALSE;
+       user_entry->is_pager = FALSE;
+       user_entry->is_copy = FALSE;
+       user_entry->internal = FALSE;
+       user_entry->size = 0;
+       user_entry->offset = 0;
+       user_entry->data_offset = 0;
+       user_entry->protection = VM_PROT_NONE;
+       user_entry->ref_count = 1;
 
-       new_map = vm_map_create(0, 0, size, TRUE);
-       user_object->backing.map = new_map;
+       ipc_kobject_set(user_handle, (ipc_kobject_t) user_entry,
+                       IKOT_NAMED_ENTRY);
 
+       *user_entry_p = user_entry;
+       *user_handle_p = user_handle;
 
-       user_object->object = VM_OBJECT_NULL;
-       user_object->internal = TRUE;
-       user_object->is_sub_map = TRUE;
-       user_object->offset = 0;
-       user_object->protection = VM_PROT_ALL;
-       user_object->size = size;
-       user_object->ref_count = 1;
+       return KERN_SUCCESS;
+}
 
-       ipc_kobject_set(user_handle, (ipc_kobject_t) user_object,
-                                                       IKOT_NAMED_ENTRY);
-       *object_handle = user_handle;
+/*
+ *     mach_memory_object_memory_entry_64
+ *
+ *     Create a named entry backed by the provided pager.
+ *
+ *     JMM - we need to hold a reference on the pager -
+ *     and release it when the named entry is destroyed.
+ */
+kern_return_t
+mach_memory_object_memory_entry_64(
+       host_t                  host,
+       boolean_t               internal,
+       vm_object_offset_t      size,
+       vm_prot_t               permission,
+       memory_object_t         pager,
+       ipc_port_t              *entry_handle)
+{
+       unsigned int            access;
+       vm_named_entry_t        user_entry;
+       ipc_port_t              user_handle;
+
+        if (host == HOST_NULL)
+                return(KERN_INVALID_HOST);
+
+       if (mach_memory_entry_allocate(&user_entry, &user_handle)
+           != KERN_SUCCESS) {
+               return KERN_FAILURE;
+       }
+
+       user_entry->backing.pager = pager;
+       user_entry->size = size;
+       user_entry->offset = 0;
+       user_entry->protection = permission & VM_PROT_ALL;
+       access = GET_MAP_MEM(permission);
+       SET_MAP_MEM(access, user_entry->protection);
+       user_entry->internal = internal;
+       user_entry->is_sub_map = FALSE;
+       user_entry->is_pager = TRUE;
+       assert(user_entry->ref_count == 1);
+
+       *entry_handle = user_handle;
        return KERN_SUCCESS;
+}      
 
+kern_return_t
+mach_memory_object_memory_entry(
+       host_t          host,
+       boolean_t       internal,
+       vm_size_t       size,
+       vm_prot_t       permission,
+       memory_object_t pager,
+       ipc_port_t      *entry_handle)
+{
+       return mach_memory_object_memory_entry_64( host, internal, 
+               (vm_object_offset_t)size, permission, pager, entry_handle);
 }
 
-/* For a given range, check all map entries.  If the entry coresponds to */
-/* the old vm_region/map provided on the call, replace it with the      */
-/* corresponding range in the new vm_region/map */
-kern_return_t vm_map_region_replace(
-       vm_map_t        target_map,
-       ipc_port_t      old_region, 
-       ipc_port_t      new_region,
-       vm_offset_t     start,
-       vm_offset_t     end)
+
+kern_return_t
+mach_memory_entry_purgable_control(
+       ipc_port_t      entry_port,
+       vm_purgable_t   control,
+       int             *state)
 {
-       vm_named_entry_t        old_object;
-       vm_named_entry_t        new_object;
-       vm_map_t                old_submap;
-       vm_map_t                new_submap;
-       vm_offset_t             addr;
-       vm_map_entry_t          entry;
-       int                     nested_pmap = 0;
+       kern_return_t           kr;
+       vm_named_entry_t        mem_entry;
+       vm_object_t             object;
 
+       if (entry_port == IP_NULL ||
+           ip_kotype(entry_port) != IKOT_NAMED_ENTRY) {
+               return KERN_INVALID_ARGUMENT;
+       }
+       if (control != VM_PURGABLE_SET_STATE &&
+           control != VM_PURGABLE_GET_STATE)
+               return(KERN_INVALID_ARGUMENT);
+
+       if (control == VM_PURGABLE_SET_STATE &&
+           (((*state & ~(VM_PURGABLE_ALL_MASKS)) != 0) ||
+            ((*state & VM_PURGABLE_STATE_MASK) > VM_PURGABLE_STATE_MASK)))
+               return(KERN_INVALID_ARGUMENT);
+
+       mem_entry = (vm_named_entry_t) entry_port->ip_kobject;
 
-       vm_map_lock(target_map);
-       old_object = (vm_named_entry_t)old_region->ip_kobject;
-       new_object = (vm_named_entry_t)new_region->ip_kobject;
-       if((!old_object->is_sub_map) || (!new_object->is_sub_map)) {
-               vm_map_unlock(target_map);
+       named_entry_lock(mem_entry);
+
+       if (mem_entry->is_sub_map ||
+           mem_entry->is_pager ||
+           mem_entry->is_copy) {
+               named_entry_unlock(mem_entry);
                return KERN_INVALID_ARGUMENT;
        }
-       old_submap = (vm_map_t)old_object->backing.map;
-       new_submap = (vm_map_t)new_object->backing.map;
-       vm_map_lock(old_submap);
-       if((old_submap->min_offset != new_submap->min_offset) || 
-                       (old_submap->max_offset != new_submap->max_offset)) {
-               vm_map_unlock(old_submap);
-               vm_map_unlock(target_map);
+
+       object = mem_entry->backing.object;
+       if (object == VM_OBJECT_NULL) {
+               named_entry_unlock(mem_entry);
                return KERN_INVALID_ARGUMENT;
        }
-       if(!vm_map_lookup_entry(target_map, start, &entry)) {
-               /* if the src is not contained, the entry preceeds */
-               /* our range */
-               addr = entry->vme_start;
-               if(entry == vm_map_to_entry(target_map)) {
-                       vm_map_unlock(old_submap);
-                       vm_map_unlock(target_map);
-                       return KERN_SUCCESS;
-               }
+
+       vm_object_lock(object);
+
+       /* check that named entry covers entire object ? */
+       if (mem_entry->offset != 0 || object->vo_size != mem_entry->size) {
+               vm_object_unlock(object);
+               named_entry_unlock(mem_entry);
+               return KERN_INVALID_ARGUMENT;
        }
-       if ((entry->use_pmap) && 
-                       (new_submap->pmap == NULL)) {
-               new_submap->pmap = pmap_create((vm_size_t) 0);
-               if(new_submap->pmap == PMAP_NULL) {
-                       vm_map_unlock(old_submap);
-                       vm_map_unlock(target_map);
-                       return(KERN_NO_SPACE);
-               }
+
+       named_entry_unlock(mem_entry);
+
+       kr = vm_object_purgable_control(object, control, state);
+
+       vm_object_unlock(object);
+
+       return kr;
+}
+
+kern_return_t
+mach_memory_entry_get_page_counts(
+       ipc_port_t      entry_port,
+       unsigned int    *resident_page_count,
+       unsigned int    *dirty_page_count)
+{
+       kern_return_t           kr;
+       vm_named_entry_t        mem_entry;
+       vm_object_t             object;
+       vm_object_offset_t      offset;
+       vm_object_size_t        size;
+
+       if (entry_port == IP_NULL ||
+           ip_kotype(entry_port) != IKOT_NAMED_ENTRY) {
+               return KERN_INVALID_ARGUMENT;
        }
-       addr = entry->vme_start;
-       vm_map_reference(old_submap);
-       while((entry != vm_map_to_entry(target_map)) && 
-                                       (entry->vme_start < end)) {
-               if((entry->is_sub_map) && 
-                       (entry->object.sub_map == old_submap)) {
-                       if(entry->use_pmap) {
-                               if((start & 0x0fffffff) || 
-                                       ((end - start) != 0x10000000)) {
-                                       vm_map_unlock(old_submap);
-                                       vm_map_deallocate(old_submap);
-                                       vm_map_unlock(target_map);
-                                       return  KERN_INVALID_ARGUMENT;
-                               }
-                               nested_pmap = 1;
-                       }
-                       entry->object.sub_map = new_submap;
-                       vm_map_reference(new_submap);
-                       vm_map_deallocate(old_submap);
-               }
-               entry = entry->vme_next;
-               addr = entry->vme_start;
+
+       mem_entry = (vm_named_entry_t) entry_port->ip_kobject;
+
+       named_entry_lock(mem_entry);
+
+       if (mem_entry->is_sub_map ||
+           mem_entry->is_pager ||
+           mem_entry->is_copy) {
+               named_entry_unlock(mem_entry);
+               return KERN_INVALID_ARGUMENT;
        }
-       if(nested_pmap) {
-#ifndef i386
-               pmap_unnest(target_map->pmap, (addr64_t)start);
-               if(target_map->mapped) {
-                       vm_map_submap_pmap_clean(target_map,
-                               start, end, old_submap, 0);
-               }
-               pmap_nest(target_map->pmap, new_submap->pmap, 
-                               (addr64_t)start, (addr64_t)start, 
-                               (addr64_t)(end - start));
-#endif /* i386 */
-       } else {
-               vm_map_submap_pmap_clean(target_map,
-                               start, end, old_submap, 0);
+
+       object = mem_entry->backing.object;
+       if (object == VM_OBJECT_NULL) {
+               named_entry_unlock(mem_entry);
+               return KERN_INVALID_ARGUMENT;
        }
-       vm_map_unlock(old_submap);
-       vm_map_deallocate(old_submap);
-       vm_map_unlock(target_map);
-       return KERN_SUCCESS;
+
+       vm_object_lock(object);
+
+       offset = mem_entry->offset;
+       size = mem_entry->size;
+
+       named_entry_unlock(mem_entry);
+
+       kr = vm_object_get_page_counts(object, offset, size, resident_page_count, dirty_page_count);
+
+       vm_object_unlock(object);
+
+       return kr;
 }
 
+/*
+ * mach_memory_entry_port_release:
+ *
+ * Release a send right on a named entry port.  This is the correct
+ * way to destroy a named entry.  When the last right on the port is
+ * released, ipc_kobject_destroy() will call mach_destroy_memory_entry().
+ */
+void
+mach_memory_entry_port_release(
+       ipc_port_t      port)
+{
+       assert(ip_kotype(port) == IKOT_NAMED_ENTRY);
+       ipc_port_release_send(port);
+}
 
+/*
+ * mach_destroy_memory_entry:
+ *
+ * Drops a reference on a memory entry and destroys the memory entry if
+ * there are no more references on it.
+ * NOTE: This routine should not be called to destroy a memory entry from the
+ * kernel, as it will not release the Mach port associated with the memory
+ * entry.  The proper way to destroy a memory entry in the kernel is to
+ * call mach_memort_entry_port_release() to release the kernel's send-right on
+ * the memory entry's port.  When the last send right is released, the memory
+ * entry will be destroyed via ipc_kobject_destroy().
+ */
 void
 mach_destroy_memory_entry(
        ipc_port_t      port)
@@ -2062,109 +3131,137 @@ mach_destroy_memory_entry(
        assert(ip_kotype(port) == IKOT_NAMED_ENTRY);
 #endif /* MACH_ASSERT */
        named_entry = (vm_named_entry_t)port->ip_kobject;
-       mutex_lock(&(named_entry)->Lock);
-       named_entry->ref_count-=1;
+
+       named_entry_lock(named_entry);
+       named_entry->ref_count -= 1;
+
        if(named_entry->ref_count == 0) {
-               if(named_entry->object) {
-                       /* release the memory object we've been pointing to */
-                       vm_object_deallocate(named_entry->object);
-               }
-               if(named_entry->is_sub_map) {
+               if (named_entry->is_sub_map) {
                        vm_map_deallocate(named_entry->backing.map);
+               } else if (named_entry->is_pager) {
+                       /* JMM - need to drop reference on pager in that case */
+               } else if (named_entry->is_copy) {
+                       vm_map_copy_discard(named_entry->backing.copy);
+               } else {
+                       /* release the VM object we've been pointing to */
+                       vm_object_deallocate(named_entry->backing.object);
                }
-               kfree((vm_offset_t)port->ip_kobject, 
-                               sizeof (struct vm_named_entry));
+
+               named_entry_unlock(named_entry);
+               named_entry_lock_destroy(named_entry);
+
+               kfree((void *) port->ip_kobject,
+                     sizeof (struct vm_named_entry));
        } else
-               mutex_unlock(&(named_entry)->Lock);
+               named_entry_unlock(named_entry);
 }
 
+/* Allow manipulation of individual page state.  This is actually part of */
+/* the UPL regimen but takes place on the memory entry rather than on a UPL */
 
 kern_return_t
-vm_map_page_query(
-       vm_map_t                target_map,
-       vm_offset_t             offset,
-       int                     *disposition,
-       int                     *ref_count)
+mach_memory_entry_page_op(
+       ipc_port_t              entry_port,
+       vm_object_offset_t      offset,
+       int                     ops,
+       ppnum_t                 *phys_entry,
+       int                     *flags)
 {
-       vm_map_entry_t  map_entry;
-       vm_object_t     object;
-       vm_page_t       m;
+       vm_named_entry_t        mem_entry;
+       vm_object_t             object;
+       kern_return_t           kr;
 
-restart_page_query:
-       *disposition = 0;
-       *ref_count = 0;
-       vm_map_lock(target_map);
-       if(!vm_map_lookup_entry(target_map, offset, &map_entry)) {
-               vm_map_unlock(target_map);
-               return KERN_FAILURE;
+       if (entry_port == IP_NULL ||
+           ip_kotype(entry_port) != IKOT_NAMED_ENTRY) {
+               return KERN_INVALID_ARGUMENT;
        }
-       offset -= map_entry->vme_start;  /* adjust to offset within entry */
-       offset += map_entry->offset;     /* adjust to target object offset */
-       if(map_entry->object.vm_object != VM_OBJECT_NULL) {
-               if(!map_entry->is_sub_map) {
-                       object = map_entry->object.vm_object;
-               } else {
-                       vm_map_unlock(target_map);
-                       target_map = map_entry->object.sub_map;
-                       goto restart_page_query;
-               }
-       } else {
-               vm_map_unlock(target_map);
-               return KERN_FAILURE;
+
+       mem_entry = (vm_named_entry_t) entry_port->ip_kobject;
+
+       named_entry_lock(mem_entry);
+
+       if (mem_entry->is_sub_map ||
+           mem_entry->is_pager ||
+           mem_entry->is_copy) {
+               named_entry_unlock(mem_entry);
+               return KERN_INVALID_ARGUMENT;
        }
-       vm_object_lock(object);
-       vm_map_unlock(target_map);
-       while(TRUE) {
-               m = vm_page_lookup(object, offset);
-               if (m != VM_PAGE_NULL) {
-                       *disposition |= VM_PAGE_QUERY_PAGE_PRESENT;
-                       break;
-               } else {
-                       if(object->shadow) {
-                               offset += object->shadow_offset;
-                               vm_object_unlock(object);
-                               object = object->shadow;
-                               vm_object_lock(object);
-                               continue;
-                       }
-                       vm_object_unlock(object);
-                       return KERN_FAILURE;
-               }
+
+       object = mem_entry->backing.object;
+       if (object == VM_OBJECT_NULL) {
+               named_entry_unlock(mem_entry);
+               return KERN_INVALID_ARGUMENT;
        }
 
-       /* The ref_count is not strictly accurate, it measures the number   */
-       /* of entities holding a ref on the object, they may not be mapping */
-       /* the object or may not be mapping the section holding the         */
-       /* target page but its still a ball park number and though an over- */
-       /* count, it picks up the copy-on-write cases                       */
+       vm_object_reference(object);
+       named_entry_unlock(mem_entry);
 
-       /* We could also get a picture of page sharing from pmap_attributes */
-       /* but this would under count as only faulted-in mappings would     */
-       /* show up.                                                         */
+       kr = vm_object_page_op(object, offset, ops, phys_entry, flags);
 
-       *ref_count = object->ref_count;
+       vm_object_deallocate(object);   
 
-       if (m->fictitious) {
-               *disposition |= VM_PAGE_QUERY_PAGE_FICTITIOUS;
-               vm_object_unlock(object);
-               return KERN_SUCCESS;
+       return kr;
+}
+
+/*
+ * mach_memory_entry_range_op offers performance enhancement over 
+ * mach_memory_entry_page_op for page_op functions which do not require page 
+ * level state to be returned from the call.  Page_op was created to provide 
+ * a low-cost alternative to page manipulation via UPLs when only a single 
+ * page was involved.  The range_op call establishes the ability in the _op 
+ * family of functions to work on multiple pages where the lack of page level
+ * state handling allows the caller to avoid the overhead of the upl structures.
+ */
+
+kern_return_t
+mach_memory_entry_range_op(
+       ipc_port_t              entry_port,
+       vm_object_offset_t      offset_beg,
+       vm_object_offset_t      offset_end,
+       int                     ops,
+       int                     *range)
+{
+       vm_named_entry_t        mem_entry;
+       vm_object_t             object;
+       kern_return_t           kr;
+
+       if (entry_port == IP_NULL ||
+           ip_kotype(entry_port) != IKOT_NAMED_ENTRY) {
+               return KERN_INVALID_ARGUMENT;
        }
 
-       if (m->dirty)
-               *disposition |= VM_PAGE_QUERY_PAGE_DIRTY;
-       else if(pmap_is_modified(m->phys_page))
-               *disposition |= VM_PAGE_QUERY_PAGE_DIRTY;
+       mem_entry = (vm_named_entry_t) entry_port->ip_kobject;
 
-       if (m->reference)
-               *disposition |= VM_PAGE_QUERY_PAGE_REF;
-       else if(pmap_is_referenced(m->phys_page))
-               *disposition |= VM_PAGE_QUERY_PAGE_REF;
+       named_entry_lock(mem_entry);
 
-       vm_object_unlock(object);
-       return KERN_SUCCESS;
-       
+       if (mem_entry->is_sub_map ||
+           mem_entry->is_pager ||
+           mem_entry->is_copy) {
+               named_entry_unlock(mem_entry);
+               return KERN_INVALID_ARGUMENT;
+       }
+
+       object = mem_entry->backing.object;
+       if (object == VM_OBJECT_NULL) {
+               named_entry_unlock(mem_entry);
+               return KERN_INVALID_ARGUMENT;
+       }
+
+       vm_object_reference(object);
+       named_entry_unlock(mem_entry);
+
+       kr = vm_object_range_op(object,
+                               offset_beg,
+                               offset_end,
+                               ops,
+                               (uint32_t *) range);
+
+       vm_object_deallocate(object);
+
+       return kr;
 }
 
+
 kern_return_t
 set_dp_control_port(
        host_priv_t     host_priv,
@@ -2193,234 +3290,48 @@ get_dp_control_port(
        
 }
 
+/* ******* Temporary Internal calls to UPL for BSD ***** */
 
-/* Retrieve a upl for an object underlying an address range in a map */
-
-kern_return_t
-vm_map_get_upl(
-       vm_map_t                map,
-       vm_address_t            offset,
-       vm_size_t               *upl_size,
-       upl_t                   *upl,
-       upl_page_info_array_t   page_list,
-       unsigned int            *count,
-       int                     *flags,
-       int                     force_data_sync)
-{
-       vm_map_entry_t  entry;
-       int             caller_flags;
-       int             sync_cow_data = FALSE;
-       vm_object_t     local_object;
-       vm_offset_t     local_offset;
-       vm_offset_t     local_start;
-       kern_return_t   ret;
-
-       caller_flags = *flags;
-       if (!(caller_flags & UPL_COPYOUT_FROM)) {
-               sync_cow_data = TRUE;
-       }
-       if(upl == NULL)
-               return KERN_INVALID_ARGUMENT;
-
-
-REDISCOVER_ENTRY:
-       vm_map_lock(map);
-       if (vm_map_lookup_entry(map, offset, &entry)) {
-               if (entry->object.vm_object == VM_OBJECT_NULL ||
-                       !entry->object.vm_object->phys_contiguous) {
-                       if((*upl_size/page_size) > MAX_UPL_TRANSFER) {
-                                       *upl_size = MAX_UPL_TRANSFER * page_size;
-                       }
-               }
-               if((entry->vme_end - offset) < *upl_size) {
-                       *upl_size = entry->vme_end - offset;
-               }
-               if (caller_flags & UPL_QUERY_OBJECT_TYPE) {
-                       if (entry->object.vm_object == VM_OBJECT_NULL) {
-                               *flags = 0;
-                       } else if (entry->object.vm_object->private) {
-                               *flags = UPL_DEV_MEMORY;
-                               if (entry->object.vm_object->phys_contiguous) {
-                                       *flags |= UPL_PHYS_CONTIG;
-                               }
-                       } else  {
-                               *flags = 0;
-                       }
-                       vm_map_unlock(map);
-                       return KERN_SUCCESS;
-               }
-               /*
-                *      Create an object if necessary.
-                */
-               if (entry->object.vm_object == VM_OBJECT_NULL) {
-                       entry->object.vm_object = vm_object_allocate(
-                               (vm_size_t)(entry->vme_end - entry->vme_start));
-                       entry->offset = 0;
-               }
-               if (!(caller_flags & UPL_COPYOUT_FROM)) {
-                       if (!(entry->protection & VM_PROT_WRITE)) {
-                               vm_map_unlock(map);
-                               return KERN_PROTECTION_FAILURE;
-                       }
-                       if (entry->needs_copy)  {
-                               vm_map_t                local_map;
-                               vm_object_t             object;
-                               vm_object_offset_t      offset_hi;
-                               vm_object_offset_t      offset_lo;
-                               vm_object_offset_t      new_offset;
-                               vm_prot_t               prot;
-                               boolean_t               wired;
-                               vm_behavior_t           behavior;
-                               vm_map_version_t         version;
-                               vm_map_t                pmap_map;
-
-                               local_map = map;
-                               vm_map_lock_write_to_read(map);
-                               if(vm_map_lookup_locked(&local_map,
-                                       offset, VM_PROT_WRITE,
-                                       &version, &object,
-                                       &new_offset, &prot, &wired,
-                                       &behavior, &offset_lo,
-                                       &offset_hi, &pmap_map)) {
-                                       vm_map_unlock(local_map);
-                                       return KERN_FAILURE;
-                               }
-                               if (pmap_map != map) {
-                                       vm_map_unlock(pmap_map);
-                               }
-                               vm_object_unlock(object);
-                               vm_map_unlock(local_map);
-
-                               goto REDISCOVER_ENTRY;
-                       }
-               }
-               if (entry->is_sub_map) {
-                       vm_map_t        submap;
-
-                       submap = entry->object.sub_map;
-                       local_start = entry->vme_start;
-                       local_offset = entry->offset;
-                       vm_map_reference(submap);
-                       vm_map_unlock(map);
-
-                       ret = (vm_map_get_upl(submap, 
-                               local_offset + (offset - local_start), 
-                               upl_size, upl, page_list, count, 
-                               flags, force_data_sync));
-
-                       vm_map_deallocate(submap);
-                       return ret;
-               }
-                                       
-               if (sync_cow_data) {
-                       if (entry->object.vm_object->shadow
-                                   || entry->object.vm_object->copy) {
-                               int             flags;
-
-                               local_object = entry->object.vm_object;
-                               local_start = entry->vme_start;
-                               local_offset = entry->offset;
-                               vm_object_reference(local_object);
-                               vm_map_unlock(map);
+extern int kernel_upl_map(
+       vm_map_t        map,
+       upl_t           upl,
+       vm_offset_t     *dst_addr);
 
-                               if(local_object->copy == NULL) {
-                                       flags = MEMORY_OBJECT_DATA_SYNC;
-                               } else {
-                                       flags = MEMORY_OBJECT_COPY_SYNC;
-                               }
+extern int kernel_upl_unmap(
+       vm_map_t        map,
+       upl_t           upl);
 
-                               if (entry->object.vm_object->shadow && 
-                                          entry->object.vm_object->copy) {
-                                  vm_object_lock_request(
-                                       local_object->shadow,
-                                       (vm_object_offset_t)
-                                       ((offset - local_start) +
-                                        local_offset) +
-                                       local_object->shadow_offset,
-                                       *upl_size, FALSE, 
-                                       MEMORY_OBJECT_DATA_SYNC,
-                                       VM_PROT_NO_CHANGE);
-                               }
-                               sync_cow_data = FALSE;
-                               vm_object_deallocate(local_object);
-                               goto REDISCOVER_ENTRY;
-                       }
-               }
+extern int kernel_upl_commit(
+       upl_t                   upl,
+       upl_page_info_t         *pl,
+       mach_msg_type_number_t   count);
 
-               if (force_data_sync) {
-
-                       local_object = entry->object.vm_object;
-                       local_start = entry->vme_start;
-                       local_offset = entry->offset;
-                       vm_object_reference(local_object);
-                       vm_map_unlock(map);
-
-                       vm_object_lock_request(
-                                  local_object,
-                                  (vm_object_offset_t)
-                                  ((offset - local_start) + local_offset),
-                                  (vm_object_size_t)*upl_size, FALSE, 
-                                  MEMORY_OBJECT_DATA_SYNC,
-                                  VM_PROT_NO_CHANGE);
-                       force_data_sync = FALSE;
-                       vm_object_deallocate(local_object);
-                       goto REDISCOVER_ENTRY;
-               }
+extern int kernel_upl_commit_range(
+       upl_t                   upl,
+       upl_offset_t             offset,
+       upl_size_t              size,
+       int                     flags,
+       upl_page_info_array_t   pl,
+       mach_msg_type_number_t  count);
 
-               if(!(entry->object.vm_object->private)) {
-                       if(*upl_size > (MAX_UPL_TRANSFER*PAGE_SIZE))
-                               *upl_size = (MAX_UPL_TRANSFER*PAGE_SIZE);
-                       if(entry->object.vm_object->phys_contiguous) {
-                               *flags = UPL_PHYS_CONTIG;
-                       } else {
-                               *flags = 0;
-                       }
-               } else {
-                       *flags = UPL_DEV_MEMORY | UPL_PHYS_CONTIG;
-               }
-               local_object = entry->object.vm_object;
-               local_offset = entry->offset;
-               local_start = entry->vme_start;
-               vm_object_reference(local_object);
-               vm_map_unlock(map);
-               if(caller_flags & UPL_SET_IO_WIRE) {
-                       ret = (vm_object_iopl_request(local_object, 
-                               (vm_object_offset_t)
-                                  ((offset - local_start) 
-                                               + local_offset),
-                               *upl_size,
-                               upl,
-                               page_list,
-                               count,
-                               caller_flags));
-               } else {
-                       ret = (vm_object_upl_request(local_object, 
-                               (vm_object_offset_t)
-                                  ((offset - local_start) 
-                                               + local_offset),
-                               *upl_size,
-                               upl,
-                               page_list,
-                               count,
-                               caller_flags));
-               }
-               vm_object_deallocate(local_object);
-               return(ret);
-       } 
+extern int kernel_upl_abort(
+       upl_t                   upl,
+       int                     abort_type);
 
-       vm_map_unlock(map);
-       return(KERN_FAILURE);
+extern int kernel_upl_abort_range(
+       upl_t                   upl,
+       upl_offset_t             offset,
+       upl_size_t               size,
+       int                     abort_flags);
 
-}
 
-/* ******* Temporary Internal calls to UPL for BSD ***** */
 kern_return_t
 kernel_upl_map(
        vm_map_t        map,
        upl_t           upl,
        vm_offset_t     *dst_addr)
 {
-       return (vm_upl_map(map, upl, dst_addr));
+       return vm_upl_map(map, upl, dst_addr);
 }
 
 
@@ -2429,13 +3340,13 @@ kernel_upl_unmap(
        vm_map_t        map,
        upl_t           upl)
 {
-       return(vm_upl_unmap(map, upl));
+       return vm_upl_unmap(map, upl);
 }
 
 kern_return_t
 kernel_upl_commit(
-       upl_t                   upl,
-       upl_page_info_t         *pl,
+       upl_t                   upl,
+       upl_page_info_t        *pl,
        mach_msg_type_number_t  count)
 {
        kern_return_t   kr;
@@ -2449,8 +3360,8 @@ kernel_upl_commit(
 kern_return_t
 kernel_upl_commit_range(
        upl_t                   upl,
-       vm_offset_t             offset,
-       vm_size_t               size,
+       upl_offset_t            offset,
+       upl_size_t              size,
        int                     flags,
        upl_page_info_array_t   pl,
        mach_msg_type_number_t  count)
@@ -2461,6 +3372,10 @@ kernel_upl_commit_range(
        if (flags & UPL_COMMIT_FREE_ON_EMPTY)
                flags |= UPL_COMMIT_NOTIFY_EMPTY;
 
+       if (flags & UPL_COMMIT_KERNEL_ONLY_FLAGS) {
+               return KERN_INVALID_ARGUMENT;
+       }
+
        kr = upl_commit_range(upl, offset, size, flags, pl, count, &finished);
 
        if ((flags & UPL_COMMIT_NOTIFY_EMPTY) && finished)
@@ -2472,8 +3387,8 @@ kernel_upl_commit_range(
 kern_return_t
 kernel_upl_abort_range(
        upl_t                   upl,
-       vm_offset_t             offset,
-       vm_size_t               size,
+       upl_offset_t            offset,
+       upl_size_t              size,
        int                     abort_flags)
 {
        kern_return_t           kr;
@@ -2502,237 +3417,79 @@ kernel_upl_abort(
        return kr;
 }
 
+/*
+ * Now a kernel-private interface (for BootCache
+ * use only).  Need a cleaner way to create an
+ * empty vm_map() and return a handle to it.
+ */
 
 kern_return_t
-vm_get_shared_region(
-       task_t  task,
-       shared_region_mapping_t *shared_region)
-{
-       *shared_region = (shared_region_mapping_t) task->system_shared_region;
-       return KERN_SUCCESS;
-}
-
-kern_return_t
-vm_set_shared_region(
-       task_t  task,
-       shared_region_mapping_t shared_region)
-{
-       task->system_shared_region = (vm_offset_t) shared_region;
-       return KERN_SUCCESS;
-}
-
-kern_return_t
-shared_region_mapping_info(
-       shared_region_mapping_t shared_region,
-       ipc_port_t              *text_region,
-       vm_size_t               *text_size,
-       ipc_port_t              *data_region,
-       vm_size_t               *data_size,
-       vm_offset_t             *region_mappings,
-       vm_offset_t             *client_base,
-       vm_offset_t             *alt_base,
-       vm_offset_t             *alt_next,
-       unsigned int            *fs_base,
-       unsigned int            *system,
-       int                     *flags,
-       shared_region_mapping_t *next)
+vm_region_object_create(
+       __unused vm_map_t       target_map,
+       vm_size_t               size,
+       ipc_port_t              *object_handle)
 {
-       shared_region_mapping_lock(shared_region);
-
-       *text_region = shared_region->text_region;
-       *text_size = shared_region->text_size;
-       *data_region = shared_region->data_region;
-       *data_size = shared_region->data_size;
-       *region_mappings = shared_region->region_mappings;
-       *client_base = shared_region->client_base;
-       *alt_base = shared_region->alternate_base;
-       *alt_next = shared_region->alternate_next;
-       *flags = shared_region->flags;
-       *fs_base = shared_region->fs_base;
-       *system = shared_region->system;
-       *next = shared_region->next;
-
-       shared_region_mapping_unlock(shared_region);
-}
+       vm_named_entry_t        user_entry;
+       ipc_port_t              user_handle;
 
-kern_return_t
-shared_region_object_chain_attach(
-       shared_region_mapping_t         target_region,
-       shared_region_mapping_t         object_chain_region)
-{
-       shared_region_object_chain_t    object_ele;
+       vm_map_t        new_map;
        
-       if(target_region->object_chain)
+       if (mach_memory_entry_allocate(&user_entry, &user_handle)
+           != KERN_SUCCESS) {
                return KERN_FAILURE;
-       object_ele = (shared_region_object_chain_t)
-                       kalloc(sizeof (struct shared_region_object_chain));
-       shared_region_mapping_lock(object_chain_region);
-       target_region->object_chain = object_ele;
-       object_ele->object_chain_region = object_chain_region;
-       object_ele->next = object_chain_region->object_chain;
-       object_ele->depth = object_chain_region->depth;
-       object_chain_region->depth++;
-       target_region->alternate_next = object_chain_region->alternate_next;
-       shared_region_mapping_unlock(object_chain_region);
-       return KERN_SUCCESS;
-}
+       }
 
-kern_return_t
-shared_region_mapping_create(
-       ipc_port_t              text_region,
-       vm_size_t               text_size,
-       ipc_port_t              data_region,
-       vm_size_t               data_size,
-       vm_offset_t             region_mappings,
-       vm_offset_t             client_base,
-       shared_region_mapping_t *shared_region,
-       vm_offset_t             alt_base,
-       vm_offset_t             alt_next)
-{
-       *shared_region = (shared_region_mapping_t) 
-                       kalloc(sizeof (struct shared_region_mapping));
-       if(*shared_region == NULL)
-               return KERN_FAILURE;
-       shared_region_mapping_lock_init((*shared_region));
-       (*shared_region)->text_region = text_region;
-       (*shared_region)->text_size = text_size;
-       (*shared_region)->fs_base = ENV_DEFAULT_ROOT;
-       (*shared_region)->system = machine_slot[cpu_number()].cpu_type;
-       (*shared_region)->data_region = data_region;
-       (*shared_region)->data_size = data_size;
-       (*shared_region)->region_mappings = region_mappings;
-       (*shared_region)->client_base = client_base;
-       (*shared_region)->ref_count = 1;
-       (*shared_region)->next = NULL;
-       (*shared_region)->object_chain = NULL;
-       (*shared_region)->self = *shared_region;
-       (*shared_region)->flags = 0;
-       (*shared_region)->depth = 0;
-       (*shared_region)->default_env_list = NULL;
-       (*shared_region)->alternate_base = alt_base;
-       (*shared_region)->alternate_next = alt_next;
-       return KERN_SUCCESS;
-}
+       /* Create a named object based on a submap of specified size */
 
-kern_return_t
-shared_region_mapping_set_alt_next(
-               shared_region_mapping_t shared_region,
-               vm_offset_t             alt_next) 
-{
-       shared_region->alternate_next = alt_next;
-       return KERN_SUCCESS;
-}
+       new_map = vm_map_create(PMAP_NULL, VM_MAP_MIN_ADDRESS,
+                               vm_map_round_page(size,
+                                                 VM_MAP_PAGE_MASK(target_map)),
+                               TRUE);
+       vm_map_set_page_shift(new_map, VM_MAP_PAGE_SHIFT(target_map));
 
-kern_return_t
-shared_region_mapping_ref(
-       shared_region_mapping_t shared_region)
-{
-       if(shared_region == NULL)
-               return KERN_SUCCESS;
-       hw_atomic_add(&shared_region->ref_count, 1);
-       return KERN_SUCCESS;
-}
+       user_entry->backing.map = new_map;
+       user_entry->internal = TRUE;
+       user_entry->is_sub_map = TRUE;
+       user_entry->offset = 0;
+       user_entry->protection = VM_PROT_ALL;
+       user_entry->size = size;
+       assert(user_entry->ref_count == 1);
 
-__private_extern__ kern_return_t
-shared_region_mapping_dealloc_lock(
-       shared_region_mapping_t shared_region,
-       int need_lock)
-{
-       struct shared_region_task_mappings sm_info;
-       shared_region_mapping_t next = NULL;
-       int ref_count;
-
-       while (shared_region) {
-               if ((ref_count = 
-                         hw_atomic_sub(&shared_region->ref_count, 1)) == 0) {
-                       shared_region_mapping_lock(shared_region);
-
-                       sm_info.text_region = shared_region->text_region;
-                       sm_info.text_size = shared_region->text_size;
-                       sm_info.data_region = shared_region->data_region;
-                       sm_info.data_size = shared_region->data_size;
-                       sm_info.region_mappings = shared_region->region_mappings;
-                       sm_info.client_base = shared_region->client_base;
-                       sm_info.alternate_base = shared_region->alternate_base;
-                       sm_info.alternate_next = shared_region->alternate_next;
-                       sm_info.flags = shared_region->flags;
-                       sm_info.self = (vm_offset_t)shared_region;
-
-                       if(shared_region->region_mappings) {
-                               lsf_remove_regions_mappings_lock(shared_region, &sm_info, need_lock);
-                       }
-                       if(((vm_named_entry_t)
-                               (shared_region->text_region->ip_kobject))
-                                                        ->backing.map->pmap) {
-                           pmap_remove(((vm_named_entry_t)
-                               (shared_region->text_region->ip_kobject))
-                                                       ->backing.map->pmap, 
-                               sm_info.client_base, 
-                               sm_info.client_base + sm_info.text_size);
-                       }
-                       ipc_port_release_send(shared_region->text_region);
-                       if(shared_region->data_region)
-                               ipc_port_release_send(shared_region->data_region);
-                       if (shared_region->object_chain) {
-                               next = shared_region->object_chain->object_chain_region;
-                               kfree((vm_offset_t)shared_region->object_chain,
-                                       sizeof (struct shared_region_object_chain));
-                       } else {
-                               next = NULL;
-                       }
-                       shared_region_mapping_unlock(shared_region);
-                       kfree((vm_offset_t)shared_region,
-                               sizeof (struct shared_region_mapping));
-                       shared_region = next;
-               } else {
-                       /* Stale indicates that a system region is no */
-                       /* longer in the default environment list.    */
-                       if((ref_count == 1) && 
-                         (shared_region->flags & SHARED_REGION_SYSTEM)
-                         && (shared_region->flags & ~SHARED_REGION_STALE)) {
-                               remove_default_shared_region_lock(shared_region,need_lock);
-                       }
-                       break;
-               }
-       }
+       *object_handle = user_handle;
        return KERN_SUCCESS;
-}
 
-/*
- * Stub function; always indicates that the lock needs to be taken in the
- * call to lsf_remove_regions_mappings_lock().
- */
-kern_return_t
-shared_region_mapping_dealloc(
-       shared_region_mapping_t shared_region)
-{
-       return shared_region_mapping_dealloc_lock(shared_region, 1);
 }
 
+ppnum_t vm_map_get_phys_page(          /* forward */
+       vm_map_t        map,
+       vm_offset_t     offset);
+
 ppnum_t
 vm_map_get_phys_page(
-       vm_map_t        map,
-       vm_offset_t     offset)
+       vm_map_t                map,
+       vm_offset_t             addr)
 {
-       vm_map_entry_t  entry;
-       int             ops;
-       int             flags;
-       ppnum_t         phys_page = 0;
-       vm_object_t     object;
+       vm_object_offset_t      offset;
+       vm_object_t             object;
+       vm_map_offset_t         map_offset;
+       vm_map_entry_t          entry;
+       ppnum_t                 phys_page = 0;
+
+       map_offset = vm_map_trunc_page(addr, PAGE_MASK);
 
        vm_map_lock(map);
-       while (vm_map_lookup_entry(map, offset, &entry)) {
+       while (vm_map_lookup_entry(map, map_offset, &entry)) {
 
                if (entry->object.vm_object == VM_OBJECT_NULL) {
                        vm_map_unlock(map);
-                       return (vm_offset_t) 0;
+                       return (ppnum_t) 0;
                }
                if (entry->is_sub_map) {
                        vm_map_t        old_map;
                        vm_map_lock(entry->object.sub_map);
                        old_map = map;
                        map = entry->object.sub_map;
-                       offset = entry->offset + (offset - entry->vme_start);
+                       map_offset = entry->offset + (map_offset - entry->vme_start);
                        vm_map_unlock(old_map);
                        continue;
                }
@@ -2741,22 +3498,22 @@ vm_map_get_phys_page(
                        /* If they are not present in the object they will  */
                        /* have to be picked up from the pager through the  */
                        /* fault mechanism.  */
-                       if(entry->object.vm_object->shadow_offset == 0) {
+                       if(entry->object.vm_object->vo_shadow_offset == 0) {
                                /* need to call vm_fault */
                                vm_map_unlock(map);
-                               vm_fault(map, offset, VM_PROT_NONE, 
+                               vm_fault(map, map_offset, VM_PROT_NONE, 
                                        FALSE, THREAD_UNINT, NULL, 0);
                                vm_map_lock(map);
                                continue;
                        }
-                       offset = entry->offset + (offset - entry->vme_start);
+                       offset = entry->offset + (map_offset - entry->vme_start);
                        phys_page = (ppnum_t)
-                               ((entry->object.vm_object->shadow_offset 
-                                                       + offset) >> 12);
+                               ((entry->object.vm_object->vo_shadow_offset 
+                                                       + offset) >> PAGE_SHIFT);
                        break;
                        
                }
-               offset = entry->offset + (offset - entry->vme_start);
+               offset = entry->offset + (map_offset - entry->vme_start);
                object = entry->object.vm_object;
                vm_object_lock(object);
                while (TRUE) {
@@ -2766,7 +3523,7 @@ vm_map_get_phys_page(
                                        vm_object_t old_object;
                                        vm_object_lock(object->shadow);
                                        old_object = object;
-                                       offset = offset + object->shadow_offset;
+                                       offset = offset + object->vo_shadow_offset;
                                        object = object->shadow;
                                        vm_object_unlock(old_object);
                                } else {
@@ -2789,11 +3546,20 @@ vm_map_get_phys_page(
 
 
 
+kern_return_t kernel_object_iopl_request(      /* forward */
+       vm_named_entry_t        named_entry,
+       memory_object_offset_t  offset,
+       upl_size_t              *upl_size,
+       upl_t                   *upl_ptr,
+       upl_page_info_array_t   user_page_list,
+       unsigned int            *page_list_count,
+       int                     *flags);
+
 kern_return_t
 kernel_object_iopl_request(
        vm_named_entry_t        named_entry,
        memory_object_offset_t  offset,
-       vm_size_t               *upl_size,
+       upl_size_t              *upl_size,
        upl_t                   *upl_ptr,
        upl_page_info_array_t   user_page_list,
        unsigned int            *page_list_count,
@@ -2806,11 +3572,21 @@ kernel_object_iopl_request(
 
        caller_flags = *flags;
 
+       if (caller_flags & ~UPL_VALID_FLAGS) {
+               /*
+                * For forward compatibility's sake,
+                * reject any unknown flag.
+                */
+               return KERN_INVALID_VALUE;
+       }
+
        /* a few checks to make sure user is obeying rules */
        if(*upl_size == 0) {
                if(offset >= named_entry->size)
                        return(KERN_INVALID_RIGHT);
-               *upl_size = named_entry->size - offset;
+               *upl_size = (upl_size_t) (named_entry->size - offset);
+               if (*upl_size != named_entry->size - offset)
+                       return KERN_INVALID_ARGUMENT;
        }
        if(caller_flags & UPL_COPYOUT_FROM) {
                if((named_entry->protection & VM_PROT_READ) 
@@ -2831,22 +3607,13 @@ kernel_object_iopl_request(
        /* offset from beginning of named entry offset in object */
        offset = offset + named_entry->offset;
 
-       if(named_entry->is_sub_map) 
-               return (KERN_INVALID_ARGUMENT);
+       if (named_entry->is_sub_map ||
+           named_entry->is_copy)
+               return KERN_INVALID_ARGUMENT;
                
        named_entry_lock(named_entry);
 
-       if(named_entry->object) {
-               /* This is the case where we are going to map */
-               /* an already mapped object.  If the object is */
-               /* not ready it is internal.  An external     */
-               /* object cannot be mapped until it is ready  */
-               /* we can therefore avoid the ready check     */
-               /* in this case.  */
-               vm_object_reference(named_entry->object);
-               object = named_entry->object;
-               named_entry_unlock(named_entry);
-       } else {
+       if (named_entry->is_pager) {
                object = vm_object_enter(named_entry->backing.pager, 
                                named_entry->offset + named_entry->size, 
                                named_entry->internal, 
@@ -2856,26 +3623,42 @@ kernel_object_iopl_request(
                        named_entry_unlock(named_entry);
                        return(KERN_INVALID_OBJECT);
                }
-               vm_object_lock(object);
 
-               /* create an extra reference for the named entry */
+               /* JMM - drop reference on the pager here? */
+
+               /* create an extra reference for the object */
+               vm_object_lock(object);
                vm_object_reference_locked(object);
-               named_entry->object = object;
+               named_entry->backing.object = object;
+               named_entry->is_pager = FALSE;
                named_entry_unlock(named_entry);
 
                /* wait for object (if any) to be ready */
-               while (!object->pager_ready) {
-                       vm_object_wait(object,
-                               VM_OBJECT_EVENT_PAGER_READY,
-                               THREAD_UNINT);
-                       vm_object_lock(object);
+               if (!named_entry->internal) {
+                       while (!object->pager_ready) {
+                               vm_object_wait(object,
+                                              VM_OBJECT_EVENT_PAGER_READY,
+                                              THREAD_UNINT);
+                               vm_object_lock(object);
+                       }
                }
                vm_object_unlock(object);
+
+       } else {
+               /* This is the case where we are going to operate */
+               /* an an already known object.  If the object is */
+               /* not ready it is internal.  An external     */
+               /* object cannot be mapped until it is ready  */
+               /* we can therefore avoid the ready check     */
+               /* in this case.  */
+               object = named_entry->backing.object;
+               vm_object_reference(object);
+               named_entry_unlock(named_entry);
        }
 
        if (!object->private) {
-               if (*upl_size > (MAX_UPL_TRANSFER*PAGE_SIZE))
-                       *upl_size = (MAX_UPL_TRANSFER*PAGE_SIZE);
+               if (*upl_size > MAX_UPL_TRANSFER_BYTES)
+                       *upl_size = MAX_UPL_TRANSFER_BYTES;
                if (object->phys_contiguous) {
                        *flags = UPL_PHYS_CONTIG;
                } else {
@@ -2895,5 +3678,3 @@ kernel_object_iopl_request(
        vm_object_deallocate(object);
        return ret;
 }
-
-#endif /* VM_CPM */