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