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