]> git.saurik.com Git - apple/xnu.git/blob - osfmk/vm/vm_user.c
xnu-3789.51.2.tar.gz
[apple/xnu.git] / osfmk / vm / vm_user.c
1 /*
2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56 /*
57 */
58 /*
59 * File: vm/vm_user.c
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young
61 *
62 * User-exported virtual memory functions.
63 */
64
65 /*
66 * There are three implementations of the "XXX_allocate" functionality in
67 * the kernel: mach_vm_allocate (for any task on the platform), vm_allocate
68 * (for a task with the same address space size, especially the current task),
69 * and vm32_vm_allocate (for the specific case of a 32-bit task). vm_allocate
70 * in the kernel should only be used on the kernel_task. vm32_vm_allocate only
71 * makes sense on platforms where a user task can either be 32 or 64, or the kernel
72 * task can be 32 or 64. mach_vm_allocate makes sense everywhere, and is preferred
73 * for new code.
74 *
75 * The entrypoints into the kernel are more complex. All platforms support a
76 * mach_vm_allocate-style API (subsystem 4800) which operates with the largest
77 * size types for the platform. On platforms that only support U32/K32,
78 * subsystem 4800 is all you need. On platforms that support both U32 and U64,
79 * subsystem 3800 is used disambiguate the size of parameters, and they will
80 * always be 32-bit and call into the vm32_vm_allocate APIs. On non-U32/K32 platforms,
81 * the MIG glue should never call into vm_allocate directly, because the calling
82 * task and kernel_task are unlikely to use the same size parameters
83 *
84 * New VM call implementations should be added here and to mach_vm.defs
85 * (subsystem 4800), and use mach_vm_* "wide" types.
86 */
87
88 #include <debug.h>
89
90 #include <vm_cpm.h>
91 #include <mach/boolean.h>
92 #include <mach/kern_return.h>
93 #include <mach/mach_types.h> /* to get vm_address_t */
94 #include <mach/memory_object.h>
95 #include <mach/std_types.h> /* to get pointer_t */
96 #include <mach/upl.h>
97 #include <mach/vm_attributes.h>
98 #include <mach/vm_param.h>
99 #include <mach/vm_statistics.h>
100 #include <mach/mach_syscalls.h>
101 #include <mach/sdt.h>
102
103 #include <mach/host_priv_server.h>
104 #include <mach/mach_vm_server.h>
105 #include <mach/vm_map_server.h>
106
107 #include <kern/host.h>
108 #include <kern/kalloc.h>
109 #include <kern/task.h>
110 #include <kern/misc_protos.h>
111 #include <vm/vm_fault.h>
112 #include <vm/vm_map.h>
113 #include <vm/vm_object.h>
114 #include <vm/vm_page.h>
115 #include <vm/memory_object.h>
116 #include <vm/vm_pageout.h>
117 #include <vm/vm_protos.h>
118 #include <vm/vm_purgeable_internal.h>
119 #include <vm/vm_init.h>
120
121 vm_size_t upl_offset_to_pagelist = 0;
122
123 #if VM_CPM
124 #include <vm/cpm.h>
125 #endif /* VM_CPM */
126
127 lck_grp_t dynamic_pager_control_port_lock_group;
128 decl_lck_mtx_data(, dynamic_pager_control_port_lock);
129 ipc_port_t dynamic_pager_control_port=NULL;
130
131 /*
132 * mach_vm_allocate allocates "zero fill" memory in the specfied
133 * map.
134 */
135 kern_return_t
136 mach_vm_allocate(
137 vm_map_t map,
138 mach_vm_offset_t *addr,
139 mach_vm_size_t size,
140 int flags)
141 {
142 vm_map_offset_t map_addr;
143 vm_map_size_t map_size;
144 kern_return_t result;
145 boolean_t anywhere;
146
147 /* filter out any kernel-only flags */
148 if (flags & ~VM_FLAGS_USER_ALLOCATE)
149 return KERN_INVALID_ARGUMENT;
150
151 if (map == VM_MAP_NULL)
152 return(KERN_INVALID_ARGUMENT);
153 if (size == 0) {
154 *addr = 0;
155 return(KERN_SUCCESS);
156 }
157
158 anywhere = ((VM_FLAGS_ANYWHERE & flags) != 0);
159 if (anywhere) {
160 /*
161 * No specific address requested, so start candidate address
162 * search at the minimum address in the map. However, if that
163 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
164 * allocations of PAGEZERO to explicit requests since its
165 * normal use is to catch dereferences of NULL and many
166 * applications also treat pointers with a value of 0 as
167 * special and suddenly having address 0 contain useable
168 * memory would tend to confuse those applications.
169 */
170 map_addr = vm_map_min(map);
171 if (map_addr == 0)
172 map_addr += VM_MAP_PAGE_SIZE(map);
173 } else
174 map_addr = vm_map_trunc_page(*addr,
175 VM_MAP_PAGE_MASK(map));
176 map_size = vm_map_round_page(size,
177 VM_MAP_PAGE_MASK(map));
178 if (map_size == 0) {
179 return(KERN_INVALID_ARGUMENT);
180 }
181
182 result = vm_map_enter(
183 map,
184 &map_addr,
185 map_size,
186 (vm_map_offset_t)0,
187 flags,
188 VM_OBJECT_NULL,
189 (vm_object_offset_t)0,
190 FALSE,
191 VM_PROT_DEFAULT,
192 VM_PROT_ALL,
193 VM_INHERIT_DEFAULT);
194
195 *addr = map_addr;
196 return(result);
197 }
198
199 /*
200 * vm_allocate
201 * Legacy routine that allocates "zero fill" memory in the specfied
202 * map (which is limited to the same size as the kernel).
203 */
204 kern_return_t
205 vm_allocate(
206 vm_map_t map,
207 vm_offset_t *addr,
208 vm_size_t size,
209 int flags)
210 {
211 vm_map_offset_t map_addr;
212 vm_map_size_t map_size;
213 kern_return_t result;
214 boolean_t anywhere;
215
216 /* filter out any kernel-only flags */
217 if (flags & ~VM_FLAGS_USER_ALLOCATE)
218 return KERN_INVALID_ARGUMENT;
219
220 if (map == VM_MAP_NULL)
221 return(KERN_INVALID_ARGUMENT);
222 if (size == 0) {
223 *addr = 0;
224 return(KERN_SUCCESS);
225 }
226
227 anywhere = ((VM_FLAGS_ANYWHERE & flags) != 0);
228 if (anywhere) {
229 /*
230 * No specific address requested, so start candidate address
231 * search at the minimum address in the map. However, if that
232 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
233 * allocations of PAGEZERO to explicit requests since its
234 * normal use is to catch dereferences of NULL and many
235 * applications also treat pointers with a value of 0 as
236 * special and suddenly having address 0 contain useable
237 * memory would tend to confuse those applications.
238 */
239 map_addr = vm_map_min(map);
240 if (map_addr == 0)
241 map_addr += VM_MAP_PAGE_SIZE(map);
242 } else
243 map_addr = vm_map_trunc_page(*addr,
244 VM_MAP_PAGE_MASK(map));
245 map_size = vm_map_round_page(size,
246 VM_MAP_PAGE_MASK(map));
247 if (map_size == 0) {
248 return(KERN_INVALID_ARGUMENT);
249 }
250
251 result = vm_map_enter(
252 map,
253 &map_addr,
254 map_size,
255 (vm_map_offset_t)0,
256 flags,
257 VM_OBJECT_NULL,
258 (vm_object_offset_t)0,
259 FALSE,
260 VM_PROT_DEFAULT,
261 VM_PROT_ALL,
262 VM_INHERIT_DEFAULT);
263
264 *addr = CAST_DOWN(vm_offset_t, map_addr);
265 return(result);
266 }
267
268 /*
269 * mach_vm_deallocate -
270 * deallocates the specified range of addresses in the
271 * specified address map.
272 */
273 kern_return_t
274 mach_vm_deallocate(
275 vm_map_t map,
276 mach_vm_offset_t start,
277 mach_vm_size_t size)
278 {
279 if ((map == VM_MAP_NULL) || (start + size < start))
280 return(KERN_INVALID_ARGUMENT);
281
282 if (size == (mach_vm_offset_t) 0)
283 return(KERN_SUCCESS);
284
285 return(vm_map_remove(map,
286 vm_map_trunc_page(start,
287 VM_MAP_PAGE_MASK(map)),
288 vm_map_round_page(start+size,
289 VM_MAP_PAGE_MASK(map)),
290 VM_MAP_NO_FLAGS));
291 }
292
293 /*
294 * vm_deallocate -
295 * deallocates the specified range of addresses in the
296 * specified address map (limited to addresses the same
297 * size as the kernel).
298 */
299 kern_return_t
300 vm_deallocate(
301 vm_map_t map,
302 vm_offset_t start,
303 vm_size_t size)
304 {
305 if ((map == VM_MAP_NULL) || (start + size < start))
306 return(KERN_INVALID_ARGUMENT);
307
308 if (size == (vm_offset_t) 0)
309 return(KERN_SUCCESS);
310
311 return(vm_map_remove(map,
312 vm_map_trunc_page(start,
313 VM_MAP_PAGE_MASK(map)),
314 vm_map_round_page(start+size,
315 VM_MAP_PAGE_MASK(map)),
316 VM_MAP_NO_FLAGS));
317 }
318
319 /*
320 * mach_vm_inherit -
321 * Sets the inheritance of the specified range in the
322 * specified map.
323 */
324 kern_return_t
325 mach_vm_inherit(
326 vm_map_t map,
327 mach_vm_offset_t start,
328 mach_vm_size_t size,
329 vm_inherit_t new_inheritance)
330 {
331 if ((map == VM_MAP_NULL) || (start + size < start) ||
332 (new_inheritance > VM_INHERIT_LAST_VALID))
333 return(KERN_INVALID_ARGUMENT);
334
335 if (size == 0)
336 return KERN_SUCCESS;
337
338 return(vm_map_inherit(map,
339 vm_map_trunc_page(start,
340 VM_MAP_PAGE_MASK(map)),
341 vm_map_round_page(start+size,
342 VM_MAP_PAGE_MASK(map)),
343 new_inheritance));
344 }
345
346 /*
347 * vm_inherit -
348 * Sets the inheritance of the specified range in the
349 * specified map (range limited to addresses
350 */
351 kern_return_t
352 vm_inherit(
353 vm_map_t map,
354 vm_offset_t start,
355 vm_size_t size,
356 vm_inherit_t new_inheritance)
357 {
358 if ((map == VM_MAP_NULL) || (start + size < start) ||
359 (new_inheritance > VM_INHERIT_LAST_VALID))
360 return(KERN_INVALID_ARGUMENT);
361
362 if (size == 0)
363 return KERN_SUCCESS;
364
365 return(vm_map_inherit(map,
366 vm_map_trunc_page(start,
367 VM_MAP_PAGE_MASK(map)),
368 vm_map_round_page(start+size,
369 VM_MAP_PAGE_MASK(map)),
370 new_inheritance));
371 }
372
373 /*
374 * mach_vm_protect -
375 * Sets the protection of the specified range in the
376 * specified map.
377 */
378
379 kern_return_t
380 mach_vm_protect(
381 vm_map_t map,
382 mach_vm_offset_t start,
383 mach_vm_size_t size,
384 boolean_t set_maximum,
385 vm_prot_t new_protection)
386 {
387 if ((map == VM_MAP_NULL) || (start + size < start) ||
388 (new_protection & ~(VM_PROT_ALL | VM_PROT_COPY)))
389 return(KERN_INVALID_ARGUMENT);
390
391 if (size == 0)
392 return KERN_SUCCESS;
393
394 return(vm_map_protect(map,
395 vm_map_trunc_page(start,
396 VM_MAP_PAGE_MASK(map)),
397 vm_map_round_page(start+size,
398 VM_MAP_PAGE_MASK(map)),
399 new_protection,
400 set_maximum));
401 }
402
403 /*
404 * vm_protect -
405 * Sets the protection of the specified range in the
406 * specified map. Addressability of the range limited
407 * to the same size as the kernel.
408 */
409
410 kern_return_t
411 vm_protect(
412 vm_map_t map,
413 vm_offset_t start,
414 vm_size_t size,
415 boolean_t set_maximum,
416 vm_prot_t new_protection)
417 {
418 if ((map == VM_MAP_NULL) || (start + size < start) ||
419 (new_protection & ~(VM_PROT_ALL | VM_PROT_COPY)))
420 return(KERN_INVALID_ARGUMENT);
421
422 if (size == 0)
423 return KERN_SUCCESS;
424
425 return(vm_map_protect(map,
426 vm_map_trunc_page(start,
427 VM_MAP_PAGE_MASK(map)),
428 vm_map_round_page(start+size,
429 VM_MAP_PAGE_MASK(map)),
430 new_protection,
431 set_maximum));
432 }
433
434 /*
435 * mach_vm_machine_attributes -
436 * Handle machine-specific attributes for a mapping, such
437 * as cachability, migrability, etc.
438 */
439 kern_return_t
440 mach_vm_machine_attribute(
441 vm_map_t map,
442 mach_vm_address_t addr,
443 mach_vm_size_t size,
444 vm_machine_attribute_t attribute,
445 vm_machine_attribute_val_t* value) /* IN/OUT */
446 {
447 if ((map == VM_MAP_NULL) || (addr + size < addr))
448 return(KERN_INVALID_ARGUMENT);
449
450 if (size == 0)
451 return KERN_SUCCESS;
452
453 return vm_map_machine_attribute(
454 map,
455 vm_map_trunc_page(addr,
456 VM_MAP_PAGE_MASK(map)),
457 vm_map_round_page(addr+size,
458 VM_MAP_PAGE_MASK(map)),
459 attribute,
460 value);
461 }
462
463 /*
464 * vm_machine_attribute -
465 * Handle machine-specific attributes for a mapping, such
466 * as cachability, migrability, etc. Limited addressability
467 * (same range limits as for the native kernel map).
468 */
469 kern_return_t
470 vm_machine_attribute(
471 vm_map_t map,
472 vm_address_t addr,
473 vm_size_t size,
474 vm_machine_attribute_t attribute,
475 vm_machine_attribute_val_t* value) /* IN/OUT */
476 {
477 if ((map == VM_MAP_NULL) || (addr + size < addr))
478 return(KERN_INVALID_ARGUMENT);
479
480 if (size == 0)
481 return KERN_SUCCESS;
482
483 return vm_map_machine_attribute(
484 map,
485 vm_map_trunc_page(addr,
486 VM_MAP_PAGE_MASK(map)),
487 vm_map_round_page(addr+size,
488 VM_MAP_PAGE_MASK(map)),
489 attribute,
490 value);
491 }
492
493 /*
494 * mach_vm_read -
495 * Read/copy a range from one address space and return it to the caller.
496 *
497 * It is assumed that the address for the returned memory is selected by
498 * the IPC implementation as part of receiving the reply to this call.
499 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
500 * that gets returned.
501 *
502 * JMM - because of mach_msg_type_number_t, this call is limited to a
503 * single 4GB region at this time.
504 *
505 */
506 kern_return_t
507 mach_vm_read(
508 vm_map_t map,
509 mach_vm_address_t addr,
510 mach_vm_size_t size,
511 pointer_t *data,
512 mach_msg_type_number_t *data_size)
513 {
514 kern_return_t error;
515 vm_map_copy_t ipc_address;
516
517 if (map == VM_MAP_NULL)
518 return(KERN_INVALID_ARGUMENT);
519
520 if ((mach_msg_type_number_t) size != size)
521 return KERN_INVALID_ARGUMENT;
522
523 error = vm_map_copyin(map,
524 (vm_map_address_t)addr,
525 (vm_map_size_t)size,
526 FALSE, /* src_destroy */
527 &ipc_address);
528
529 if (KERN_SUCCESS == error) {
530 *data = (pointer_t) ipc_address;
531 *data_size = (mach_msg_type_number_t) size;
532 assert(*data_size == size);
533 }
534 return(error);
535 }
536
537 /*
538 * vm_read -
539 * Read/copy a range from one address space and return it to the caller.
540 * Limited addressability (same range limits as for the native kernel map).
541 *
542 * It is assumed that the address for the returned memory is selected by
543 * the IPC implementation as part of receiving the reply to this call.
544 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
545 * that gets returned.
546 */
547 kern_return_t
548 vm_read(
549 vm_map_t map,
550 vm_address_t addr,
551 vm_size_t size,
552 pointer_t *data,
553 mach_msg_type_number_t *data_size)
554 {
555 kern_return_t error;
556 vm_map_copy_t ipc_address;
557
558 if (map == VM_MAP_NULL)
559 return(KERN_INVALID_ARGUMENT);
560
561 if (size > (unsigned)(mach_msg_type_number_t) -1) {
562 /*
563 * The kernel could handle a 64-bit "size" value, but
564 * it could not return the size of the data in "*data_size"
565 * without overflowing.
566 * Let's reject this "size" as invalid.
567 */
568 return KERN_INVALID_ARGUMENT;
569 }
570
571 error = vm_map_copyin(map,
572 (vm_map_address_t)addr,
573 (vm_map_size_t)size,
574 FALSE, /* src_destroy */
575 &ipc_address);
576
577 if (KERN_SUCCESS == error) {
578 *data = (pointer_t) ipc_address;
579 *data_size = (mach_msg_type_number_t) size;
580 assert(*data_size == size);
581 }
582 return(error);
583 }
584
585 /*
586 * mach_vm_read_list -
587 * Read/copy a list of address ranges from specified map.
588 *
589 * MIG does not know how to deal with a returned array of
590 * vm_map_copy_t structures, so we have to do the copyout
591 * manually here.
592 */
593 kern_return_t
594 mach_vm_read_list(
595 vm_map_t map,
596 mach_vm_read_entry_t data_list,
597 natural_t count)
598 {
599 mach_msg_type_number_t i;
600 kern_return_t error;
601 vm_map_copy_t copy;
602
603 if (map == VM_MAP_NULL ||
604 count > VM_MAP_ENTRY_MAX)
605 return(KERN_INVALID_ARGUMENT);
606
607 error = KERN_SUCCESS;
608 for(i=0; i<count; i++) {
609 vm_map_address_t map_addr;
610 vm_map_size_t map_size;
611
612 map_addr = (vm_map_address_t)(data_list[i].address);
613 map_size = (vm_map_size_t)(data_list[i].size);
614
615 if(map_size != 0) {
616 error = vm_map_copyin(map,
617 map_addr,
618 map_size,
619 FALSE, /* src_destroy */
620 &copy);
621 if (KERN_SUCCESS == error) {
622 error = vm_map_copyout(
623 current_task()->map,
624 &map_addr,
625 copy);
626 if (KERN_SUCCESS == error) {
627 data_list[i].address = map_addr;
628 continue;
629 }
630 vm_map_copy_discard(copy);
631 }
632 }
633 data_list[i].address = (mach_vm_address_t)0;
634 data_list[i].size = (mach_vm_size_t)0;
635 }
636 return(error);
637 }
638
639 /*
640 * vm_read_list -
641 * Read/copy a list of address ranges from specified map.
642 *
643 * MIG does not know how to deal with a returned array of
644 * vm_map_copy_t structures, so we have to do the copyout
645 * manually here.
646 *
647 * The source and destination ranges are limited to those
648 * that can be described with a vm_address_t (i.e. same
649 * size map as the kernel).
650 *
651 * JMM - If the result of the copyout is an address range
652 * that cannot be described with a vm_address_t (i.e. the
653 * caller had a larger address space but used this call
654 * anyway), it will result in a truncated address being
655 * returned (and a likely confused caller).
656 */
657
658 kern_return_t
659 vm_read_list(
660 vm_map_t map,
661 vm_read_entry_t data_list,
662 natural_t count)
663 {
664 mach_msg_type_number_t i;
665 kern_return_t error;
666 vm_map_copy_t copy;
667
668 if (map == VM_MAP_NULL ||
669 count > VM_MAP_ENTRY_MAX)
670 return(KERN_INVALID_ARGUMENT);
671
672 error = KERN_SUCCESS;
673 for(i=0; i<count; i++) {
674 vm_map_address_t map_addr;
675 vm_map_size_t map_size;
676
677 map_addr = (vm_map_address_t)(data_list[i].address);
678 map_size = (vm_map_size_t)(data_list[i].size);
679
680 if(map_size != 0) {
681 error = vm_map_copyin(map,
682 map_addr,
683 map_size,
684 FALSE, /* src_destroy */
685 &copy);
686 if (KERN_SUCCESS == error) {
687 error = vm_map_copyout(current_task()->map,
688 &map_addr,
689 copy);
690 if (KERN_SUCCESS == error) {
691 data_list[i].address =
692 CAST_DOWN(vm_offset_t, map_addr);
693 continue;
694 }
695 vm_map_copy_discard(copy);
696 }
697 }
698 data_list[i].address = (mach_vm_address_t)0;
699 data_list[i].size = (mach_vm_size_t)0;
700 }
701 return(error);
702 }
703
704 /*
705 * mach_vm_read_overwrite -
706 * Overwrite a range of the current map with data from the specified
707 * map/address range.
708 *
709 * In making an assumption that the current thread is local, it is
710 * no longer cluster-safe without a fully supportive local proxy
711 * thread/task (but we don't support cluster's anymore so this is moot).
712 */
713
714 kern_return_t
715 mach_vm_read_overwrite(
716 vm_map_t map,
717 mach_vm_address_t address,
718 mach_vm_size_t size,
719 mach_vm_address_t data,
720 mach_vm_size_t *data_size)
721 {
722 kern_return_t error;
723 vm_map_copy_t copy;
724
725 if (map == VM_MAP_NULL)
726 return(KERN_INVALID_ARGUMENT);
727
728 error = vm_map_copyin(map, (vm_map_address_t)address,
729 (vm_map_size_t)size, FALSE, &copy);
730
731 if (KERN_SUCCESS == error) {
732 error = vm_map_copy_overwrite(current_thread()->map,
733 (vm_map_address_t)data,
734 copy, FALSE);
735 if (KERN_SUCCESS == error) {
736 *data_size = size;
737 return error;
738 }
739 vm_map_copy_discard(copy);
740 }
741 return(error);
742 }
743
744 /*
745 * vm_read_overwrite -
746 * Overwrite a range of the current map with data from the specified
747 * map/address range.
748 *
749 * This routine adds the additional limitation that the source and
750 * destination ranges must be describable with vm_address_t values
751 * (i.e. the same size address spaces as the kernel, or at least the
752 * the ranges are in that first portion of the respective address
753 * spaces).
754 */
755
756 kern_return_t
757 vm_read_overwrite(
758 vm_map_t map,
759 vm_address_t address,
760 vm_size_t size,
761 vm_address_t data,
762 vm_size_t *data_size)
763 {
764 kern_return_t error;
765 vm_map_copy_t copy;
766
767 if (map == VM_MAP_NULL)
768 return(KERN_INVALID_ARGUMENT);
769
770 error = vm_map_copyin(map, (vm_map_address_t)address,
771 (vm_map_size_t)size, FALSE, &copy);
772
773 if (KERN_SUCCESS == error) {
774 error = vm_map_copy_overwrite(current_thread()->map,
775 (vm_map_address_t)data,
776 copy, FALSE);
777 if (KERN_SUCCESS == error) {
778 *data_size = size;
779 return error;
780 }
781 vm_map_copy_discard(copy);
782 }
783 return(error);
784 }
785
786
787 /*
788 * mach_vm_write -
789 * Overwrite the specified address range with the data provided
790 * (from the current map).
791 */
792 kern_return_t
793 mach_vm_write(
794 vm_map_t map,
795 mach_vm_address_t address,
796 pointer_t data,
797 __unused mach_msg_type_number_t size)
798 {
799 if (map == VM_MAP_NULL)
800 return KERN_INVALID_ARGUMENT;
801
802 return vm_map_copy_overwrite(map, (vm_map_address_t)address,
803 (vm_map_copy_t) data, FALSE /* interruptible XXX */);
804 }
805
806 /*
807 * vm_write -
808 * Overwrite the specified address range with the data provided
809 * (from the current map).
810 *
811 * The addressability of the range of addresses to overwrite is
812 * limited bu the use of a vm_address_t (same size as kernel map).
813 * Either the target map is also small, or the range is in the
814 * low addresses within it.
815 */
816 kern_return_t
817 vm_write(
818 vm_map_t map,
819 vm_address_t address,
820 pointer_t data,
821 __unused mach_msg_type_number_t size)
822 {
823 if (map == VM_MAP_NULL)
824 return KERN_INVALID_ARGUMENT;
825
826 return vm_map_copy_overwrite(map, (vm_map_address_t)address,
827 (vm_map_copy_t) data, FALSE /* interruptible XXX */);
828 }
829
830 /*
831 * mach_vm_copy -
832 * Overwrite one range of the specified map with the contents of
833 * another range within that same map (i.e. both address ranges
834 * are "over there").
835 */
836 kern_return_t
837 mach_vm_copy(
838 vm_map_t map,
839 mach_vm_address_t source_address,
840 mach_vm_size_t size,
841 mach_vm_address_t dest_address)
842 {
843 vm_map_copy_t copy;
844 kern_return_t kr;
845
846 if (map == VM_MAP_NULL)
847 return KERN_INVALID_ARGUMENT;
848
849 kr = vm_map_copyin(map, (vm_map_address_t)source_address,
850 (vm_map_size_t)size, FALSE, &copy);
851
852 if (KERN_SUCCESS == kr) {
853 kr = vm_map_copy_overwrite(map,
854 (vm_map_address_t)dest_address,
855 copy, FALSE /* interruptible XXX */);
856
857 if (KERN_SUCCESS != kr)
858 vm_map_copy_discard(copy);
859 }
860 return kr;
861 }
862
863 kern_return_t
864 vm_copy(
865 vm_map_t map,
866 vm_address_t source_address,
867 vm_size_t size,
868 vm_address_t dest_address)
869 {
870 vm_map_copy_t copy;
871 kern_return_t kr;
872
873 if (map == VM_MAP_NULL)
874 return KERN_INVALID_ARGUMENT;
875
876 kr = vm_map_copyin(map, (vm_map_address_t)source_address,
877 (vm_map_size_t)size, FALSE, &copy);
878
879 if (KERN_SUCCESS == kr) {
880 kr = vm_map_copy_overwrite(map,
881 (vm_map_address_t)dest_address,
882 copy, FALSE /* interruptible XXX */);
883
884 if (KERN_SUCCESS != kr)
885 vm_map_copy_discard(copy);
886 }
887 return kr;
888 }
889
890 /*
891 * mach_vm_map -
892 * Map some range of an object into an address space.
893 *
894 * The object can be one of several types of objects:
895 * NULL - anonymous memory
896 * a named entry - a range within another address space
897 * or a range within a memory object
898 * a whole memory object
899 *
900 */
901 kern_return_t
902 mach_vm_map(
903 vm_map_t target_map,
904 mach_vm_offset_t *address,
905 mach_vm_size_t initial_size,
906 mach_vm_offset_t mask,
907 int flags,
908 ipc_port_t port,
909 vm_object_offset_t offset,
910 boolean_t copy,
911 vm_prot_t cur_protection,
912 vm_prot_t max_protection,
913 vm_inherit_t inheritance)
914 {
915 kern_return_t kr;
916 vm_map_offset_t vmmaddr;
917
918 vmmaddr = (vm_map_offset_t) *address;
919
920 /* filter out any kernel-only flags */
921 if (flags & ~VM_FLAGS_USER_MAP)
922 return KERN_INVALID_ARGUMENT;
923
924 kr = vm_map_enter_mem_object(target_map,
925 &vmmaddr,
926 initial_size,
927 mask,
928 flags,
929 port,
930 offset,
931 copy,
932 cur_protection,
933 max_protection,
934 inheritance);
935
936 *address = vmmaddr;
937 return kr;
938 }
939
940
941 /* legacy interface */
942 kern_return_t
943 vm_map_64(
944 vm_map_t target_map,
945 vm_offset_t *address,
946 vm_size_t size,
947 vm_offset_t mask,
948 int flags,
949 ipc_port_t port,
950 vm_object_offset_t offset,
951 boolean_t copy,
952 vm_prot_t cur_protection,
953 vm_prot_t max_protection,
954 vm_inherit_t inheritance)
955 {
956 mach_vm_address_t map_addr;
957 mach_vm_size_t map_size;
958 mach_vm_offset_t map_mask;
959 kern_return_t kr;
960
961 map_addr = (mach_vm_address_t)*address;
962 map_size = (mach_vm_size_t)size;
963 map_mask = (mach_vm_offset_t)mask;
964
965 kr = mach_vm_map(target_map, &map_addr, map_size, map_mask, flags,
966 port, offset, copy,
967 cur_protection, max_protection, inheritance);
968 *address = CAST_DOWN(vm_offset_t, map_addr);
969 return kr;
970 }
971
972 /* temporary, until world build */
973 kern_return_t
974 vm_map(
975 vm_map_t target_map,
976 vm_offset_t *address,
977 vm_size_t size,
978 vm_offset_t mask,
979 int flags,
980 ipc_port_t port,
981 vm_offset_t offset,
982 boolean_t copy,
983 vm_prot_t cur_protection,
984 vm_prot_t max_protection,
985 vm_inherit_t inheritance)
986 {
987 mach_vm_address_t map_addr;
988 mach_vm_size_t map_size;
989 mach_vm_offset_t map_mask;
990 vm_object_offset_t obj_offset;
991 kern_return_t kr;
992
993 map_addr = (mach_vm_address_t)*address;
994 map_size = (mach_vm_size_t)size;
995 map_mask = (mach_vm_offset_t)mask;
996 obj_offset = (vm_object_offset_t)offset;
997
998 kr = mach_vm_map(target_map, &map_addr, map_size, map_mask, flags,
999 port, obj_offset, copy,
1000 cur_protection, max_protection, inheritance);
1001 *address = CAST_DOWN(vm_offset_t, map_addr);
1002 return kr;
1003 }
1004
1005 /*
1006 * mach_vm_remap -
1007 * Remap a range of memory from one task into another,
1008 * to another address range within the same task, or
1009 * over top of itself (with altered permissions and/or
1010 * as an in-place copy of itself).
1011 */
1012
1013 kern_return_t
1014 mach_vm_remap(
1015 vm_map_t target_map,
1016 mach_vm_offset_t *address,
1017 mach_vm_size_t size,
1018 mach_vm_offset_t mask,
1019 int flags,
1020 vm_map_t src_map,
1021 mach_vm_offset_t memory_address,
1022 boolean_t copy,
1023 vm_prot_t *cur_protection,
1024 vm_prot_t *max_protection,
1025 vm_inherit_t inheritance)
1026 {
1027 vm_map_offset_t map_addr;
1028 kern_return_t kr;
1029
1030 if (VM_MAP_NULL == target_map || VM_MAP_NULL == src_map)
1031 return KERN_INVALID_ARGUMENT;
1032
1033 /* filter out any kernel-only flags */
1034 if (flags & ~VM_FLAGS_USER_REMAP)
1035 return KERN_INVALID_ARGUMENT;
1036
1037 map_addr = (vm_map_offset_t)*address;
1038
1039 kr = vm_map_remap(target_map,
1040 &map_addr,
1041 size,
1042 mask,
1043 flags,
1044 src_map,
1045 memory_address,
1046 copy,
1047 cur_protection,
1048 max_protection,
1049 inheritance);
1050 *address = map_addr;
1051 return kr;
1052 }
1053
1054 /*
1055 * vm_remap -
1056 * Remap a range of memory from one task into another,
1057 * to another address range within the same task, or
1058 * over top of itself (with altered permissions and/or
1059 * as an in-place copy of itself).
1060 *
1061 * The addressability of the source and target address
1062 * range is limited by the size of vm_address_t (in the
1063 * kernel context).
1064 */
1065 kern_return_t
1066 vm_remap(
1067 vm_map_t target_map,
1068 vm_offset_t *address,
1069 vm_size_t size,
1070 vm_offset_t mask,
1071 int flags,
1072 vm_map_t src_map,
1073 vm_offset_t memory_address,
1074 boolean_t copy,
1075 vm_prot_t *cur_protection,
1076 vm_prot_t *max_protection,
1077 vm_inherit_t inheritance)
1078 {
1079 vm_map_offset_t map_addr;
1080 kern_return_t kr;
1081
1082 if (VM_MAP_NULL == target_map || VM_MAP_NULL == src_map)
1083 return KERN_INVALID_ARGUMENT;
1084
1085 /* filter out any kernel-only flags */
1086 if (flags & ~VM_FLAGS_USER_REMAP)
1087 return KERN_INVALID_ARGUMENT;
1088
1089 map_addr = (vm_map_offset_t)*address;
1090
1091 kr = vm_map_remap(target_map,
1092 &map_addr,
1093 size,
1094 mask,
1095 flags,
1096 src_map,
1097 memory_address,
1098 copy,
1099 cur_protection,
1100 max_protection,
1101 inheritance);
1102 *address = CAST_DOWN(vm_offset_t, map_addr);
1103 return kr;
1104 }
1105
1106 /*
1107 * NOTE: these routine (and this file) will no longer require mach_host_server.h
1108 * when mach_vm_wire and vm_wire are changed to use ledgers.
1109 */
1110 #include <mach/mach_host_server.h>
1111 /*
1112 * mach_vm_wire
1113 * Specify that the range of the virtual address space
1114 * of the target task must not cause page faults for
1115 * the indicated accesses.
1116 *
1117 * [ To unwire the pages, specify VM_PROT_NONE. ]
1118 */
1119 kern_return_t
1120 mach_vm_wire(
1121 host_priv_t host_priv,
1122 vm_map_t map,
1123 mach_vm_offset_t start,
1124 mach_vm_size_t size,
1125 vm_prot_t access)
1126 {
1127 kern_return_t rc;
1128
1129 if (host_priv == HOST_PRIV_NULL)
1130 return KERN_INVALID_HOST;
1131
1132 assert(host_priv == &realhost);
1133
1134 if (map == VM_MAP_NULL)
1135 return KERN_INVALID_TASK;
1136
1137 if (access & ~VM_PROT_ALL || (start + size < start))
1138 return KERN_INVALID_ARGUMENT;
1139
1140 if (access != VM_PROT_NONE) {
1141 rc = vm_map_wire(map,
1142 vm_map_trunc_page(start,
1143 VM_MAP_PAGE_MASK(map)),
1144 vm_map_round_page(start+size,
1145 VM_MAP_PAGE_MASK(map)),
1146 access | VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_MLOCK),
1147 TRUE);
1148 } else {
1149 rc = vm_map_unwire(map,
1150 vm_map_trunc_page(start,
1151 VM_MAP_PAGE_MASK(map)),
1152 vm_map_round_page(start+size,
1153 VM_MAP_PAGE_MASK(map)),
1154 TRUE);
1155 }
1156 return rc;
1157 }
1158
1159 /*
1160 * vm_wire -
1161 * Specify that the range of the virtual address space
1162 * of the target task must not cause page faults for
1163 * the indicated accesses.
1164 *
1165 * [ To unwire the pages, specify VM_PROT_NONE. ]
1166 */
1167 kern_return_t
1168 vm_wire(
1169 host_priv_t host_priv,
1170 vm_map_t map,
1171 vm_offset_t start,
1172 vm_size_t size,
1173 vm_prot_t access)
1174 {
1175 kern_return_t rc;
1176
1177 if (host_priv == HOST_PRIV_NULL)
1178 return KERN_INVALID_HOST;
1179
1180 assert(host_priv == &realhost);
1181
1182 if (map == VM_MAP_NULL)
1183 return KERN_INVALID_TASK;
1184
1185 if ((access & ~VM_PROT_ALL) || (start + size < start))
1186 return KERN_INVALID_ARGUMENT;
1187
1188 if (size == 0) {
1189 rc = KERN_SUCCESS;
1190 } else if (access != VM_PROT_NONE) {
1191 rc = vm_map_wire(map,
1192 vm_map_trunc_page(start,
1193 VM_MAP_PAGE_MASK(map)),
1194 vm_map_round_page(start+size,
1195 VM_MAP_PAGE_MASK(map)),
1196 access | VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_OSFMK),
1197 TRUE);
1198 } else {
1199 rc = vm_map_unwire(map,
1200 vm_map_trunc_page(start,
1201 VM_MAP_PAGE_MASK(map)),
1202 vm_map_round_page(start+size,
1203 VM_MAP_PAGE_MASK(map)),
1204 TRUE);
1205 }
1206 return rc;
1207 }
1208
1209 /*
1210 * vm_msync
1211 *
1212 * Synchronises the memory range specified with its backing store
1213 * image by either flushing or cleaning the contents to the appropriate
1214 * memory manager.
1215 *
1216 * interpretation of sync_flags
1217 * VM_SYNC_INVALIDATE - discard pages, only return precious
1218 * pages to manager.
1219 *
1220 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1221 * - discard pages, write dirty or precious
1222 * pages back to memory manager.
1223 *
1224 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1225 * - write dirty or precious pages back to
1226 * the memory manager.
1227 *
1228 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1229 * is a hole in the region, and we would
1230 * have returned KERN_SUCCESS, return
1231 * KERN_INVALID_ADDRESS instead.
1232 *
1233 * RETURNS
1234 * KERN_INVALID_TASK Bad task parameter
1235 * KERN_INVALID_ARGUMENT both sync and async were specified.
1236 * KERN_SUCCESS The usual.
1237 * KERN_INVALID_ADDRESS There was a hole in the region.
1238 */
1239
1240 kern_return_t
1241 mach_vm_msync(
1242 vm_map_t map,
1243 mach_vm_address_t address,
1244 mach_vm_size_t size,
1245 vm_sync_t sync_flags)
1246 {
1247
1248 if (map == VM_MAP_NULL)
1249 return(KERN_INVALID_TASK);
1250
1251 return vm_map_msync(map, (vm_map_address_t)address,
1252 (vm_map_size_t)size, sync_flags);
1253 }
1254
1255 /*
1256 * vm_msync
1257 *
1258 * Synchronises the memory range specified with its backing store
1259 * image by either flushing or cleaning the contents to the appropriate
1260 * memory manager.
1261 *
1262 * interpretation of sync_flags
1263 * VM_SYNC_INVALIDATE - discard pages, only return precious
1264 * pages to manager.
1265 *
1266 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1267 * - discard pages, write dirty or precious
1268 * pages back to memory manager.
1269 *
1270 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1271 * - write dirty or precious pages back to
1272 * the memory manager.
1273 *
1274 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1275 * is a hole in the region, and we would
1276 * have returned KERN_SUCCESS, return
1277 * KERN_INVALID_ADDRESS instead.
1278 *
1279 * The addressability of the range is limited to that which can
1280 * be described by a vm_address_t.
1281 *
1282 * RETURNS
1283 * KERN_INVALID_TASK Bad task parameter
1284 * KERN_INVALID_ARGUMENT both sync and async were specified.
1285 * KERN_SUCCESS The usual.
1286 * KERN_INVALID_ADDRESS There was a hole in the region.
1287 */
1288
1289 kern_return_t
1290 vm_msync(
1291 vm_map_t map,
1292 vm_address_t address,
1293 vm_size_t size,
1294 vm_sync_t sync_flags)
1295 {
1296
1297 if (map == VM_MAP_NULL)
1298 return(KERN_INVALID_TASK);
1299
1300 return vm_map_msync(map, (vm_map_address_t)address,
1301 (vm_map_size_t)size, sync_flags);
1302 }
1303
1304
1305 int
1306 vm_toggle_entry_reuse(int toggle, int *old_value)
1307 {
1308 vm_map_t map = current_map();
1309
1310 assert(!map->is_nested_map);
1311 if(toggle == VM_TOGGLE_GETVALUE && old_value != NULL){
1312 *old_value = map->disable_vmentry_reuse;
1313 } else if(toggle == VM_TOGGLE_SET){
1314 vm_map_entry_t map_to_entry;
1315
1316 vm_map_lock(map);
1317 vm_map_disable_hole_optimization(map);
1318 map->disable_vmentry_reuse = TRUE;
1319 __IGNORE_WCASTALIGN(map_to_entry = vm_map_to_entry(map));
1320 if (map->first_free == map_to_entry) {
1321 map->highest_entry_end = vm_map_min(map);
1322 } else {
1323 map->highest_entry_end = map->first_free->vme_end;
1324 }
1325 vm_map_unlock(map);
1326 } else if (toggle == VM_TOGGLE_CLEAR){
1327 vm_map_lock(map);
1328 map->disable_vmentry_reuse = FALSE;
1329 vm_map_unlock(map);
1330 } else
1331 return KERN_INVALID_ARGUMENT;
1332
1333 return KERN_SUCCESS;
1334 }
1335
1336 /*
1337 * mach_vm_behavior_set
1338 *
1339 * Sets the paging behavior attribute for the specified range
1340 * in the specified map.
1341 *
1342 * This routine will fail with KERN_INVALID_ADDRESS if any address
1343 * in [start,start+size) is not a valid allocated memory region.
1344 */
1345 kern_return_t
1346 mach_vm_behavior_set(
1347 vm_map_t map,
1348 mach_vm_offset_t start,
1349 mach_vm_size_t size,
1350 vm_behavior_t new_behavior)
1351 {
1352 vm_map_offset_t align_mask;
1353
1354 if ((map == VM_MAP_NULL) || (start + size < start))
1355 return(KERN_INVALID_ARGUMENT);
1356
1357 if (size == 0)
1358 return KERN_SUCCESS;
1359
1360 switch (new_behavior) {
1361 case VM_BEHAVIOR_REUSABLE:
1362 case VM_BEHAVIOR_REUSE:
1363 case VM_BEHAVIOR_CAN_REUSE:
1364 /*
1365 * Align to the hardware page size, to allow
1366 * malloc() to maximize the amount of re-usability,
1367 * even on systems with larger software page size.
1368 */
1369 align_mask = PAGE_MASK;
1370 break;
1371 default:
1372 align_mask = VM_MAP_PAGE_MASK(map);
1373 break;
1374 }
1375
1376 return vm_map_behavior_set(map,
1377 vm_map_trunc_page(start, align_mask),
1378 vm_map_round_page(start+size, align_mask),
1379 new_behavior);
1380 }
1381
1382 /*
1383 * vm_behavior_set
1384 *
1385 * Sets the paging behavior attribute for the specified range
1386 * in the specified map.
1387 *
1388 * This routine will fail with KERN_INVALID_ADDRESS if any address
1389 * in [start,start+size) is not a valid allocated memory region.
1390 *
1391 * This routine is potentially limited in addressibility by the
1392 * use of vm_offset_t (if the map provided is larger than the
1393 * kernel's).
1394 */
1395 kern_return_t
1396 vm_behavior_set(
1397 vm_map_t map,
1398 vm_offset_t start,
1399 vm_size_t size,
1400 vm_behavior_t new_behavior)
1401 {
1402 if (start + size < start)
1403 return KERN_INVALID_ARGUMENT;
1404
1405 return mach_vm_behavior_set(map,
1406 (mach_vm_offset_t) start,
1407 (mach_vm_size_t) size,
1408 new_behavior);
1409 }
1410
1411 /*
1412 * mach_vm_region:
1413 *
1414 * User call to obtain information about a region in
1415 * a task's address map. Currently, only one flavor is
1416 * supported.
1417 *
1418 * XXX The reserved and behavior fields cannot be filled
1419 * in until the vm merge from the IK is completed, and
1420 * vm_reserve is implemented.
1421 *
1422 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1423 */
1424
1425 kern_return_t
1426 mach_vm_region(
1427 vm_map_t map,
1428 mach_vm_offset_t *address, /* IN/OUT */
1429 mach_vm_size_t *size, /* OUT */
1430 vm_region_flavor_t flavor, /* IN */
1431 vm_region_info_t info, /* OUT */
1432 mach_msg_type_number_t *count, /* IN/OUT */
1433 mach_port_t *object_name) /* OUT */
1434 {
1435 vm_map_offset_t map_addr;
1436 vm_map_size_t map_size;
1437 kern_return_t kr;
1438
1439 if (VM_MAP_NULL == map)
1440 return KERN_INVALID_ARGUMENT;
1441
1442 map_addr = (vm_map_offset_t)*address;
1443 map_size = (vm_map_size_t)*size;
1444
1445 /* legacy conversion */
1446 if (VM_REGION_BASIC_INFO == flavor)
1447 flavor = VM_REGION_BASIC_INFO_64;
1448
1449 kr = vm_map_region(map,
1450 &map_addr, &map_size,
1451 flavor, info, count,
1452 object_name);
1453
1454 *address = map_addr;
1455 *size = map_size;
1456 return kr;
1457 }
1458
1459 /*
1460 * vm_region_64 and vm_region:
1461 *
1462 * User call to obtain information about a region in
1463 * a task's address map. Currently, only one flavor is
1464 * supported.
1465 *
1466 * XXX The reserved and behavior fields cannot be filled
1467 * in until the vm merge from the IK is completed, and
1468 * vm_reserve is implemented.
1469 *
1470 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1471 */
1472
1473 kern_return_t
1474 vm_region_64(
1475 vm_map_t map,
1476 vm_offset_t *address, /* IN/OUT */
1477 vm_size_t *size, /* OUT */
1478 vm_region_flavor_t flavor, /* IN */
1479 vm_region_info_t info, /* OUT */
1480 mach_msg_type_number_t *count, /* IN/OUT */
1481 mach_port_t *object_name) /* OUT */
1482 {
1483 vm_map_offset_t map_addr;
1484 vm_map_size_t map_size;
1485 kern_return_t kr;
1486
1487 if (VM_MAP_NULL == map)
1488 return KERN_INVALID_ARGUMENT;
1489
1490 map_addr = (vm_map_offset_t)*address;
1491 map_size = (vm_map_size_t)*size;
1492
1493 /* legacy conversion */
1494 if (VM_REGION_BASIC_INFO == flavor)
1495 flavor = VM_REGION_BASIC_INFO_64;
1496
1497 kr = vm_map_region(map,
1498 &map_addr, &map_size,
1499 flavor, info, count,
1500 object_name);
1501
1502 *address = CAST_DOWN(vm_offset_t, map_addr);
1503 *size = CAST_DOWN(vm_size_t, map_size);
1504
1505 if (KERN_SUCCESS == kr && map_addr + map_size > VM_MAX_ADDRESS)
1506 return KERN_INVALID_ADDRESS;
1507 return kr;
1508 }
1509
1510 kern_return_t
1511 vm_region(
1512 vm_map_t map,
1513 vm_address_t *address, /* IN/OUT */
1514 vm_size_t *size, /* OUT */
1515 vm_region_flavor_t flavor, /* IN */
1516 vm_region_info_t info, /* OUT */
1517 mach_msg_type_number_t *count, /* IN/OUT */
1518 mach_port_t *object_name) /* OUT */
1519 {
1520 vm_map_address_t map_addr;
1521 vm_map_size_t map_size;
1522 kern_return_t kr;
1523
1524 if (VM_MAP_NULL == map)
1525 return KERN_INVALID_ARGUMENT;
1526
1527 map_addr = (vm_map_address_t)*address;
1528 map_size = (vm_map_size_t)*size;
1529
1530 kr = vm_map_region(map,
1531 &map_addr, &map_size,
1532 flavor, info, count,
1533 object_name);
1534
1535 *address = CAST_DOWN(vm_address_t, map_addr);
1536 *size = CAST_DOWN(vm_size_t, map_size);
1537
1538 if (KERN_SUCCESS == kr && map_addr + map_size > VM_MAX_ADDRESS)
1539 return KERN_INVALID_ADDRESS;
1540 return kr;
1541 }
1542
1543 /*
1544 * vm_region_recurse: A form of vm_region which follows the
1545 * submaps in a target map
1546 *
1547 */
1548 kern_return_t
1549 mach_vm_region_recurse(
1550 vm_map_t map,
1551 mach_vm_address_t *address,
1552 mach_vm_size_t *size,
1553 uint32_t *depth,
1554 vm_region_recurse_info_t info,
1555 mach_msg_type_number_t *infoCnt)
1556 {
1557 vm_map_address_t map_addr;
1558 vm_map_size_t map_size;
1559 kern_return_t kr;
1560
1561 if (VM_MAP_NULL == map)
1562 return KERN_INVALID_ARGUMENT;
1563
1564 map_addr = (vm_map_address_t)*address;
1565 map_size = (vm_map_size_t)*size;
1566
1567 kr = vm_map_region_recurse_64(
1568 map,
1569 &map_addr,
1570 &map_size,
1571 depth,
1572 (vm_region_submap_info_64_t)info,
1573 infoCnt);
1574
1575 *address = map_addr;
1576 *size = map_size;
1577 return kr;
1578 }
1579
1580 /*
1581 * vm_region_recurse: A form of vm_region which follows the
1582 * submaps in a target map
1583 *
1584 */
1585 kern_return_t
1586 vm_region_recurse_64(
1587 vm_map_t map,
1588 vm_address_t *address,
1589 vm_size_t *size,
1590 uint32_t *depth,
1591 vm_region_recurse_info_64_t info,
1592 mach_msg_type_number_t *infoCnt)
1593 {
1594 vm_map_address_t map_addr;
1595 vm_map_size_t map_size;
1596 kern_return_t kr;
1597
1598 if (VM_MAP_NULL == map)
1599 return KERN_INVALID_ARGUMENT;
1600
1601 map_addr = (vm_map_address_t)*address;
1602 map_size = (vm_map_size_t)*size;
1603
1604 kr = vm_map_region_recurse_64(
1605 map,
1606 &map_addr,
1607 &map_size,
1608 depth,
1609 (vm_region_submap_info_64_t)info,
1610 infoCnt);
1611
1612 *address = CAST_DOWN(vm_address_t, map_addr);
1613 *size = CAST_DOWN(vm_size_t, map_size);
1614
1615 if (KERN_SUCCESS == kr && map_addr + map_size > VM_MAX_ADDRESS)
1616 return KERN_INVALID_ADDRESS;
1617 return kr;
1618 }
1619
1620 kern_return_t
1621 vm_region_recurse(
1622 vm_map_t map,
1623 vm_offset_t *address, /* IN/OUT */
1624 vm_size_t *size, /* OUT */
1625 natural_t *depth, /* IN/OUT */
1626 vm_region_recurse_info_t info32, /* IN/OUT */
1627 mach_msg_type_number_t *infoCnt) /* IN/OUT */
1628 {
1629 vm_region_submap_info_data_64_t info64;
1630 vm_region_submap_info_t info;
1631 vm_map_address_t map_addr;
1632 vm_map_size_t map_size;
1633 kern_return_t kr;
1634
1635 if (VM_MAP_NULL == map || *infoCnt < VM_REGION_SUBMAP_INFO_COUNT)
1636 return KERN_INVALID_ARGUMENT;
1637
1638
1639 map_addr = (vm_map_address_t)*address;
1640 map_size = (vm_map_size_t)*size;
1641 info = (vm_region_submap_info_t)info32;
1642 *infoCnt = VM_REGION_SUBMAP_INFO_COUNT_64;
1643
1644 kr = vm_map_region_recurse_64(map, &map_addr,&map_size,
1645 depth, &info64, infoCnt);
1646
1647 info->protection = info64.protection;
1648 info->max_protection = info64.max_protection;
1649 info->inheritance = info64.inheritance;
1650 info->offset = (uint32_t)info64.offset; /* trouble-maker */
1651 info->user_tag = info64.user_tag;
1652 info->pages_resident = info64.pages_resident;
1653 info->pages_shared_now_private = info64.pages_shared_now_private;
1654 info->pages_swapped_out = info64.pages_swapped_out;
1655 info->pages_dirtied = info64.pages_dirtied;
1656 info->ref_count = info64.ref_count;
1657 info->shadow_depth = info64.shadow_depth;
1658 info->external_pager = info64.external_pager;
1659 info->share_mode = info64.share_mode;
1660 info->is_submap = info64.is_submap;
1661 info->behavior = info64.behavior;
1662 info->object_id = info64.object_id;
1663 info->user_wired_count = info64.user_wired_count;
1664
1665 *address = CAST_DOWN(vm_address_t, map_addr);
1666 *size = CAST_DOWN(vm_size_t, map_size);
1667 *infoCnt = VM_REGION_SUBMAP_INFO_COUNT;
1668
1669 if (KERN_SUCCESS == kr && map_addr + map_size > VM_MAX_ADDRESS)
1670 return KERN_INVALID_ADDRESS;
1671 return kr;
1672 }
1673
1674 kern_return_t
1675 mach_vm_purgable_control(
1676 vm_map_t map,
1677 mach_vm_offset_t address,
1678 vm_purgable_t control,
1679 int *state)
1680 {
1681 if (VM_MAP_NULL == map)
1682 return KERN_INVALID_ARGUMENT;
1683
1684 return vm_map_purgable_control(map,
1685 vm_map_trunc_page(address, PAGE_MASK),
1686 control,
1687 state);
1688 }
1689
1690 kern_return_t
1691 vm_purgable_control(
1692 vm_map_t map,
1693 vm_offset_t address,
1694 vm_purgable_t control,
1695 int *state)
1696 {
1697 if (VM_MAP_NULL == map)
1698 return KERN_INVALID_ARGUMENT;
1699
1700 return vm_map_purgable_control(map,
1701 vm_map_trunc_page(address, PAGE_MASK),
1702 control,
1703 state);
1704 }
1705
1706
1707 /*
1708 * Ordinarily, the right to allocate CPM is restricted
1709 * to privileged applications (those that can gain access
1710 * to the host priv port). Set this variable to zero if
1711 * you want to let any application allocate CPM.
1712 */
1713 unsigned int vm_allocate_cpm_privileged = 0;
1714
1715 /*
1716 * Allocate memory in the specified map, with the caveat that
1717 * the memory is physically contiguous. This call may fail
1718 * if the system can't find sufficient contiguous memory.
1719 * This call may cause or lead to heart-stopping amounts of
1720 * paging activity.
1721 *
1722 * Memory obtained from this call should be freed in the
1723 * normal way, viz., via vm_deallocate.
1724 */
1725 kern_return_t
1726 vm_allocate_cpm(
1727 host_priv_t host_priv,
1728 vm_map_t map,
1729 vm_address_t *addr,
1730 vm_size_t size,
1731 int flags)
1732 {
1733 vm_map_address_t map_addr;
1734 vm_map_size_t map_size;
1735 kern_return_t kr;
1736
1737 if (vm_allocate_cpm_privileged && HOST_PRIV_NULL == host_priv)
1738 return KERN_INVALID_HOST;
1739
1740 if (VM_MAP_NULL == map)
1741 return KERN_INVALID_ARGUMENT;
1742
1743 map_addr = (vm_map_address_t)*addr;
1744 map_size = (vm_map_size_t)size;
1745
1746 kr = vm_map_enter_cpm(map,
1747 &map_addr,
1748 map_size,
1749 flags);
1750
1751 *addr = CAST_DOWN(vm_address_t, map_addr);
1752 return kr;
1753 }
1754
1755
1756 kern_return_t
1757 mach_vm_page_query(
1758 vm_map_t map,
1759 mach_vm_offset_t offset,
1760 int *disposition,
1761 int *ref_count)
1762 {
1763 if (VM_MAP_NULL == map)
1764 return KERN_INVALID_ARGUMENT;
1765
1766 return vm_map_page_query_internal(
1767 map,
1768 vm_map_trunc_page(offset, PAGE_MASK),
1769 disposition, ref_count);
1770 }
1771
1772 kern_return_t
1773 vm_map_page_query(
1774 vm_map_t map,
1775 vm_offset_t offset,
1776 int *disposition,
1777 int *ref_count)
1778 {
1779 if (VM_MAP_NULL == map)
1780 return KERN_INVALID_ARGUMENT;
1781
1782 return vm_map_page_query_internal(
1783 map,
1784 vm_map_trunc_page(offset, PAGE_MASK),
1785 disposition, ref_count);
1786 }
1787
1788 kern_return_t
1789 mach_vm_page_info(
1790 vm_map_t map,
1791 mach_vm_address_t address,
1792 vm_page_info_flavor_t flavor,
1793 vm_page_info_t info,
1794 mach_msg_type_number_t *count)
1795 {
1796 kern_return_t kr;
1797
1798 if (map == VM_MAP_NULL) {
1799 return KERN_INVALID_ARGUMENT;
1800 }
1801
1802 kr = vm_map_page_info(map, address, flavor, info, count);
1803 return kr;
1804 }
1805
1806 /* map a (whole) upl into an address space */
1807 kern_return_t
1808 vm_upl_map(
1809 vm_map_t map,
1810 upl_t upl,
1811 vm_address_t *dst_addr)
1812 {
1813 vm_map_offset_t map_addr;
1814 kern_return_t kr;
1815
1816 if (VM_MAP_NULL == map)
1817 return KERN_INVALID_ARGUMENT;
1818
1819 kr = vm_map_enter_upl(map, upl, &map_addr);
1820 *dst_addr = CAST_DOWN(vm_address_t, map_addr);
1821 return kr;
1822 }
1823
1824 kern_return_t
1825 vm_upl_unmap(
1826 vm_map_t map,
1827 upl_t upl)
1828 {
1829 if (VM_MAP_NULL == map)
1830 return KERN_INVALID_ARGUMENT;
1831
1832 return (vm_map_remove_upl(map, upl));
1833 }
1834
1835 /* Retrieve a upl for an object underlying an address range in a map */
1836
1837 kern_return_t
1838 vm_map_get_upl(
1839 vm_map_t map,
1840 vm_map_offset_t map_offset,
1841 upl_size_t *upl_size,
1842 upl_t *upl,
1843 upl_page_info_array_t page_list,
1844 unsigned int *count,
1845 upl_control_flags_t *flags,
1846 int force_data_sync)
1847 {
1848 upl_control_flags_t map_flags;
1849 kern_return_t kr;
1850
1851 if (VM_MAP_NULL == map)
1852 return KERN_INVALID_ARGUMENT;
1853
1854 map_flags = *flags & ~UPL_NOZEROFILL;
1855 if (force_data_sync)
1856 map_flags |= UPL_FORCE_DATA_SYNC;
1857
1858 kr = vm_map_create_upl(map,
1859 map_offset,
1860 upl_size,
1861 upl,
1862 page_list,
1863 count,
1864 &map_flags);
1865
1866 *flags = (map_flags & ~UPL_FORCE_DATA_SYNC);
1867 return kr;
1868 }
1869
1870
1871 /*
1872 * mach_make_memory_entry_64
1873 *
1874 * Think of it as a two-stage vm_remap() operation. First
1875 * you get a handle. Second, you get map that handle in
1876 * somewhere else. Rather than doing it all at once (and
1877 * without needing access to the other whole map).
1878 */
1879
1880 kern_return_t
1881 mach_make_memory_entry_64(
1882 vm_map_t target_map,
1883 memory_object_size_t *size,
1884 memory_object_offset_t offset,
1885 vm_prot_t permission,
1886 ipc_port_t *object_handle,
1887 ipc_port_t parent_handle)
1888 {
1889 vm_map_version_t version;
1890 vm_named_entry_t parent_entry;
1891 vm_named_entry_t user_entry;
1892 ipc_port_t user_handle;
1893 kern_return_t kr;
1894 vm_map_t real_map;
1895
1896 /* needed for call to vm_map_lookup_locked */
1897 boolean_t wired;
1898 boolean_t iskernel;
1899 vm_object_offset_t obj_off;
1900 vm_prot_t prot;
1901 struct vm_object_fault_info fault_info;
1902 vm_object_t object;
1903 vm_object_t shadow_object;
1904
1905 /* needed for direct map entry manipulation */
1906 vm_map_entry_t map_entry;
1907 vm_map_entry_t next_entry;
1908 vm_map_t local_map;
1909 vm_map_t original_map = target_map;
1910 vm_map_size_t total_size, map_size;
1911 vm_map_offset_t map_start, map_end;
1912 vm_map_offset_t local_offset;
1913 vm_object_size_t mappable_size;
1914
1915 /*
1916 * Stash the offset in the page for use by vm_map_enter_mem_object()
1917 * in the VM_FLAGS_RETURN_DATA_ADDR/MAP_MEM_USE_DATA_ADDR case.
1918 */
1919 vm_object_offset_t offset_in_page;
1920
1921 unsigned int access;
1922 vm_prot_t protections;
1923 vm_prot_t original_protections, mask_protections;
1924 unsigned int wimg_mode;
1925
1926 boolean_t force_shadow = FALSE;
1927 boolean_t use_data_addr;
1928 boolean_t use_4K_compat;
1929
1930 if (((permission & 0x00FF0000) &
1931 ~(MAP_MEM_ONLY |
1932 MAP_MEM_NAMED_CREATE |
1933 MAP_MEM_GRAB_SECLUDED | /* XXX FBDP TODO: restrict usage? */
1934 MAP_MEM_PURGABLE |
1935 MAP_MEM_NAMED_REUSE |
1936 MAP_MEM_USE_DATA_ADDR |
1937 MAP_MEM_VM_COPY |
1938 MAP_MEM_4K_DATA_ADDR |
1939 MAP_MEM_VM_SHARE))) {
1940 /*
1941 * Unknown flag: reject for forward compatibility.
1942 */
1943 return KERN_INVALID_VALUE;
1944 }
1945
1946 if (parent_handle != IP_NULL &&
1947 ip_kotype(parent_handle) == IKOT_NAMED_ENTRY) {
1948 parent_entry = (vm_named_entry_t) parent_handle->ip_kobject;
1949 } else {
1950 parent_entry = NULL;
1951 }
1952
1953 if (parent_entry && parent_entry->is_copy) {
1954 return KERN_INVALID_ARGUMENT;
1955 }
1956
1957 original_protections = permission & VM_PROT_ALL;
1958 protections = original_protections;
1959 mask_protections = permission & VM_PROT_IS_MASK;
1960 access = GET_MAP_MEM(permission);
1961 use_data_addr = ((permission & MAP_MEM_USE_DATA_ADDR) != 0);
1962 use_4K_compat = ((permission & MAP_MEM_4K_DATA_ADDR) != 0);
1963
1964 user_handle = IP_NULL;
1965 user_entry = NULL;
1966
1967 map_start = vm_map_trunc_page(offset, PAGE_MASK);
1968
1969 if (permission & MAP_MEM_ONLY) {
1970 boolean_t parent_is_object;
1971
1972 map_end = vm_map_round_page(offset + *size, PAGE_MASK);
1973 map_size = map_end - map_start;
1974
1975 if (use_data_addr || use_4K_compat || parent_entry == NULL) {
1976 return KERN_INVALID_ARGUMENT;
1977 }
1978
1979 parent_is_object = !(parent_entry->is_sub_map ||
1980 parent_entry->is_pager);
1981 object = parent_entry->backing.object;
1982 if(parent_is_object && object != VM_OBJECT_NULL)
1983 wimg_mode = object->wimg_bits;
1984 else
1985 wimg_mode = VM_WIMG_USE_DEFAULT;
1986 if((access != GET_MAP_MEM(parent_entry->protection)) &&
1987 !(parent_entry->protection & VM_PROT_WRITE)) {
1988 return KERN_INVALID_RIGHT;
1989 }
1990 if(access == MAP_MEM_IO) {
1991 SET_MAP_MEM(access, parent_entry->protection);
1992 wimg_mode = VM_WIMG_IO;
1993 } else if (access == MAP_MEM_COPYBACK) {
1994 SET_MAP_MEM(access, parent_entry->protection);
1995 wimg_mode = VM_WIMG_USE_DEFAULT;
1996 } else if (access == MAP_MEM_INNERWBACK) {
1997 SET_MAP_MEM(access, parent_entry->protection);
1998 wimg_mode = VM_WIMG_INNERWBACK;
1999 } else if (access == MAP_MEM_WTHRU) {
2000 SET_MAP_MEM(access, parent_entry->protection);
2001 wimg_mode = VM_WIMG_WTHRU;
2002 } else if (access == MAP_MEM_WCOMB) {
2003 SET_MAP_MEM(access, parent_entry->protection);
2004 wimg_mode = VM_WIMG_WCOMB;
2005 }
2006 if (parent_is_object && object &&
2007 (access != MAP_MEM_NOOP) &&
2008 (!(object->nophyscache))) {
2009
2010 if (object->wimg_bits != wimg_mode) {
2011 vm_object_lock(object);
2012 vm_object_change_wimg_mode(object, wimg_mode);
2013 vm_object_unlock(object);
2014 }
2015 }
2016 if (object_handle)
2017 *object_handle = IP_NULL;
2018 return KERN_SUCCESS;
2019 } else if (permission & MAP_MEM_NAMED_CREATE) {
2020 map_end = vm_map_round_page(offset + *size, PAGE_MASK);
2021 map_size = map_end - map_start;
2022
2023 if (use_data_addr || use_4K_compat) {
2024 return KERN_INVALID_ARGUMENT;
2025 }
2026
2027 kr = mach_memory_entry_allocate(&user_entry, &user_handle);
2028 if (kr != KERN_SUCCESS) {
2029 return KERN_FAILURE;
2030 }
2031
2032 /*
2033 * Force the creation of the VM object now.
2034 */
2035 if (map_size > (vm_map_size_t) ANON_MAX_SIZE) {
2036 /*
2037 * LP64todo - for now, we can only allocate 4GB-4096
2038 * internal objects because the default pager can't
2039 * page bigger ones. Remove this when it can.
2040 */
2041 kr = KERN_FAILURE;
2042 goto make_mem_done;
2043 }
2044
2045 object = vm_object_allocate(map_size);
2046 assert(object != VM_OBJECT_NULL);
2047
2048 if (permission & MAP_MEM_PURGABLE) {
2049 if (! (permission & VM_PROT_WRITE)) {
2050 /* if we can't write, we can't purge */
2051 vm_object_deallocate(object);
2052 kr = KERN_INVALID_ARGUMENT;
2053 goto make_mem_done;
2054 }
2055 object->purgable = VM_PURGABLE_NONVOLATILE;
2056 assert(object->vo_purgeable_owner == NULL);
2057 assert(object->resident_page_count == 0);
2058 assert(object->wired_page_count == 0);
2059 vm_object_lock(object);
2060 vm_purgeable_nonvolatile_enqueue(object,
2061 current_task());
2062 vm_object_unlock(object);
2063 }
2064
2065 #if CONFIG_SECLUDED_MEMORY
2066 if (secluded_for_iokit && /* global boot-arg */
2067 ((permission & MAP_MEM_GRAB_SECLUDED)
2068 #if 11
2069 /* XXX FBDP for my testing only */
2070 || (secluded_for_fbdp && map_size == 97550336)
2071 #endif
2072 )) {
2073 #if 11
2074 if (!(permission & MAP_MEM_GRAB_SECLUDED) &&
2075 secluded_for_fbdp) {
2076 printf("FBDP: object %p size %lld can grab secluded\n", object, (uint64_t) map_size);
2077 }
2078 #endif
2079 object->can_grab_secluded = TRUE;
2080 assert(!object->eligible_for_secluded);
2081 }
2082 #endif /* CONFIG_SECLUDED_MEMORY */
2083
2084 /*
2085 * The VM object is brand new and nobody else knows about it,
2086 * so we don't need to lock it.
2087 */
2088
2089 wimg_mode = object->wimg_bits;
2090 if (access == MAP_MEM_IO) {
2091 wimg_mode = VM_WIMG_IO;
2092 } else if (access == MAP_MEM_COPYBACK) {
2093 wimg_mode = VM_WIMG_USE_DEFAULT;
2094 } else if (access == MAP_MEM_INNERWBACK) {
2095 wimg_mode = VM_WIMG_INNERWBACK;
2096 } else if (access == MAP_MEM_WTHRU) {
2097 wimg_mode = VM_WIMG_WTHRU;
2098 } else if (access == MAP_MEM_WCOMB) {
2099 wimg_mode = VM_WIMG_WCOMB;
2100 }
2101 if (access != MAP_MEM_NOOP) {
2102 object->wimg_bits = wimg_mode;
2103 }
2104 /* the object has no pages, so no WIMG bits to update here */
2105
2106 /*
2107 * XXX
2108 * We use this path when we want to make sure that
2109 * nobody messes with the object (coalesce, for
2110 * example) before we map it.
2111 * We might want to use these objects for transposition via
2112 * vm_object_transpose() too, so we don't want any copy or
2113 * shadow objects either...
2114 */
2115 object->copy_strategy = MEMORY_OBJECT_COPY_NONE;
2116 object->true_share = TRUE;
2117
2118 user_entry->backing.object = object;
2119 user_entry->internal = TRUE;
2120 user_entry->is_sub_map = FALSE;
2121 user_entry->is_pager = FALSE;
2122 user_entry->offset = 0;
2123 user_entry->data_offset = 0;
2124 user_entry->protection = protections;
2125 SET_MAP_MEM(access, user_entry->protection);
2126 user_entry->size = map_size;
2127
2128 /* user_object pager and internal fields are not used */
2129 /* when the object field is filled in. */
2130
2131 *size = CAST_DOWN(vm_size_t, (user_entry->size -
2132 user_entry->data_offset));
2133 *object_handle = user_handle;
2134 return KERN_SUCCESS;
2135 }
2136
2137 if (permission & MAP_MEM_VM_COPY) {
2138 vm_map_copy_t copy;
2139
2140 if (target_map == VM_MAP_NULL) {
2141 return KERN_INVALID_TASK;
2142 }
2143
2144 map_end = vm_map_round_page(offset + *size, PAGE_MASK);
2145 map_size = map_end - map_start;
2146 if (use_data_addr || use_4K_compat) {
2147 offset_in_page = offset - map_start;
2148 if (use_4K_compat)
2149 offset_in_page &= ~((signed)(0xFFF));
2150 } else {
2151 offset_in_page = 0;
2152 }
2153
2154 kr = vm_map_copyin_internal(target_map,
2155 map_start,
2156 map_size,
2157 VM_MAP_COPYIN_ENTRY_LIST,
2158 &copy);
2159 if (kr != KERN_SUCCESS) {
2160 return kr;
2161 }
2162
2163 kr = mach_memory_entry_allocate(&user_entry, &user_handle);
2164 if (kr != KERN_SUCCESS) {
2165 vm_map_copy_discard(copy);
2166 return KERN_FAILURE;
2167 }
2168
2169 user_entry->backing.copy = copy;
2170 user_entry->internal = FALSE;
2171 user_entry->is_sub_map = FALSE;
2172 user_entry->is_pager = FALSE;
2173 user_entry->is_copy = TRUE;
2174 user_entry->offset = 0;
2175 user_entry->protection = protections;
2176 user_entry->size = map_size;
2177 user_entry->data_offset = offset_in_page;
2178
2179 *size = CAST_DOWN(vm_size_t, (user_entry->size -
2180 user_entry->data_offset));
2181 *object_handle = user_handle;
2182 return KERN_SUCCESS;
2183 }
2184
2185 if (permission & MAP_MEM_VM_SHARE) {
2186 vm_map_copy_t copy;
2187 vm_prot_t cur_prot, max_prot;
2188
2189 if (target_map == VM_MAP_NULL) {
2190 return KERN_INVALID_TASK;
2191 }
2192
2193 map_end = vm_map_round_page(offset + *size, PAGE_MASK);
2194 map_size = map_end - map_start;
2195 if (use_data_addr || use_4K_compat) {
2196 offset_in_page = offset - map_start;
2197 if (use_4K_compat)
2198 offset_in_page &= ~((signed)(0xFFF));
2199 } else {
2200 offset_in_page = 0;
2201 }
2202
2203 cur_prot = VM_PROT_ALL;
2204 kr = vm_map_copy_extract(target_map,
2205 map_start,
2206 map_size,
2207 &copy,
2208 &cur_prot,
2209 &max_prot);
2210 if (kr != KERN_SUCCESS) {
2211 return kr;
2212 }
2213
2214 if (mask_protections) {
2215 /*
2216 * We just want as much of "original_protections"
2217 * as we can get out of the actual "cur_prot".
2218 */
2219 protections &= cur_prot;
2220 if (protections == VM_PROT_NONE) {
2221 /* no access at all: fail */
2222 vm_map_copy_discard(copy);
2223 return KERN_PROTECTION_FAILURE;
2224 }
2225 } else {
2226 /*
2227 * We want exactly "original_protections"
2228 * out of "cur_prot".
2229 */
2230 if ((cur_prot & protections) != protections) {
2231 vm_map_copy_discard(copy);
2232 return KERN_PROTECTION_FAILURE;
2233 }
2234 }
2235
2236 kr = mach_memory_entry_allocate(&user_entry, &user_handle);
2237 if (kr != KERN_SUCCESS) {
2238 vm_map_copy_discard(copy);
2239 return KERN_FAILURE;
2240 }
2241
2242 user_entry->backing.copy = copy;
2243 user_entry->internal = FALSE;
2244 user_entry->is_sub_map = FALSE;
2245 user_entry->is_pager = FALSE;
2246 user_entry->is_copy = TRUE;
2247 user_entry->offset = 0;
2248 user_entry->protection = protections;
2249 user_entry->size = map_size;
2250 user_entry->data_offset = offset_in_page;
2251
2252 *size = CAST_DOWN(vm_size_t, (user_entry->size -
2253 user_entry->data_offset));
2254 *object_handle = user_handle;
2255 return KERN_SUCCESS;
2256 }
2257
2258 if (parent_entry == NULL ||
2259 (permission & MAP_MEM_NAMED_REUSE)) {
2260
2261 map_end = vm_map_round_page(offset + *size, PAGE_MASK);
2262 map_size = map_end - map_start;
2263 if (use_data_addr || use_4K_compat) {
2264 offset_in_page = offset - map_start;
2265 if (use_4K_compat)
2266 offset_in_page &= ~((signed)(0xFFF));
2267 } else {
2268 offset_in_page = 0;
2269 }
2270
2271 /* Create a named object based on address range within the task map */
2272 /* Go find the object at given address */
2273
2274 if (target_map == VM_MAP_NULL) {
2275 return KERN_INVALID_TASK;
2276 }
2277
2278 redo_lookup:
2279 protections = original_protections;
2280 vm_map_lock_read(target_map);
2281
2282 /* get the object associated with the target address */
2283 /* note we check the permission of the range against */
2284 /* that requested by the caller */
2285
2286 kr = vm_map_lookup_locked(&target_map, map_start,
2287 protections | mask_protections,
2288 OBJECT_LOCK_EXCLUSIVE, &version,
2289 &object, &obj_off, &prot, &wired,
2290 &fault_info,
2291 &real_map);
2292 if (kr != KERN_SUCCESS) {
2293 vm_map_unlock_read(target_map);
2294 goto make_mem_done;
2295 }
2296 if (mask_protections) {
2297 /*
2298 * The caller asked us to use the "protections" as
2299 * a mask, so restrict "protections" to what this
2300 * mapping actually allows.
2301 */
2302 protections &= prot;
2303 }
2304
2305 if (((prot & protections) != protections)
2306 || (object == kernel_object)) {
2307 kr = KERN_INVALID_RIGHT;
2308 vm_object_unlock(object);
2309 vm_map_unlock_read(target_map);
2310 if(real_map != target_map)
2311 vm_map_unlock_read(real_map);
2312 if(object == kernel_object) {
2313 printf("Warning: Attempt to create a named"
2314 " entry from the kernel_object\n");
2315 }
2316 goto make_mem_done;
2317 }
2318
2319 /* We have an object, now check to see if this object */
2320 /* is suitable. If not, create a shadow and share that */
2321
2322 /*
2323 * We have to unlock the VM object to avoid deadlocking with
2324 * a VM map lock (the lock ordering is map, the object), if we
2325 * need to modify the VM map to create a shadow object. Since
2326 * we might release the VM map lock below anyway, we have
2327 * to release the VM map lock now.
2328 * XXX FBDP There must be a way to avoid this double lookup...
2329 *
2330 * Take an extra reference on the VM object to make sure it's
2331 * not going to disappear.
2332 */
2333 vm_object_reference_locked(object); /* extra ref to hold obj */
2334 vm_object_unlock(object);
2335
2336 local_map = original_map;
2337 local_offset = map_start;
2338 if(target_map != local_map) {
2339 vm_map_unlock_read(target_map);
2340 if(real_map != target_map)
2341 vm_map_unlock_read(real_map);
2342 vm_map_lock_read(local_map);
2343 target_map = local_map;
2344 real_map = local_map;
2345 }
2346 while(TRUE) {
2347 if(!vm_map_lookup_entry(local_map,
2348 local_offset, &map_entry)) {
2349 kr = KERN_INVALID_ARGUMENT;
2350 vm_map_unlock_read(target_map);
2351 if(real_map != target_map)
2352 vm_map_unlock_read(real_map);
2353 vm_object_deallocate(object); /* release extra ref */
2354 object = VM_OBJECT_NULL;
2355 goto make_mem_done;
2356 }
2357 iskernel = (local_map->pmap == kernel_pmap);
2358 if(!(map_entry->is_sub_map)) {
2359 if (VME_OBJECT(map_entry) != object) {
2360 kr = KERN_INVALID_ARGUMENT;
2361 vm_map_unlock_read(target_map);
2362 if(real_map != target_map)
2363 vm_map_unlock_read(real_map);
2364 vm_object_deallocate(object); /* release extra ref */
2365 object = VM_OBJECT_NULL;
2366 goto make_mem_done;
2367 }
2368 break;
2369 } else {
2370 vm_map_t tmap;
2371 tmap = local_map;
2372 local_map = VME_SUBMAP(map_entry);
2373
2374 vm_map_lock_read(local_map);
2375 vm_map_unlock_read(tmap);
2376 target_map = local_map;
2377 real_map = local_map;
2378 local_offset = local_offset - map_entry->vme_start;
2379 local_offset += VME_OFFSET(map_entry);
2380 }
2381 }
2382
2383 /*
2384 * We found the VM map entry, lock the VM object again.
2385 */
2386 vm_object_lock(object);
2387 if(map_entry->wired_count) {
2388 /* JMM - The check below should be reworked instead. */
2389 object->true_share = TRUE;
2390 }
2391 if (mask_protections) {
2392 /*
2393 * The caller asked us to use the "protections" as
2394 * a mask, so restrict "protections" to what this
2395 * mapping actually allows.
2396 */
2397 protections &= map_entry->max_protection;
2398 }
2399 if(((map_entry->max_protection) & protections) != protections) {
2400 kr = KERN_INVALID_RIGHT;
2401 vm_object_unlock(object);
2402 vm_map_unlock_read(target_map);
2403 if(real_map != target_map)
2404 vm_map_unlock_read(real_map);
2405 vm_object_deallocate(object);
2406 object = VM_OBJECT_NULL;
2407 goto make_mem_done;
2408 }
2409
2410 mappable_size = fault_info.hi_offset - obj_off;
2411 total_size = map_entry->vme_end - map_entry->vme_start;
2412 if(map_size > mappable_size) {
2413 /* try to extend mappable size if the entries */
2414 /* following are from the same object and are */
2415 /* compatible */
2416 next_entry = map_entry->vme_next;
2417 /* lets see if the next map entry is still */
2418 /* pointing at this object and is contiguous */
2419 while(map_size > mappable_size) {
2420 if ((VME_OBJECT(next_entry) == object) &&
2421 (next_entry->vme_start ==
2422 next_entry->vme_prev->vme_end) &&
2423 (VME_OFFSET(next_entry) ==
2424 (VME_OFFSET(next_entry->vme_prev) +
2425 (next_entry->vme_prev->vme_end -
2426 next_entry->vme_prev->vme_start)))) {
2427 if (mask_protections) {
2428 /*
2429 * The caller asked us to use
2430 * the "protections" as a mask,
2431 * so restrict "protections" to
2432 * what this mapping actually
2433 * allows.
2434 */
2435 protections &= next_entry->max_protection;
2436 }
2437 if ((next_entry->wired_count) &&
2438 (map_entry->wired_count == 0)) {
2439 break;
2440 }
2441 if(((next_entry->max_protection)
2442 & protections) != protections) {
2443 break;
2444 }
2445 if (next_entry->needs_copy !=
2446 map_entry->needs_copy)
2447 break;
2448 mappable_size += next_entry->vme_end
2449 - next_entry->vme_start;
2450 total_size += next_entry->vme_end
2451 - next_entry->vme_start;
2452 next_entry = next_entry->vme_next;
2453 } else {
2454 break;
2455 }
2456
2457 }
2458 }
2459
2460 /* vm_map_entry_should_cow_for_true_share() checks for malloc tags,
2461 * never true in kernel */
2462 if (!iskernel && vm_map_entry_should_cow_for_true_share(map_entry) &&
2463 object->vo_size > map_size &&
2464 map_size != 0) {
2465 /*
2466 * Set up the targeted range for copy-on-write to
2467 * limit the impact of "true_share"/"copy_delay" to
2468 * that range instead of the entire VM object...
2469 */
2470
2471 vm_object_unlock(object);
2472 if (vm_map_lock_read_to_write(target_map)) {
2473 vm_object_deallocate(object);
2474 target_map = original_map;
2475 goto redo_lookup;
2476 }
2477
2478 vm_map_clip_start(target_map,
2479 map_entry,
2480 vm_map_trunc_page(map_start,
2481 VM_MAP_PAGE_MASK(target_map)));
2482 vm_map_clip_end(target_map,
2483 map_entry,
2484 (vm_map_round_page(map_end,
2485 VM_MAP_PAGE_MASK(target_map))));
2486 force_shadow = TRUE;
2487
2488 if ((map_entry->vme_end - offset) < map_size) {
2489 map_size = map_entry->vme_end - map_start;
2490 }
2491 total_size = map_entry->vme_end - map_entry->vme_start;
2492
2493 vm_map_lock_write_to_read(target_map);
2494 vm_object_lock(object);
2495 }
2496
2497 if (object->internal) {
2498 /* vm_map_lookup_locked will create a shadow if */
2499 /* needs_copy is set but does not check for the */
2500 /* other two conditions shown. It is important to */
2501 /* set up an object which will not be pulled from */
2502 /* under us. */
2503
2504 if (force_shadow ||
2505 ((map_entry->needs_copy ||
2506 object->shadowed ||
2507 (object->vo_size > total_size &&
2508 (VME_OFFSET(map_entry) != 0 ||
2509 object->vo_size >
2510 vm_map_round_page(total_size,
2511 VM_MAP_PAGE_MASK(target_map)))))
2512 && !object->true_share)) {
2513 /*
2514 * We have to unlock the VM object before
2515 * trying to upgrade the VM map lock, to
2516 * honor lock ordering (map then object).
2517 * Otherwise, we would deadlock if another
2518 * thread holds a read lock on the VM map and
2519 * is trying to acquire the VM object's lock.
2520 * We still hold an extra reference on the
2521 * VM object, guaranteeing that it won't
2522 * disappear.
2523 */
2524 vm_object_unlock(object);
2525
2526 if (vm_map_lock_read_to_write(target_map)) {
2527 /*
2528 * We couldn't upgrade our VM map lock
2529 * from "read" to "write" and we lost
2530 * our "read" lock.
2531 * Start all over again...
2532 */
2533 vm_object_deallocate(object); /* extra ref */
2534 target_map = original_map;
2535 goto redo_lookup;
2536 }
2537 #if 00
2538 vm_object_lock(object);
2539 #endif
2540
2541 /*
2542 * JMM - We need to avoid coming here when the object
2543 * is wired by anybody, not just the current map. Why
2544 * couldn't we use the standard vm_object_copy_quickly()
2545 * approach here?
2546 */
2547
2548 /* create a shadow object */
2549 VME_OBJECT_SHADOW(map_entry, total_size);
2550 shadow_object = VME_OBJECT(map_entry);
2551 #if 00
2552 vm_object_unlock(object);
2553 #endif
2554
2555 prot = map_entry->protection & ~VM_PROT_WRITE;
2556
2557 if (override_nx(target_map,
2558 VME_ALIAS(map_entry))
2559 && prot)
2560 prot |= VM_PROT_EXECUTE;
2561
2562 vm_object_pmap_protect(
2563 object, VME_OFFSET(map_entry),
2564 total_size,
2565 ((map_entry->is_shared
2566 || target_map->mapped_in_other_pmaps)
2567 ? PMAP_NULL :
2568 target_map->pmap),
2569 map_entry->vme_start,
2570 prot);
2571 total_size -= (map_entry->vme_end
2572 - map_entry->vme_start);
2573 next_entry = map_entry->vme_next;
2574 map_entry->needs_copy = FALSE;
2575
2576 vm_object_lock(shadow_object);
2577 while (total_size) {
2578 assert((next_entry->wired_count == 0) ||
2579 (map_entry->wired_count));
2580
2581 if (VME_OBJECT(next_entry) == object) {
2582 vm_object_reference_locked(shadow_object);
2583 VME_OBJECT_SET(next_entry,
2584 shadow_object);
2585 vm_object_deallocate(object);
2586 VME_OFFSET_SET(
2587 next_entry,
2588 (VME_OFFSET(next_entry->vme_prev) +
2589 (next_entry->vme_prev->vme_end
2590 - next_entry->vme_prev->vme_start)));
2591 next_entry->needs_copy = FALSE;
2592 } else {
2593 panic("mach_make_memory_entry_64:"
2594 " map entries out of sync\n");
2595 }
2596 total_size -=
2597 next_entry->vme_end
2598 - next_entry->vme_start;
2599 next_entry = next_entry->vme_next;
2600 }
2601
2602 /*
2603 * Transfer our extra reference to the
2604 * shadow object.
2605 */
2606 vm_object_reference_locked(shadow_object);
2607 vm_object_deallocate(object); /* extra ref */
2608 object = shadow_object;
2609
2610 obj_off = ((local_offset - map_entry->vme_start)
2611 + VME_OFFSET(map_entry));
2612
2613 vm_map_lock_write_to_read(target_map);
2614 }
2615 }
2616
2617 /* note: in the future we can (if necessary) allow for */
2618 /* memory object lists, this will better support */
2619 /* fragmentation, but is it necessary? The user should */
2620 /* be encouraged to create address space oriented */
2621 /* shared objects from CLEAN memory regions which have */
2622 /* a known and defined history. i.e. no inheritence */
2623 /* share, make this call before making the region the */
2624 /* target of ipc's, etc. The code above, protecting */
2625 /* against delayed copy, etc. is mostly defensive. */
2626
2627 wimg_mode = object->wimg_bits;
2628 if(!(object->nophyscache)) {
2629 if(access == MAP_MEM_IO) {
2630 wimg_mode = VM_WIMG_IO;
2631 } else if (access == MAP_MEM_COPYBACK) {
2632 wimg_mode = VM_WIMG_USE_DEFAULT;
2633 } else if (access == MAP_MEM_INNERWBACK) {
2634 wimg_mode = VM_WIMG_INNERWBACK;
2635 } else if (access == MAP_MEM_WTHRU) {
2636 wimg_mode = VM_WIMG_WTHRU;
2637 } else if (access == MAP_MEM_WCOMB) {
2638 wimg_mode = VM_WIMG_WCOMB;
2639 }
2640 }
2641
2642 #if VM_OBJECT_TRACKING_OP_TRUESHARE
2643 if (!object->true_share &&
2644 vm_object_tracking_inited) {
2645 void *bt[VM_OBJECT_TRACKING_BTDEPTH];
2646 int num = 0;
2647
2648 num = OSBacktrace(bt,
2649 VM_OBJECT_TRACKING_BTDEPTH);
2650 btlog_add_entry(vm_object_tracking_btlog,
2651 object,
2652 VM_OBJECT_TRACKING_OP_TRUESHARE,
2653 bt,
2654 num);
2655 }
2656 #endif /* VM_OBJECT_TRACKING_OP_TRUESHARE */
2657
2658 vm_object_lock_assert_exclusive(object);
2659 object->true_share = TRUE;
2660 if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC)
2661 object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
2662
2663 /*
2664 * The memory entry now points to this VM object and we
2665 * need to hold a reference on the VM object. Use the extra
2666 * reference we took earlier to keep the object alive when we
2667 * had to unlock it.
2668 */
2669
2670 vm_map_unlock_read(target_map);
2671 if(real_map != target_map)
2672 vm_map_unlock_read(real_map);
2673
2674 if (object->wimg_bits != wimg_mode)
2675 vm_object_change_wimg_mode(object, wimg_mode);
2676
2677 /* the size of mapped entry that overlaps with our region */
2678 /* which is targeted for share. */
2679 /* (entry_end - entry_start) - */
2680 /* offset of our beg addr within entry */
2681 /* it corresponds to this: */
2682
2683 if(map_size > mappable_size)
2684 map_size = mappable_size;
2685
2686 if (permission & MAP_MEM_NAMED_REUSE) {
2687 /*
2688 * Compare what we got with the "parent_entry".
2689 * If they match, re-use the "parent_entry" instead
2690 * of creating a new one.
2691 */
2692 if (parent_entry != NULL &&
2693 parent_entry->backing.object == object &&
2694 parent_entry->internal == object->internal &&
2695 parent_entry->is_sub_map == FALSE &&
2696 parent_entry->is_pager == FALSE &&
2697 parent_entry->offset == obj_off &&
2698 parent_entry->protection == protections &&
2699 parent_entry->size == map_size &&
2700 ((!(use_data_addr || use_4K_compat) &&
2701 (parent_entry->data_offset == 0)) ||
2702 ((use_data_addr || use_4K_compat) &&
2703 (parent_entry->data_offset == offset_in_page)))) {
2704 /*
2705 * We have a match: re-use "parent_entry".
2706 */
2707 /* release our extra reference on object */
2708 vm_object_unlock(object);
2709 vm_object_deallocate(object);
2710 /* parent_entry->ref_count++; XXX ? */
2711 /* Get an extra send-right on handle */
2712 ipc_port_copy_send(parent_handle);
2713
2714 *size = CAST_DOWN(vm_size_t,
2715 (parent_entry->size -
2716 parent_entry->data_offset));
2717 *object_handle = parent_handle;
2718 return KERN_SUCCESS;
2719 } else {
2720 /*
2721 * No match: we need to create a new entry.
2722 * fall through...
2723 */
2724 }
2725 }
2726
2727 vm_object_unlock(object);
2728 if (mach_memory_entry_allocate(&user_entry, &user_handle)
2729 != KERN_SUCCESS) {
2730 /* release our unused reference on the object */
2731 vm_object_deallocate(object);
2732 return KERN_FAILURE;
2733 }
2734
2735 user_entry->backing.object = object;
2736 user_entry->internal = object->internal;
2737 user_entry->is_sub_map = FALSE;
2738 user_entry->is_pager = FALSE;
2739 user_entry->offset = obj_off;
2740 user_entry->data_offset = offset_in_page;
2741 user_entry->protection = protections;
2742 SET_MAP_MEM(GET_MAP_MEM(permission), user_entry->protection);
2743 user_entry->size = map_size;
2744
2745 /* user_object pager and internal fields are not used */
2746 /* when the object field is filled in. */
2747
2748 *size = CAST_DOWN(vm_size_t, (user_entry->size -
2749 user_entry->data_offset));
2750 *object_handle = user_handle;
2751 return KERN_SUCCESS;
2752
2753 } else {
2754 /* The new object will be base on an existing named object */
2755 if (parent_entry == NULL) {
2756 kr = KERN_INVALID_ARGUMENT;
2757 goto make_mem_done;
2758 }
2759
2760 if (use_data_addr || use_4K_compat) {
2761 /*
2762 * submaps and pagers should only be accessible from within
2763 * the kernel, which shouldn't use the data address flag, so can fail here.
2764 */
2765 if (parent_entry->is_pager || parent_entry->is_sub_map) {
2766 panic("Shouldn't be using data address with a parent entry that is a submap or pager.");
2767 }
2768 /*
2769 * Account for offset to data in parent entry and
2770 * compute our own offset to data.
2771 */
2772 if((offset + *size + parent_entry->data_offset) > parent_entry->size) {
2773 kr = KERN_INVALID_ARGUMENT;
2774 goto make_mem_done;
2775 }
2776
2777 map_start = vm_map_trunc_page(offset + parent_entry->data_offset, PAGE_MASK);
2778 offset_in_page = (offset + parent_entry->data_offset) - map_start;
2779 if (use_4K_compat)
2780 offset_in_page &= ~((signed)(0xFFF));
2781 map_end = vm_map_round_page(offset + parent_entry->data_offset + *size, PAGE_MASK);
2782 map_size = map_end - map_start;
2783 } else {
2784 map_end = vm_map_round_page(offset + *size, PAGE_MASK);
2785 map_size = map_end - map_start;
2786 offset_in_page = 0;
2787
2788 if((offset + map_size) > parent_entry->size) {
2789 kr = KERN_INVALID_ARGUMENT;
2790 goto make_mem_done;
2791 }
2792 }
2793
2794 if (mask_protections) {
2795 /*
2796 * The caller asked us to use the "protections" as
2797 * a mask, so restrict "protections" to what this
2798 * mapping actually allows.
2799 */
2800 protections &= parent_entry->protection;
2801 }
2802 if((protections & parent_entry->protection) != protections) {
2803 kr = KERN_PROTECTION_FAILURE;
2804 goto make_mem_done;
2805 }
2806
2807 if (mach_memory_entry_allocate(&user_entry, &user_handle)
2808 != KERN_SUCCESS) {
2809 kr = KERN_FAILURE;
2810 goto make_mem_done;
2811 }
2812
2813 user_entry->size = map_size;
2814 user_entry->offset = parent_entry->offset + map_start;
2815 user_entry->data_offset = offset_in_page;
2816 user_entry->is_sub_map = parent_entry->is_sub_map;
2817 user_entry->is_pager = parent_entry->is_pager;
2818 user_entry->is_copy = parent_entry->is_copy;
2819 user_entry->internal = parent_entry->internal;
2820 user_entry->protection = protections;
2821
2822 if(access != MAP_MEM_NOOP) {
2823 SET_MAP_MEM(access, user_entry->protection);
2824 }
2825
2826 if(parent_entry->is_sub_map) {
2827 user_entry->backing.map = parent_entry->backing.map;
2828 vm_map_lock(user_entry->backing.map);
2829 user_entry->backing.map->ref_count++;
2830 vm_map_unlock(user_entry->backing.map);
2831 }
2832 else if (parent_entry->is_pager) {
2833 user_entry->backing.pager = parent_entry->backing.pager;
2834 /* JMM - don't we need a reference here? */
2835 } else {
2836 object = parent_entry->backing.object;
2837 assert(object != VM_OBJECT_NULL);
2838 user_entry->backing.object = object;
2839 /* we now point to this object, hold on */
2840 vm_object_lock(object);
2841 vm_object_reference_locked(object);
2842 #if VM_OBJECT_TRACKING_OP_TRUESHARE
2843 if (!object->true_share &&
2844 vm_object_tracking_inited) {
2845 void *bt[VM_OBJECT_TRACKING_BTDEPTH];
2846 int num = 0;
2847
2848 num = OSBacktrace(bt,
2849 VM_OBJECT_TRACKING_BTDEPTH);
2850 btlog_add_entry(vm_object_tracking_btlog,
2851 object,
2852 VM_OBJECT_TRACKING_OP_TRUESHARE,
2853 bt,
2854 num);
2855 }
2856 #endif /* VM_OBJECT_TRACKING_OP_TRUESHARE */
2857
2858 object->true_share = TRUE;
2859 if (object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC)
2860 object->copy_strategy = MEMORY_OBJECT_COPY_DELAY;
2861 vm_object_unlock(object);
2862 }
2863 *size = CAST_DOWN(vm_size_t, (user_entry->size -
2864 user_entry->data_offset));
2865 *object_handle = user_handle;
2866 return KERN_SUCCESS;
2867 }
2868
2869 make_mem_done:
2870 if (user_handle != IP_NULL) {
2871 /*
2872 * Releasing "user_handle" causes the kernel object
2873 * associated with it ("user_entry" here) to also be
2874 * released and freed.
2875 */
2876 mach_memory_entry_port_release(user_handle);
2877 }
2878 return kr;
2879 }
2880
2881 kern_return_t
2882 _mach_make_memory_entry(
2883 vm_map_t target_map,
2884 memory_object_size_t *size,
2885 memory_object_offset_t offset,
2886 vm_prot_t permission,
2887 ipc_port_t *object_handle,
2888 ipc_port_t parent_entry)
2889 {
2890 memory_object_size_t mo_size;
2891 kern_return_t kr;
2892
2893 mo_size = (memory_object_size_t)*size;
2894 kr = mach_make_memory_entry_64(target_map, &mo_size,
2895 (memory_object_offset_t)offset, permission, object_handle,
2896 parent_entry);
2897 *size = mo_size;
2898 return kr;
2899 }
2900
2901 kern_return_t
2902 mach_make_memory_entry(
2903 vm_map_t target_map,
2904 vm_size_t *size,
2905 vm_offset_t offset,
2906 vm_prot_t permission,
2907 ipc_port_t *object_handle,
2908 ipc_port_t parent_entry)
2909 {
2910 memory_object_size_t mo_size;
2911 kern_return_t kr;
2912
2913 mo_size = (memory_object_size_t)*size;
2914 kr = mach_make_memory_entry_64(target_map, &mo_size,
2915 (memory_object_offset_t)offset, permission, object_handle,
2916 parent_entry);
2917 *size = CAST_DOWN(vm_size_t, mo_size);
2918 return kr;
2919 }
2920
2921 /*
2922 * task_wire
2923 *
2924 * Set or clear the map's wiring_required flag. This flag, if set,
2925 * will cause all future virtual memory allocation to allocate
2926 * user wired memory. Unwiring pages wired down as a result of
2927 * this routine is done with the vm_wire interface.
2928 */
2929 kern_return_t
2930 task_wire(
2931 vm_map_t map,
2932 boolean_t must_wire)
2933 {
2934 if (map == VM_MAP_NULL)
2935 return(KERN_INVALID_ARGUMENT);
2936
2937 if (must_wire)
2938 map->wiring_required = TRUE;
2939 else
2940 map->wiring_required = FALSE;
2941
2942 return(KERN_SUCCESS);
2943 }
2944
2945 __private_extern__ kern_return_t
2946 mach_memory_entry_allocate(
2947 vm_named_entry_t *user_entry_p,
2948 ipc_port_t *user_handle_p)
2949 {
2950 vm_named_entry_t user_entry;
2951 ipc_port_t user_handle;
2952 ipc_port_t previous;
2953
2954 user_entry = (vm_named_entry_t) kalloc(sizeof *user_entry);
2955 if (user_entry == NULL)
2956 return KERN_FAILURE;
2957
2958 named_entry_lock_init(user_entry);
2959
2960 user_handle = ipc_port_alloc_kernel();
2961 if (user_handle == IP_NULL) {
2962 kfree(user_entry, sizeof *user_entry);
2963 return KERN_FAILURE;
2964 }
2965 ip_lock(user_handle);
2966
2967 /* make a sonce right */
2968 user_handle->ip_sorights++;
2969 ip_reference(user_handle);
2970
2971 user_handle->ip_destination = IP_NULL;
2972 user_handle->ip_receiver_name = MACH_PORT_NULL;
2973 user_handle->ip_receiver = ipc_space_kernel;
2974
2975 /* make a send right */
2976 user_handle->ip_mscount++;
2977 user_handle->ip_srights++;
2978 ip_reference(user_handle);
2979
2980 ipc_port_nsrequest(user_handle, 1, user_handle, &previous);
2981 /* nsrequest unlocks user_handle */
2982
2983 user_entry->backing.pager = NULL;
2984 user_entry->is_sub_map = FALSE;
2985 user_entry->is_pager = FALSE;
2986 user_entry->is_copy = FALSE;
2987 user_entry->internal = FALSE;
2988 user_entry->size = 0;
2989 user_entry->offset = 0;
2990 user_entry->data_offset = 0;
2991 user_entry->protection = VM_PROT_NONE;
2992 user_entry->ref_count = 1;
2993
2994 ipc_kobject_set(user_handle, (ipc_kobject_t) user_entry,
2995 IKOT_NAMED_ENTRY);
2996
2997 *user_entry_p = user_entry;
2998 *user_handle_p = user_handle;
2999
3000 return KERN_SUCCESS;
3001 }
3002
3003 /*
3004 * mach_memory_object_memory_entry_64
3005 *
3006 * Create a named entry backed by the provided pager.
3007 *
3008 * JMM - we need to hold a reference on the pager -
3009 * and release it when the named entry is destroyed.
3010 */
3011 kern_return_t
3012 mach_memory_object_memory_entry_64(
3013 host_t host,
3014 boolean_t internal,
3015 vm_object_offset_t size,
3016 vm_prot_t permission,
3017 memory_object_t pager,
3018 ipc_port_t *entry_handle)
3019 {
3020 unsigned int access;
3021 vm_named_entry_t user_entry;
3022 ipc_port_t user_handle;
3023
3024 if (host == HOST_NULL)
3025 return(KERN_INVALID_HOST);
3026
3027 if (mach_memory_entry_allocate(&user_entry, &user_handle)
3028 != KERN_SUCCESS) {
3029 return KERN_FAILURE;
3030 }
3031
3032 user_entry->backing.pager = pager;
3033 user_entry->size = size;
3034 user_entry->offset = 0;
3035 user_entry->protection = permission & VM_PROT_ALL;
3036 access = GET_MAP_MEM(permission);
3037 SET_MAP_MEM(access, user_entry->protection);
3038 user_entry->internal = internal;
3039 user_entry->is_sub_map = FALSE;
3040 user_entry->is_pager = TRUE;
3041 assert(user_entry->ref_count == 1);
3042
3043 *entry_handle = user_handle;
3044 return KERN_SUCCESS;
3045 }
3046
3047 kern_return_t
3048 mach_memory_object_memory_entry(
3049 host_t host,
3050 boolean_t internal,
3051 vm_size_t size,
3052 vm_prot_t permission,
3053 memory_object_t pager,
3054 ipc_port_t *entry_handle)
3055 {
3056 return mach_memory_object_memory_entry_64( host, internal,
3057 (vm_object_offset_t)size, permission, pager, entry_handle);
3058 }
3059
3060
3061 kern_return_t
3062 mach_memory_entry_purgable_control(
3063 ipc_port_t entry_port,
3064 vm_purgable_t control,
3065 int *state)
3066 {
3067 kern_return_t kr;
3068 vm_named_entry_t mem_entry;
3069 vm_object_t object;
3070
3071 if (entry_port == IP_NULL ||
3072 ip_kotype(entry_port) != IKOT_NAMED_ENTRY) {
3073 return KERN_INVALID_ARGUMENT;
3074 }
3075 if (control != VM_PURGABLE_SET_STATE &&
3076 control != VM_PURGABLE_GET_STATE)
3077 return(KERN_INVALID_ARGUMENT);
3078
3079 if (control == VM_PURGABLE_SET_STATE &&
3080 (((*state & ~(VM_PURGABLE_ALL_MASKS)) != 0) ||
3081 ((*state & VM_PURGABLE_STATE_MASK) > VM_PURGABLE_STATE_MASK)))
3082 return(KERN_INVALID_ARGUMENT);
3083
3084 mem_entry = (vm_named_entry_t) entry_port->ip_kobject;
3085
3086 named_entry_lock(mem_entry);
3087
3088 if (mem_entry->is_sub_map ||
3089 mem_entry->is_pager ||
3090 mem_entry->is_copy) {
3091 named_entry_unlock(mem_entry);
3092 return KERN_INVALID_ARGUMENT;
3093 }
3094
3095 object = mem_entry->backing.object;
3096 if (object == VM_OBJECT_NULL) {
3097 named_entry_unlock(mem_entry);
3098 return KERN_INVALID_ARGUMENT;
3099 }
3100
3101 vm_object_lock(object);
3102
3103 /* check that named entry covers entire object ? */
3104 if (mem_entry->offset != 0 || object->vo_size != mem_entry->size) {
3105 vm_object_unlock(object);
3106 named_entry_unlock(mem_entry);
3107 return KERN_INVALID_ARGUMENT;
3108 }
3109
3110 named_entry_unlock(mem_entry);
3111
3112 kr = vm_object_purgable_control(object, control, state);
3113
3114 vm_object_unlock(object);
3115
3116 return kr;
3117 }
3118
3119 kern_return_t
3120 mach_memory_entry_get_page_counts(
3121 ipc_port_t entry_port,
3122 unsigned int *resident_page_count,
3123 unsigned int *dirty_page_count)
3124 {
3125 kern_return_t kr;
3126 vm_named_entry_t mem_entry;
3127 vm_object_t object;
3128 vm_object_offset_t offset;
3129 vm_object_size_t size;
3130
3131 if (entry_port == IP_NULL ||
3132 ip_kotype(entry_port) != IKOT_NAMED_ENTRY) {
3133 return KERN_INVALID_ARGUMENT;
3134 }
3135
3136 mem_entry = (vm_named_entry_t) entry_port->ip_kobject;
3137
3138 named_entry_lock(mem_entry);
3139
3140 if (mem_entry->is_sub_map ||
3141 mem_entry->is_pager ||
3142 mem_entry->is_copy) {
3143 named_entry_unlock(mem_entry);
3144 return KERN_INVALID_ARGUMENT;
3145 }
3146
3147 object = mem_entry->backing.object;
3148 if (object == VM_OBJECT_NULL) {
3149 named_entry_unlock(mem_entry);
3150 return KERN_INVALID_ARGUMENT;
3151 }
3152
3153 vm_object_lock(object);
3154
3155 offset = mem_entry->offset;
3156 size = mem_entry->size;
3157
3158 named_entry_unlock(mem_entry);
3159
3160 kr = vm_object_get_page_counts(object, offset, size, resident_page_count, dirty_page_count);
3161
3162 vm_object_unlock(object);
3163
3164 return kr;
3165 }
3166
3167 /*
3168 * mach_memory_entry_port_release:
3169 *
3170 * Release a send right on a named entry port. This is the correct
3171 * way to destroy a named entry. When the last right on the port is
3172 * released, ipc_kobject_destroy() will call mach_destroy_memory_entry().
3173 */
3174 void
3175 mach_memory_entry_port_release(
3176 ipc_port_t port)
3177 {
3178 assert(ip_kotype(port) == IKOT_NAMED_ENTRY);
3179 ipc_port_release_send(port);
3180 }
3181
3182 /*
3183 * mach_destroy_memory_entry:
3184 *
3185 * Drops a reference on a memory entry and destroys the memory entry if
3186 * there are no more references on it.
3187 * NOTE: This routine should not be called to destroy a memory entry from the
3188 * kernel, as it will not release the Mach port associated with the memory
3189 * entry. The proper way to destroy a memory entry in the kernel is to
3190 * call mach_memort_entry_port_release() to release the kernel's send-right on
3191 * the memory entry's port. When the last send right is released, the memory
3192 * entry will be destroyed via ipc_kobject_destroy().
3193 */
3194 void
3195 mach_destroy_memory_entry(
3196 ipc_port_t port)
3197 {
3198 vm_named_entry_t named_entry;
3199 #if MACH_ASSERT
3200 assert(ip_kotype(port) == IKOT_NAMED_ENTRY);
3201 #endif /* MACH_ASSERT */
3202 named_entry = (vm_named_entry_t)port->ip_kobject;
3203
3204 named_entry_lock(named_entry);
3205 named_entry->ref_count -= 1;
3206
3207 if(named_entry->ref_count == 0) {
3208 if (named_entry->is_sub_map) {
3209 vm_map_deallocate(named_entry->backing.map);
3210 } else if (named_entry->is_pager) {
3211 /* JMM - need to drop reference on pager in that case */
3212 } else if (named_entry->is_copy) {
3213 vm_map_copy_discard(named_entry->backing.copy);
3214 } else {
3215 /* release the VM object we've been pointing to */
3216 vm_object_deallocate(named_entry->backing.object);
3217 }
3218
3219 named_entry_unlock(named_entry);
3220 named_entry_lock_destroy(named_entry);
3221
3222 kfree((void *) port->ip_kobject,
3223 sizeof (struct vm_named_entry));
3224 } else
3225 named_entry_unlock(named_entry);
3226 }
3227
3228 /* Allow manipulation of individual page state. This is actually part of */
3229 /* the UPL regimen but takes place on the memory entry rather than on a UPL */
3230
3231 kern_return_t
3232 mach_memory_entry_page_op(
3233 ipc_port_t entry_port,
3234 vm_object_offset_t offset,
3235 int ops,
3236 ppnum_t *phys_entry,
3237 int *flags)
3238 {
3239 vm_named_entry_t mem_entry;
3240 vm_object_t object;
3241 kern_return_t kr;
3242
3243 if (entry_port == IP_NULL ||
3244 ip_kotype(entry_port) != IKOT_NAMED_ENTRY) {
3245 return KERN_INVALID_ARGUMENT;
3246 }
3247
3248 mem_entry = (vm_named_entry_t) entry_port->ip_kobject;
3249
3250 named_entry_lock(mem_entry);
3251
3252 if (mem_entry->is_sub_map ||
3253 mem_entry->is_pager ||
3254 mem_entry->is_copy) {
3255 named_entry_unlock(mem_entry);
3256 return KERN_INVALID_ARGUMENT;
3257 }
3258
3259 object = mem_entry->backing.object;
3260 if (object == VM_OBJECT_NULL) {
3261 named_entry_unlock(mem_entry);
3262 return KERN_INVALID_ARGUMENT;
3263 }
3264
3265 vm_object_reference(object);
3266 named_entry_unlock(mem_entry);
3267
3268 kr = vm_object_page_op(object, offset, ops, phys_entry, flags);
3269
3270 vm_object_deallocate(object);
3271
3272 return kr;
3273 }
3274
3275 /*
3276 * mach_memory_entry_range_op offers performance enhancement over
3277 * mach_memory_entry_page_op for page_op functions which do not require page
3278 * level state to be returned from the call. Page_op was created to provide
3279 * a low-cost alternative to page manipulation via UPLs when only a single
3280 * page was involved. The range_op call establishes the ability in the _op
3281 * family of functions to work on multiple pages where the lack of page level
3282 * state handling allows the caller to avoid the overhead of the upl structures.
3283 */
3284
3285 kern_return_t
3286 mach_memory_entry_range_op(
3287 ipc_port_t entry_port,
3288 vm_object_offset_t offset_beg,
3289 vm_object_offset_t offset_end,
3290 int ops,
3291 int *range)
3292 {
3293 vm_named_entry_t mem_entry;
3294 vm_object_t object;
3295 kern_return_t kr;
3296
3297 if (entry_port == IP_NULL ||
3298 ip_kotype(entry_port) != IKOT_NAMED_ENTRY) {
3299 return KERN_INVALID_ARGUMENT;
3300 }
3301
3302 mem_entry = (vm_named_entry_t) entry_port->ip_kobject;
3303
3304 named_entry_lock(mem_entry);
3305
3306 if (mem_entry->is_sub_map ||
3307 mem_entry->is_pager ||
3308 mem_entry->is_copy) {
3309 named_entry_unlock(mem_entry);
3310 return KERN_INVALID_ARGUMENT;
3311 }
3312
3313 object = mem_entry->backing.object;
3314 if (object == VM_OBJECT_NULL) {
3315 named_entry_unlock(mem_entry);
3316 return KERN_INVALID_ARGUMENT;
3317 }
3318
3319 vm_object_reference(object);
3320 named_entry_unlock(mem_entry);
3321
3322 kr = vm_object_range_op(object,
3323 offset_beg,
3324 offset_end,
3325 ops,
3326 (uint32_t *) range);
3327
3328 vm_object_deallocate(object);
3329
3330 return kr;
3331 }
3332
3333 static void dp_control_port_init(void)
3334 {
3335 lck_grp_init(&dynamic_pager_control_port_lock_group,"dp_control_port", LCK_GRP_ATTR_NULL);
3336 lck_mtx_init(&dynamic_pager_control_port_lock, &dynamic_pager_control_port_lock_group, LCK_ATTR_NULL);
3337 }
3338
3339 kern_return_t
3340 set_dp_control_port(
3341 host_priv_t host_priv,
3342 ipc_port_t control_port)
3343 {
3344 ipc_port_t old_port;
3345
3346 if (host_priv == HOST_PRIV_NULL)
3347 return (KERN_INVALID_HOST);
3348
3349 lck_mtx_lock(&dynamic_pager_control_port_lock);
3350 old_port = dynamic_pager_control_port;
3351 dynamic_pager_control_port = control_port;
3352 lck_mtx_unlock(&dynamic_pager_control_port_lock);
3353
3354 if (IP_VALID(old_port))
3355 ipc_port_release_send(old_port);
3356
3357 return KERN_SUCCESS;
3358 }
3359
3360 kern_return_t
3361 get_dp_control_port(
3362 host_priv_t host_priv,
3363 ipc_port_t *control_port)
3364 {
3365 if (host_priv == HOST_PRIV_NULL)
3366 return (KERN_INVALID_HOST);
3367
3368 lck_mtx_lock(&dynamic_pager_control_port_lock);
3369 *control_port = ipc_port_copy_send(dynamic_pager_control_port);
3370 lck_mtx_unlock(&dynamic_pager_control_port_lock);
3371
3372 return KERN_SUCCESS;
3373
3374 }
3375
3376 /* ******* Temporary Internal calls to UPL for BSD ***** */
3377
3378 extern int kernel_upl_map(
3379 vm_map_t map,
3380 upl_t upl,
3381 vm_offset_t *dst_addr);
3382
3383 extern int kernel_upl_unmap(
3384 vm_map_t map,
3385 upl_t upl);
3386
3387 extern int kernel_upl_commit(
3388 upl_t upl,
3389 upl_page_info_t *pl,
3390 mach_msg_type_number_t count);
3391
3392 extern int kernel_upl_commit_range(
3393 upl_t upl,
3394 upl_offset_t offset,
3395 upl_size_t size,
3396 int flags,
3397 upl_page_info_array_t pl,
3398 mach_msg_type_number_t count);
3399
3400 extern int kernel_upl_abort(
3401 upl_t upl,
3402 int abort_type);
3403
3404 extern int kernel_upl_abort_range(
3405 upl_t upl,
3406 upl_offset_t offset,
3407 upl_size_t size,
3408 int abort_flags);
3409
3410
3411 kern_return_t
3412 kernel_upl_map(
3413 vm_map_t map,
3414 upl_t upl,
3415 vm_offset_t *dst_addr)
3416 {
3417 return vm_upl_map(map, upl, dst_addr);
3418 }
3419
3420
3421 kern_return_t
3422 kernel_upl_unmap(
3423 vm_map_t map,
3424 upl_t upl)
3425 {
3426 return vm_upl_unmap(map, upl);
3427 }
3428
3429 kern_return_t
3430 kernel_upl_commit(
3431 upl_t upl,
3432 upl_page_info_t *pl,
3433 mach_msg_type_number_t count)
3434 {
3435 kern_return_t kr;
3436
3437 kr = upl_commit(upl, pl, count);
3438 upl_deallocate(upl);
3439 return kr;
3440 }
3441
3442
3443 kern_return_t
3444 kernel_upl_commit_range(
3445 upl_t upl,
3446 upl_offset_t offset,
3447 upl_size_t size,
3448 int flags,
3449 upl_page_info_array_t pl,
3450 mach_msg_type_number_t count)
3451 {
3452 boolean_t finished = FALSE;
3453 kern_return_t kr;
3454
3455 if (flags & UPL_COMMIT_FREE_ON_EMPTY)
3456 flags |= UPL_COMMIT_NOTIFY_EMPTY;
3457
3458 if (flags & UPL_COMMIT_KERNEL_ONLY_FLAGS) {
3459 return KERN_INVALID_ARGUMENT;
3460 }
3461
3462 kr = upl_commit_range(upl, offset, size, flags, pl, count, &finished);
3463
3464 if ((flags & UPL_COMMIT_NOTIFY_EMPTY) && finished)
3465 upl_deallocate(upl);
3466
3467 return kr;
3468 }
3469
3470 kern_return_t
3471 kernel_upl_abort_range(
3472 upl_t upl,
3473 upl_offset_t offset,
3474 upl_size_t size,
3475 int abort_flags)
3476 {
3477 kern_return_t kr;
3478 boolean_t finished = FALSE;
3479
3480 if (abort_flags & UPL_COMMIT_FREE_ON_EMPTY)
3481 abort_flags |= UPL_COMMIT_NOTIFY_EMPTY;
3482
3483 kr = upl_abort_range(upl, offset, size, abort_flags, &finished);
3484
3485 if ((abort_flags & UPL_COMMIT_FREE_ON_EMPTY) && finished)
3486 upl_deallocate(upl);
3487
3488 return kr;
3489 }
3490
3491 kern_return_t
3492 kernel_upl_abort(
3493 upl_t upl,
3494 int abort_type)
3495 {
3496 kern_return_t kr;
3497
3498 kr = upl_abort(upl, abort_type);
3499 upl_deallocate(upl);
3500 return kr;
3501 }
3502
3503 /*
3504 * Now a kernel-private interface (for BootCache
3505 * use only). Need a cleaner way to create an
3506 * empty vm_map() and return a handle to it.
3507 */
3508
3509 kern_return_t
3510 vm_region_object_create(
3511 __unused vm_map_t target_map,
3512 vm_size_t size,
3513 ipc_port_t *object_handle)
3514 {
3515 vm_named_entry_t user_entry;
3516 ipc_port_t user_handle;
3517
3518 vm_map_t new_map;
3519
3520 if (mach_memory_entry_allocate(&user_entry, &user_handle)
3521 != KERN_SUCCESS) {
3522 return KERN_FAILURE;
3523 }
3524
3525 /* Create a named object based on a submap of specified size */
3526
3527 new_map = vm_map_create(PMAP_NULL, VM_MAP_MIN_ADDRESS,
3528 vm_map_round_page(size,
3529 VM_MAP_PAGE_MASK(target_map)),
3530 TRUE);
3531 vm_map_set_page_shift(new_map, VM_MAP_PAGE_SHIFT(target_map));
3532
3533 user_entry->backing.map = new_map;
3534 user_entry->internal = TRUE;
3535 user_entry->is_sub_map = TRUE;
3536 user_entry->offset = 0;
3537 user_entry->protection = VM_PROT_ALL;
3538 user_entry->size = size;
3539 assert(user_entry->ref_count == 1);
3540
3541 *object_handle = user_handle;
3542 return KERN_SUCCESS;
3543
3544 }
3545
3546 ppnum_t vm_map_get_phys_page( /* forward */
3547 vm_map_t map,
3548 vm_offset_t offset);
3549
3550 ppnum_t
3551 vm_map_get_phys_page(
3552 vm_map_t map,
3553 vm_offset_t addr)
3554 {
3555 vm_object_offset_t offset;
3556 vm_object_t object;
3557 vm_map_offset_t map_offset;
3558 vm_map_entry_t entry;
3559 ppnum_t phys_page = 0;
3560
3561 map_offset = vm_map_trunc_page(addr, PAGE_MASK);
3562
3563 vm_map_lock(map);
3564 while (vm_map_lookup_entry(map, map_offset, &entry)) {
3565
3566 if (VME_OBJECT(entry) == VM_OBJECT_NULL) {
3567 vm_map_unlock(map);
3568 return (ppnum_t) 0;
3569 }
3570 if (entry->is_sub_map) {
3571 vm_map_t old_map;
3572 vm_map_lock(VME_SUBMAP(entry));
3573 old_map = map;
3574 map = VME_SUBMAP(entry);
3575 map_offset = (VME_OFFSET(entry) +
3576 (map_offset - entry->vme_start));
3577 vm_map_unlock(old_map);
3578 continue;
3579 }
3580 if (VME_OBJECT(entry)->phys_contiguous) {
3581 /* These are not standard pageable memory mappings */
3582 /* If they are not present in the object they will */
3583 /* have to be picked up from the pager through the */
3584 /* fault mechanism. */
3585 if (VME_OBJECT(entry)->vo_shadow_offset == 0) {
3586 /* need to call vm_fault */
3587 vm_map_unlock(map);
3588 vm_fault(map, map_offset, VM_PROT_NONE,
3589 FALSE, THREAD_UNINT, NULL, 0);
3590 vm_map_lock(map);
3591 continue;
3592 }
3593 offset = (VME_OFFSET(entry) +
3594 (map_offset - entry->vme_start));
3595 phys_page = (ppnum_t)
3596 ((VME_OBJECT(entry)->vo_shadow_offset
3597 + offset) >> PAGE_SHIFT);
3598 break;
3599
3600 }
3601 offset = (VME_OFFSET(entry) + (map_offset - entry->vme_start));
3602 object = VME_OBJECT(entry);
3603 vm_object_lock(object);
3604 while (TRUE) {
3605 vm_page_t dst_page = vm_page_lookup(object,offset);
3606 if(dst_page == VM_PAGE_NULL) {
3607 if(object->shadow) {
3608 vm_object_t old_object;
3609 vm_object_lock(object->shadow);
3610 old_object = object;
3611 offset = offset + object->vo_shadow_offset;
3612 object = object->shadow;
3613 vm_object_unlock(old_object);
3614 } else {
3615 vm_object_unlock(object);
3616 break;
3617 }
3618 } else {
3619 phys_page = (ppnum_t)(VM_PAGE_GET_PHYS_PAGE(dst_page));
3620 vm_object_unlock(object);
3621 break;
3622 }
3623 }
3624 break;
3625
3626 }
3627
3628 vm_map_unlock(map);
3629 return phys_page;
3630 }
3631
3632 void
3633 vm_user_init(void)
3634 {
3635 dp_control_port_init();
3636 }
3637
3638 #if 0
3639 kern_return_t kernel_object_iopl_request( /* forward */
3640 vm_named_entry_t named_entry,
3641 memory_object_offset_t offset,
3642 upl_size_t *upl_size,
3643 upl_t *upl_ptr,
3644 upl_page_info_array_t user_page_list,
3645 unsigned int *page_list_count,
3646 int *flags);
3647
3648 kern_return_t
3649 kernel_object_iopl_request(
3650 vm_named_entry_t named_entry,
3651 memory_object_offset_t offset,
3652 upl_size_t *upl_size,
3653 upl_t *upl_ptr,
3654 upl_page_info_array_t user_page_list,
3655 unsigned int *page_list_count,
3656 int *flags)
3657 {
3658 vm_object_t object;
3659 kern_return_t ret;
3660
3661 int caller_flags;
3662
3663 caller_flags = *flags;
3664
3665 if (caller_flags & ~UPL_VALID_FLAGS) {
3666 /*
3667 * For forward compatibility's sake,
3668 * reject any unknown flag.
3669 */
3670 return KERN_INVALID_VALUE;
3671 }
3672
3673 /* a few checks to make sure user is obeying rules */
3674 if(*upl_size == 0) {
3675 if(offset >= named_entry->size)
3676 return(KERN_INVALID_RIGHT);
3677 *upl_size = (upl_size_t) (named_entry->size - offset);
3678 if (*upl_size != named_entry->size - offset)
3679 return KERN_INVALID_ARGUMENT;
3680 }
3681 if(caller_flags & UPL_COPYOUT_FROM) {
3682 if((named_entry->protection & VM_PROT_READ)
3683 != VM_PROT_READ) {
3684 return(KERN_INVALID_RIGHT);
3685 }
3686 } else {
3687 if((named_entry->protection &
3688 (VM_PROT_READ | VM_PROT_WRITE))
3689 != (VM_PROT_READ | VM_PROT_WRITE)) {
3690 return(KERN_INVALID_RIGHT);
3691 }
3692 }
3693 if(named_entry->size < (offset + *upl_size))
3694 return(KERN_INVALID_ARGUMENT);
3695
3696 /* the callers parameter offset is defined to be the */
3697 /* offset from beginning of named entry offset in object */
3698 offset = offset + named_entry->offset;
3699
3700 if (named_entry->is_sub_map ||
3701 named_entry->is_copy)
3702 return KERN_INVALID_ARGUMENT;
3703
3704 named_entry_lock(named_entry);
3705
3706 if (named_entry->is_pager) {
3707 object = vm_object_enter(named_entry->backing.pager,
3708 named_entry->offset + named_entry->size,
3709 named_entry->internal,
3710 FALSE,
3711 FALSE);
3712 if (object == VM_OBJECT_NULL) {
3713 named_entry_unlock(named_entry);
3714 return(KERN_INVALID_OBJECT);
3715 }
3716
3717 /* JMM - drop reference on the pager here? */
3718
3719 /* create an extra reference for the object */
3720 vm_object_lock(object);
3721 vm_object_reference_locked(object);
3722 named_entry->backing.object = object;
3723 named_entry->is_pager = FALSE;
3724 named_entry_unlock(named_entry);
3725
3726 /* wait for object (if any) to be ready */
3727 if (!named_entry->internal) {
3728 while (!object->pager_ready) {
3729 vm_object_wait(object,
3730 VM_OBJECT_EVENT_PAGER_READY,
3731 THREAD_UNINT);
3732 vm_object_lock(object);
3733 }
3734 }
3735 vm_object_unlock(object);
3736
3737 } else {
3738 /* This is the case where we are going to operate */
3739 /* an an already known object. If the object is */
3740 /* not ready it is internal. An external */
3741 /* object cannot be mapped until it is ready */
3742 /* we can therefore avoid the ready check */
3743 /* in this case. */
3744 object = named_entry->backing.object;
3745 vm_object_reference(object);
3746 named_entry_unlock(named_entry);
3747 }
3748
3749 if (!object->private) {
3750 if (*upl_size > MAX_UPL_TRANSFER_BYTES)
3751 *upl_size = MAX_UPL_TRANSFER_BYTES;
3752 if (object->phys_contiguous) {
3753 *flags = UPL_PHYS_CONTIG;
3754 } else {
3755 *flags = 0;
3756 }
3757 } else {
3758 *flags = UPL_DEV_MEMORY | UPL_PHYS_CONTIG;
3759 }
3760
3761 ret = vm_object_iopl_request(object,
3762 offset,
3763 *upl_size,
3764 upl_ptr,
3765 user_page_list,
3766 page_list_count,
3767 (upl_control_flags_t)(unsigned int)caller_flags);
3768 vm_object_deallocate(object);
3769 return ret;
3770 }
3771 #endif