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