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