+ 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;
+ else
+ wimg_mode = VM_WIMG_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_entry->protection);
+ wimg_mode = VM_WIMG_IO;
+ } else if (access == MAP_MEM_COPYBACK) {
+ SET_MAP_MEM(access, parent_entry->protection);
+ wimg_mode = VM_WIMG_DEFAULT;
+ } else if (access == MAP_MEM_WTHRU) {
+ SET_MAP_MEM(access, parent_entry->protection);
+ wimg_mode = VM_WIMG_WTHRU;
+ } else if (access == MAP_MEM_WCOMB) {
+ SET_MAP_MEM(access, parent_entry->protection);
+ wimg_mode = VM_WIMG_WCOMB;
+ }
+ 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);
+ 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_disconnect(p->phys_page);
+ if (cache_attr)
+ pmap_sync_page_attributes_phys(p->phys_page);
+ }
+ }
+ vm_object_unlock(object);
+ }
+ }
+ if (object_handle)
+ *object_handle = IP_NULL;
+ return KERN_SUCCESS;
+ }
+
+ if(permission & MAP_MEM_NAMED_CREATE) {
+ kr = mach_memory_entry_allocate(&user_entry, &user_handle);
+ if (kr != KERN_SUCCESS) {
+ return KERN_FAILURE;
+ }
+
+ /*
+ * Force the creation of the VM object now.
+ */
+ if (map_size > (vm_map_size_t) VM_MAX_ADDRESS) {
+ /*
+ * LP64todo - for now, we can only allocate 4GB
+ * internal objects because the default pager can't
+ * page bigger ones. Remove this when it can.
+ */
+ kr = KERN_FAILURE;
+ goto make_mem_done;
+ }
+
+ object = vm_object_allocate(map_size);
+ assert(object != VM_OBJECT_NULL);
+
+ 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_OBJECT_PURGABLE_NONVOLATILE;
+ }
+
+ /*
+ * The VM object is brand new and nobody else knows about it,
+ * so we don't need to lock it.
+ */
+
+ 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_DEFAULT;
+ } 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 */
+
+ /*
+ * 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;
+
+ 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->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. */
+
+ *size = CAST_DOWN(vm_size_t, map_size);
+ *object_handle = user_handle;
+ return KERN_SUCCESS;
+ }
+
+ if (parent_entry == NULL ||
+ (permission & MAP_MEM_NAMED_REUSE)) {
+
+ /* Create a named object based on address range within the task map */
+ /* Go find the object at given address */
+
+redo_lookup: