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