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