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