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