2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
34 * All Rights Reserved.
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.
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.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
60 * Author: Avadis Tevanian, Jr., Michael Wayne Young
62 * User-exported virtual memory functions.
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
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
84 * New VM call implementations should be added here and to mach_vm.defs
85 * (subsystem 4800), and use mach_vm_* "wide" types.
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 */
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>
103 #include <mach/host_priv_server.h>
104 #include <mach/mach_vm_server.h>
105 #include <mach/memory_entry_server.h>
106 #include <mach/vm_map_server.h>
108 #include <kern/host.h>
109 #include <kern/kalloc.h>
110 #include <kern/task.h>
111 #include <kern/misc_protos.h>
112 #include <vm/vm_fault.h>
113 #include <vm/vm_map.h>
114 #include <vm/vm_object.h>
115 #include <vm/vm_page.h>
116 #include <vm/memory_object.h>
117 #include <vm/vm_pageout.h>
118 #include <vm/vm_protos.h>
119 #include <vm/vm_purgeable_internal.h>
120 #include <vm/vm_init.h>
122 #include <san/kasan.h>
124 #include <libkern/OSDebug.h>
126 vm_size_t upl_offset_to_pagelist
= 0;
133 * mach_vm_allocate allocates "zero fill" memory in the specfied
137 mach_vm_allocate_external(
139 mach_vm_offset_t
*addr
,
145 VM_GET_FLAGS_ALIAS(flags
, tag
);
146 return mach_vm_allocate_kernel(map
, addr
, size
, flags
, tag
);
150 mach_vm_allocate_kernel(
152 mach_vm_offset_t
*addr
,
157 vm_map_offset_t map_addr
;
158 vm_map_size_t map_size
;
159 kern_return_t result
;
162 /* filter out any kernel-only flags */
163 if (flags
& ~VM_FLAGS_USER_ALLOCATE
) {
164 return KERN_INVALID_ARGUMENT
;
167 if (map
== VM_MAP_NULL
) {
168 return KERN_INVALID_ARGUMENT
;
175 anywhere
= ((VM_FLAGS_ANYWHERE
& flags
) != 0);
178 * No specific address requested, so start candidate address
179 * search at the minimum address in the map. However, if that
180 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
181 * allocations of PAGEZERO to explicit requests since its
182 * normal use is to catch dereferences of NULL and many
183 * applications also treat pointers with a value of 0 as
184 * special and suddenly having address 0 contain useable
185 * memory would tend to confuse those applications.
187 map_addr
= vm_map_min(map
);
189 map_addr
+= VM_MAP_PAGE_SIZE(map
);
192 map_addr
= vm_map_trunc_page(*addr
,
193 VM_MAP_PAGE_MASK(map
));
195 map_size
= vm_map_round_page(size
,
196 VM_MAP_PAGE_MASK(map
));
198 return KERN_INVALID_ARGUMENT
;
201 result
= vm_map_enter(
207 VM_MAP_KERNEL_FLAGS_NONE
,
210 (vm_object_offset_t
)0,
222 * Legacy routine that allocates "zero fill" memory in the specfied
223 * map (which is limited to the same size as the kernel).
226 vm_allocate_external(
234 VM_GET_FLAGS_ALIAS(flags
, tag
);
235 return vm_allocate_kernel(map
, addr
, size
, flags
, tag
);
246 vm_map_offset_t map_addr
;
247 vm_map_size_t map_size
;
248 kern_return_t result
;
251 /* filter out any kernel-only flags */
252 if (flags
& ~VM_FLAGS_USER_ALLOCATE
) {
253 return KERN_INVALID_ARGUMENT
;
256 if (map
== VM_MAP_NULL
) {
257 return KERN_INVALID_ARGUMENT
;
264 anywhere
= ((VM_FLAGS_ANYWHERE
& flags
) != 0);
267 * No specific address requested, so start candidate address
268 * search at the minimum address in the map. However, if that
269 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
270 * allocations of PAGEZERO to explicit requests since its
271 * normal use is to catch dereferences of NULL and many
272 * applications also treat pointers with a value of 0 as
273 * special and suddenly having address 0 contain useable
274 * memory would tend to confuse those applications.
276 map_addr
= vm_map_min(map
);
278 map_addr
+= VM_MAP_PAGE_SIZE(map
);
281 map_addr
= vm_map_trunc_page(*addr
,
282 VM_MAP_PAGE_MASK(map
));
284 map_size
= vm_map_round_page(size
,
285 VM_MAP_PAGE_MASK(map
));
287 return KERN_INVALID_ARGUMENT
;
290 result
= vm_map_enter(
296 VM_MAP_KERNEL_FLAGS_NONE
,
299 (vm_object_offset_t
)0,
306 if (result
== KERN_SUCCESS
&& map
->pmap
== kernel_pmap
) {
307 kasan_notify_address(map_addr
, map_size
);
311 *addr
= CAST_DOWN(vm_offset_t
, map_addr
);
316 * mach_vm_deallocate -
317 * deallocates the specified range of addresses in the
318 * specified address map.
323 mach_vm_offset_t start
,
326 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
)) {
327 return KERN_INVALID_ARGUMENT
;
330 if (size
== (mach_vm_offset_t
) 0) {
334 return vm_map_remove(map
,
335 vm_map_trunc_page(start
,
336 VM_MAP_PAGE_MASK(map
)),
337 vm_map_round_page(start
+ size
,
338 VM_MAP_PAGE_MASK(map
)),
339 VM_MAP_REMOVE_NO_FLAGS
);
344 * deallocates the specified range of addresses in the
345 * specified address map (limited to addresses the same
346 * size as the kernel).
354 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
)) {
355 return KERN_INVALID_ARGUMENT
;
358 if (size
== (vm_offset_t
) 0) {
362 return vm_map_remove(map
,
363 vm_map_trunc_page(start
,
364 VM_MAP_PAGE_MASK(map
)),
365 vm_map_round_page(start
+ size
,
366 VM_MAP_PAGE_MASK(map
)),
367 VM_MAP_REMOVE_NO_FLAGS
);
372 * Sets the inheritance of the specified range in the
378 mach_vm_offset_t start
,
380 vm_inherit_t new_inheritance
)
382 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
383 (new_inheritance
> VM_INHERIT_LAST_VALID
)) {
384 return KERN_INVALID_ARGUMENT
;
391 return vm_map_inherit(map
,
392 vm_map_trunc_page(start
,
393 VM_MAP_PAGE_MASK(map
)),
394 vm_map_round_page(start
+ size
,
395 VM_MAP_PAGE_MASK(map
)),
401 * Sets the inheritance of the specified range in the
402 * specified map (range limited to addresses
409 vm_inherit_t new_inheritance
)
411 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
412 (new_inheritance
> VM_INHERIT_LAST_VALID
)) {
413 return KERN_INVALID_ARGUMENT
;
420 return vm_map_inherit(map
,
421 vm_map_trunc_page(start
,
422 VM_MAP_PAGE_MASK(map
)),
423 vm_map_round_page(start
+ size
,
424 VM_MAP_PAGE_MASK(map
)),
430 * Sets the protection of the specified range in the
437 mach_vm_offset_t start
,
439 boolean_t set_maximum
,
440 vm_prot_t new_protection
)
442 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
443 (new_protection
& ~(VM_PROT_ALL
| VM_PROT_COPY
))) {
444 return KERN_INVALID_ARGUMENT
;
451 return vm_map_protect(map
,
452 vm_map_trunc_page(start
,
453 VM_MAP_PAGE_MASK(map
)),
454 vm_map_round_page(start
+ size
,
455 VM_MAP_PAGE_MASK(map
)),
462 * Sets the protection of the specified range in the
463 * specified map. Addressability of the range limited
464 * to the same size as the kernel.
472 boolean_t set_maximum
,
473 vm_prot_t new_protection
)
475 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
476 (new_protection
& ~(VM_PROT_ALL
| VM_PROT_COPY
))) {
477 return KERN_INVALID_ARGUMENT
;
484 return vm_map_protect(map
,
485 vm_map_trunc_page(start
,
486 VM_MAP_PAGE_MASK(map
)),
487 vm_map_round_page(start
+ size
,
488 VM_MAP_PAGE_MASK(map
)),
494 * mach_vm_machine_attributes -
495 * Handle machine-specific attributes for a mapping, such
496 * as cachability, migrability, etc.
499 mach_vm_machine_attribute(
501 mach_vm_address_t addr
,
503 vm_machine_attribute_t attribute
,
504 vm_machine_attribute_val_t
* value
) /* IN/OUT */
506 if ((map
== VM_MAP_NULL
) || (addr
+ size
< addr
)) {
507 return KERN_INVALID_ARGUMENT
;
514 return vm_map_machine_attribute(
516 vm_map_trunc_page(addr
,
517 VM_MAP_PAGE_MASK(map
)),
518 vm_map_round_page(addr
+ size
,
519 VM_MAP_PAGE_MASK(map
)),
525 * vm_machine_attribute -
526 * Handle machine-specific attributes for a mapping, such
527 * as cachability, migrability, etc. Limited addressability
528 * (same range limits as for the native kernel map).
531 vm_machine_attribute(
535 vm_machine_attribute_t attribute
,
536 vm_machine_attribute_val_t
* value
) /* IN/OUT */
538 if ((map
== VM_MAP_NULL
) || (addr
+ size
< addr
)) {
539 return KERN_INVALID_ARGUMENT
;
546 return vm_map_machine_attribute(
548 vm_map_trunc_page(addr
,
549 VM_MAP_PAGE_MASK(map
)),
550 vm_map_round_page(addr
+ size
,
551 VM_MAP_PAGE_MASK(map
)),
558 * Read/copy a range from one address space and return it to the caller.
560 * It is assumed that the address for the returned memory is selected by
561 * the IPC implementation as part of receiving the reply to this call.
562 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
563 * that gets returned.
565 * JMM - because of mach_msg_type_number_t, this call is limited to a
566 * single 4GB region at this time.
572 mach_vm_address_t addr
,
575 mach_msg_type_number_t
*data_size
)
578 vm_map_copy_t ipc_address
;
580 if (map
== VM_MAP_NULL
) {
581 return KERN_INVALID_ARGUMENT
;
584 if ((mach_msg_type_number_t
) size
!= size
) {
585 return KERN_INVALID_ARGUMENT
;
588 error
= vm_map_copyin(map
,
589 (vm_map_address_t
)addr
,
591 FALSE
, /* src_destroy */
594 if (KERN_SUCCESS
== error
) {
595 *data
= (pointer_t
) ipc_address
;
596 *data_size
= (mach_msg_type_number_t
) size
;
597 assert(*data_size
== size
);
604 * Read/copy a range from one address space and return it to the caller.
605 * Limited addressability (same range limits as for the native kernel map).
607 * It is assumed that the address for the returned memory is selected by
608 * the IPC implementation as part of receiving the reply to this call.
609 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
610 * that gets returned.
618 mach_msg_type_number_t
*data_size
)
621 vm_map_copy_t ipc_address
;
623 if (map
== VM_MAP_NULL
) {
624 return KERN_INVALID_ARGUMENT
;
627 mach_msg_type_number_t dsize
;
628 if (os_convert_overflow(size
, &dsize
)) {
630 * The kernel could handle a 64-bit "size" value, but
631 * it could not return the size of the data in "*data_size"
632 * without overflowing.
633 * Let's reject this "size" as invalid.
635 return KERN_INVALID_ARGUMENT
;
638 error
= vm_map_copyin(map
,
639 (vm_map_address_t
)addr
,
641 FALSE
, /* src_destroy */
644 if (KERN_SUCCESS
== error
) {
645 *data
= (pointer_t
) ipc_address
;
647 assert(*data_size
== size
);
653 * mach_vm_read_list -
654 * Read/copy a list of address ranges from specified map.
656 * MIG does not know how to deal with a returned array of
657 * vm_map_copy_t structures, so we have to do the copyout
663 mach_vm_read_entry_t data_list
,
666 mach_msg_type_number_t i
;
670 if (map
== VM_MAP_NULL
||
671 count
> VM_MAP_ENTRY_MAX
) {
672 return KERN_INVALID_ARGUMENT
;
675 error
= KERN_SUCCESS
;
676 for (i
= 0; i
< count
; i
++) {
677 vm_map_address_t map_addr
;
678 vm_map_size_t map_size
;
680 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
681 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
684 error
= vm_map_copyin(map
,
687 FALSE
, /* src_destroy */
689 if (KERN_SUCCESS
== error
) {
690 error
= vm_map_copyout(
694 if (KERN_SUCCESS
== error
) {
695 data_list
[i
].address
= map_addr
;
698 vm_map_copy_discard(copy
);
701 data_list
[i
].address
= (mach_vm_address_t
)0;
702 data_list
[i
].size
= (mach_vm_size_t
)0;
709 * Read/copy a list of address ranges from specified map.
711 * MIG does not know how to deal with a returned array of
712 * vm_map_copy_t structures, so we have to do the copyout
715 * The source and destination ranges are limited to those
716 * that can be described with a vm_address_t (i.e. same
717 * size map as the kernel).
719 * JMM - If the result of the copyout is an address range
720 * that cannot be described with a vm_address_t (i.e. the
721 * caller had a larger address space but used this call
722 * anyway), it will result in a truncated address being
723 * returned (and a likely confused caller).
729 vm_read_entry_t data_list
,
732 mach_msg_type_number_t i
;
736 if (map
== VM_MAP_NULL
||
737 count
> VM_MAP_ENTRY_MAX
) {
738 return KERN_INVALID_ARGUMENT
;
741 error
= KERN_SUCCESS
;
742 for (i
= 0; i
< count
; i
++) {
743 vm_map_address_t map_addr
;
744 vm_map_size_t map_size
;
746 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
747 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
750 error
= vm_map_copyin(map
,
753 FALSE
, /* src_destroy */
755 if (KERN_SUCCESS
== error
) {
756 error
= vm_map_copyout(current_task()->map
,
759 if (KERN_SUCCESS
== error
) {
760 data_list
[i
].address
=
761 CAST_DOWN(vm_offset_t
, map_addr
);
764 vm_map_copy_discard(copy
);
767 data_list
[i
].address
= (mach_vm_address_t
)0;
768 data_list
[i
].size
= (mach_vm_size_t
)0;
774 * mach_vm_read_overwrite -
775 * Overwrite a range of the current map with data from the specified
778 * In making an assumption that the current thread is local, it is
779 * no longer cluster-safe without a fully supportive local proxy
780 * thread/task (but we don't support cluster's anymore so this is moot).
784 mach_vm_read_overwrite(
786 mach_vm_address_t address
,
788 mach_vm_address_t data
,
789 mach_vm_size_t
*data_size
)
794 if (map
== VM_MAP_NULL
) {
795 return KERN_INVALID_ARGUMENT
;
798 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
799 (vm_map_size_t
)size
, FALSE
, ©
);
801 if (KERN_SUCCESS
== error
) {
802 error
= vm_map_copy_overwrite(current_thread()->map
,
803 (vm_map_address_t
)data
,
805 if (KERN_SUCCESS
== error
) {
809 vm_map_copy_discard(copy
);
815 * vm_read_overwrite -
816 * Overwrite a range of the current map with data from the specified
819 * This routine adds the additional limitation that the source and
820 * destination ranges must be describable with vm_address_t values
821 * (i.e. the same size address spaces as the kernel, or at least the
822 * the ranges are in that first portion of the respective address
829 vm_address_t address
,
832 vm_size_t
*data_size
)
837 if (map
== VM_MAP_NULL
) {
838 return KERN_INVALID_ARGUMENT
;
841 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
842 (vm_map_size_t
)size
, FALSE
, ©
);
844 if (KERN_SUCCESS
== error
) {
845 error
= vm_map_copy_overwrite(current_thread()->map
,
846 (vm_map_address_t
)data
,
848 if (KERN_SUCCESS
== error
) {
852 vm_map_copy_discard(copy
);
860 * Overwrite the specified address range with the data provided
861 * (from the current map).
866 mach_vm_address_t address
,
868 __unused mach_msg_type_number_t size
)
870 if (map
== VM_MAP_NULL
) {
871 return KERN_INVALID_ARGUMENT
;
874 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
875 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
880 * Overwrite the specified address range with the data provided
881 * (from the current map).
883 * The addressability of the range of addresses to overwrite is
884 * limited bu the use of a vm_address_t (same size as kernel map).
885 * Either the target map is also small, or the range is in the
886 * low addresses within it.
891 vm_address_t address
,
893 __unused mach_msg_type_number_t size
)
895 if (map
== VM_MAP_NULL
) {
896 return KERN_INVALID_ARGUMENT
;
899 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
900 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
905 * Overwrite one range of the specified map with the contents of
906 * another range within that same map (i.e. both address ranges
912 mach_vm_address_t source_address
,
914 mach_vm_address_t dest_address
)
919 if (map
== VM_MAP_NULL
) {
920 return KERN_INVALID_ARGUMENT
;
923 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
924 (vm_map_size_t
)size
, FALSE
, ©
);
926 if (KERN_SUCCESS
== kr
) {
927 kr
= vm_map_copy_overwrite(map
,
928 (vm_map_address_t
)dest_address
,
929 copy
, FALSE
/* interruptible XXX */);
931 if (KERN_SUCCESS
!= kr
) {
932 vm_map_copy_discard(copy
);
941 vm_address_t source_address
,
943 vm_address_t dest_address
)
948 if (map
== VM_MAP_NULL
) {
949 return KERN_INVALID_ARGUMENT
;
952 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
953 (vm_map_size_t
)size
, FALSE
, ©
);
955 if (KERN_SUCCESS
== kr
) {
956 kr
= vm_map_copy_overwrite(map
,
957 (vm_map_address_t
)dest_address
,
958 copy
, FALSE
/* interruptible XXX */);
960 if (KERN_SUCCESS
!= kr
) {
961 vm_map_copy_discard(copy
);
969 * Map some range of an object into an address space.
971 * The object can be one of several types of objects:
972 * NULL - anonymous memory
973 * a named entry - a range within another address space
974 * or a range within a memory object
975 * a whole memory object
979 mach_vm_map_external(
981 mach_vm_offset_t
*address
,
982 mach_vm_size_t initial_size
,
983 mach_vm_offset_t mask
,
986 vm_object_offset_t offset
,
988 vm_prot_t cur_protection
,
989 vm_prot_t max_protection
,
990 vm_inherit_t inheritance
)
994 VM_GET_FLAGS_ALIAS(flags
, tag
);
995 return mach_vm_map_kernel(target_map
, address
, initial_size
, mask
,
996 flags
, VM_MAP_KERNEL_FLAGS_NONE
, tag
,
998 cur_protection
, max_protection
,
1004 vm_map_t target_map
,
1005 mach_vm_offset_t
*address
,
1006 mach_vm_size_t initial_size
,
1007 mach_vm_offset_t mask
,
1009 vm_map_kernel_flags_t vmk_flags
,
1012 vm_object_offset_t offset
,
1014 vm_prot_t cur_protection
,
1015 vm_prot_t max_protection
,
1016 vm_inherit_t inheritance
)
1019 vm_map_offset_t vmmaddr
;
1021 vmmaddr
= (vm_map_offset_t
) *address
;
1023 /* filter out any kernel-only flags */
1024 if (flags
& ~VM_FLAGS_USER_MAP
) {
1025 return KERN_INVALID_ARGUMENT
;
1028 kr
= vm_map_enter_mem_object(target_map
,
1043 if (kr
== KERN_SUCCESS
&& target_map
->pmap
== kernel_pmap
) {
1044 kasan_notify_address(vmmaddr
, initial_size
);
1053 /* legacy interface */
1056 vm_map_t target_map
,
1057 vm_offset_t
*address
,
1062 vm_object_offset_t offset
,
1064 vm_prot_t cur_protection
,
1065 vm_prot_t max_protection
,
1066 vm_inherit_t inheritance
)
1070 VM_GET_FLAGS_ALIAS(flags
, tag
);
1071 return vm_map_64_kernel(target_map
, address
, size
, mask
,
1072 flags
, VM_MAP_KERNEL_FLAGS_NONE
,
1073 tag
, port
, offset
, copy
,
1074 cur_protection
, max_protection
,
1080 vm_map_t target_map
,
1081 vm_offset_t
*address
,
1085 vm_map_kernel_flags_t vmk_flags
,
1088 vm_object_offset_t offset
,
1090 vm_prot_t cur_protection
,
1091 vm_prot_t max_protection
,
1092 vm_inherit_t inheritance
)
1094 mach_vm_address_t map_addr
;
1095 mach_vm_size_t map_size
;
1096 mach_vm_offset_t map_mask
;
1099 map_addr
= (mach_vm_address_t
)*address
;
1100 map_size
= (mach_vm_size_t
)size
;
1101 map_mask
= (mach_vm_offset_t
)mask
;
1103 kr
= mach_vm_map_kernel(target_map
, &map_addr
, map_size
, map_mask
,
1104 flags
, vmk_flags
, tag
,
1106 cur_protection
, max_protection
, inheritance
);
1107 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1111 /* temporary, until world build */
1114 vm_map_t target_map
,
1115 vm_offset_t
*address
,
1122 vm_prot_t cur_protection
,
1123 vm_prot_t max_protection
,
1124 vm_inherit_t inheritance
)
1128 VM_GET_FLAGS_ALIAS(flags
, tag
);
1129 return vm_map_kernel(target_map
, address
, size
, mask
,
1130 flags
, VM_MAP_KERNEL_FLAGS_NONE
, tag
,
1132 cur_protection
, max_protection
, inheritance
);
1137 vm_map_t target_map
,
1138 vm_offset_t
*address
,
1142 vm_map_kernel_flags_t vmk_flags
,
1147 vm_prot_t cur_protection
,
1148 vm_prot_t max_protection
,
1149 vm_inherit_t inheritance
)
1151 mach_vm_address_t map_addr
;
1152 mach_vm_size_t map_size
;
1153 mach_vm_offset_t map_mask
;
1154 vm_object_offset_t obj_offset
;
1157 map_addr
= (mach_vm_address_t
)*address
;
1158 map_size
= (mach_vm_size_t
)size
;
1159 map_mask
= (mach_vm_offset_t
)mask
;
1160 obj_offset
= (vm_object_offset_t
)offset
;
1162 kr
= mach_vm_map_kernel(target_map
, &map_addr
, map_size
, map_mask
,
1163 flags
, vmk_flags
, tag
,
1164 port
, obj_offset
, copy
,
1165 cur_protection
, max_protection
, inheritance
);
1166 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1172 * Remap a range of memory from one task into another,
1173 * to another address range within the same task, or
1174 * over top of itself (with altered permissions and/or
1175 * as an in-place copy of itself).
1178 mach_vm_remap_external(
1179 vm_map_t target_map
,
1180 mach_vm_offset_t
*address
,
1181 mach_vm_size_t size
,
1182 mach_vm_offset_t mask
,
1185 mach_vm_offset_t memory_address
,
1187 vm_prot_t
*cur_protection
,
1188 vm_prot_t
*max_protection
,
1189 vm_inherit_t inheritance
)
1192 VM_GET_FLAGS_ALIAS(flags
, tag
);
1194 return mach_vm_remap_kernel(target_map
, address
, size
, mask
, flags
, tag
, src_map
, memory_address
,
1195 copy
, cur_protection
, max_protection
, inheritance
);
1199 mach_vm_remap_kernel(
1200 vm_map_t target_map
,
1201 mach_vm_offset_t
*address
,
1202 mach_vm_size_t size
,
1203 mach_vm_offset_t mask
,
1207 mach_vm_offset_t memory_address
,
1209 vm_prot_t
*cur_protection
,
1210 vm_prot_t
*max_protection
,
1211 vm_inherit_t inheritance
)
1213 vm_map_offset_t map_addr
;
1216 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
) {
1217 return KERN_INVALID_ARGUMENT
;
1220 /* filter out any kernel-only flags */
1221 if (flags
& ~VM_FLAGS_USER_REMAP
) {
1222 return KERN_INVALID_ARGUMENT
;
1225 map_addr
= (vm_map_offset_t
)*address
;
1227 kr
= vm_map_remap(target_map
,
1232 VM_MAP_KERNEL_FLAGS_NONE
,
1240 *address
= map_addr
;
1246 * Remap a range of memory from one task into another,
1247 * to another address range within the same task, or
1248 * over top of itself (with altered permissions and/or
1249 * as an in-place copy of itself).
1251 * The addressability of the source and target address
1252 * range is limited by the size of vm_address_t (in the
1257 vm_map_t target_map
,
1258 vm_offset_t
*address
,
1263 vm_offset_t memory_address
,
1265 vm_prot_t
*cur_protection
,
1266 vm_prot_t
*max_protection
,
1267 vm_inherit_t inheritance
)
1270 VM_GET_FLAGS_ALIAS(flags
, tag
);
1272 return vm_remap_kernel(target_map
, address
, size
, mask
, flags
, tag
, src_map
,
1273 memory_address
, copy
, cur_protection
, max_protection
, inheritance
);
1278 vm_map_t target_map
,
1279 vm_offset_t
*address
,
1285 vm_offset_t memory_address
,
1287 vm_prot_t
*cur_protection
,
1288 vm_prot_t
*max_protection
,
1289 vm_inherit_t inheritance
)
1291 vm_map_offset_t map_addr
;
1294 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
) {
1295 return KERN_INVALID_ARGUMENT
;
1298 /* filter out any kernel-only flags */
1299 if (flags
& ~VM_FLAGS_USER_REMAP
) {
1300 return KERN_INVALID_ARGUMENT
;
1303 map_addr
= (vm_map_offset_t
)*address
;
1305 kr
= vm_map_remap(target_map
,
1310 VM_MAP_KERNEL_FLAGS_NONE
,
1318 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1323 * NOTE: these routine (and this file) will no longer require mach_host_server.h
1324 * when mach_vm_wire and vm_wire are changed to use ledgers.
1326 #include <mach/mach_host_server.h>
1329 * Specify that the range of the virtual address space
1330 * of the target task must not cause page faults for
1331 * the indicated accesses.
1333 * [ To unwire the pages, specify VM_PROT_NONE. ]
1336 mach_vm_wire_external(
1337 host_priv_t host_priv
,
1339 mach_vm_offset_t start
,
1340 mach_vm_size_t size
,
1343 return mach_vm_wire_kernel(host_priv
, map
, start
, size
, access
, VM_KERN_MEMORY_MLOCK
);
1347 mach_vm_wire_kernel(
1348 host_priv_t host_priv
,
1350 mach_vm_offset_t start
,
1351 mach_vm_size_t size
,
1357 if (host_priv
== HOST_PRIV_NULL
) {
1358 return KERN_INVALID_HOST
;
1361 assert(host_priv
== &realhost
);
1363 if (map
== VM_MAP_NULL
) {
1364 return KERN_INVALID_TASK
;
1367 if (access
& ~VM_PROT_ALL
|| (start
+ size
< start
)) {
1368 return KERN_INVALID_ARGUMENT
;
1371 if (access
!= VM_PROT_NONE
) {
1372 rc
= vm_map_wire_kernel(map
,
1373 vm_map_trunc_page(start
,
1374 VM_MAP_PAGE_MASK(map
)),
1375 vm_map_round_page(start
+ size
,
1376 VM_MAP_PAGE_MASK(map
)),
1380 rc
= vm_map_unwire(map
,
1381 vm_map_trunc_page(start
,
1382 VM_MAP_PAGE_MASK(map
)),
1383 vm_map_round_page(start
+ size
,
1384 VM_MAP_PAGE_MASK(map
)),
1392 * Specify that the range of the virtual address space
1393 * of the target task must not cause page faults for
1394 * the indicated accesses.
1396 * [ To unwire the pages, specify VM_PROT_NONE. ]
1400 host_priv_t host_priv
,
1408 if (host_priv
== HOST_PRIV_NULL
) {
1409 return KERN_INVALID_HOST
;
1412 assert(host_priv
== &realhost
);
1414 if (map
== VM_MAP_NULL
) {
1415 return KERN_INVALID_TASK
;
1418 if ((access
& ~VM_PROT_ALL
) || (start
+ size
< start
)) {
1419 return KERN_INVALID_ARGUMENT
;
1424 } else if (access
!= VM_PROT_NONE
) {
1425 rc
= vm_map_wire_kernel(map
,
1426 vm_map_trunc_page(start
,
1427 VM_MAP_PAGE_MASK(map
)),
1428 vm_map_round_page(start
+ size
,
1429 VM_MAP_PAGE_MASK(map
)),
1430 access
, VM_KERN_MEMORY_OSFMK
,
1433 rc
= vm_map_unwire(map
,
1434 vm_map_trunc_page(start
,
1435 VM_MAP_PAGE_MASK(map
)),
1436 vm_map_round_page(start
+ size
,
1437 VM_MAP_PAGE_MASK(map
)),
1446 * Synchronises the memory range specified with its backing store
1447 * image by either flushing or cleaning the contents to the appropriate
1450 * interpretation of sync_flags
1451 * VM_SYNC_INVALIDATE - discard pages, only return precious
1454 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1455 * - discard pages, write dirty or precious
1456 * pages back to memory manager.
1458 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1459 * - write dirty or precious pages back to
1460 * the memory manager.
1462 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1463 * is a hole in the region, and we would
1464 * have returned KERN_SUCCESS, return
1465 * KERN_INVALID_ADDRESS instead.
1468 * KERN_INVALID_TASK Bad task parameter
1469 * KERN_INVALID_ARGUMENT both sync and async were specified.
1470 * KERN_SUCCESS The usual.
1471 * KERN_INVALID_ADDRESS There was a hole in the region.
1477 mach_vm_address_t address
,
1478 mach_vm_size_t size
,
1479 vm_sync_t sync_flags
)
1481 if (map
== VM_MAP_NULL
) {
1482 return KERN_INVALID_TASK
;
1485 return vm_map_msync(map
, (vm_map_address_t
)address
,
1486 (vm_map_size_t
)size
, sync_flags
);
1492 * Synchronises the memory range specified with its backing store
1493 * image by either flushing or cleaning the contents to the appropriate
1496 * interpretation of sync_flags
1497 * VM_SYNC_INVALIDATE - discard pages, only return precious
1500 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1501 * - discard pages, write dirty or precious
1502 * pages back to memory manager.
1504 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1505 * - write dirty or precious pages back to
1506 * the memory manager.
1508 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1509 * is a hole in the region, and we would
1510 * have returned KERN_SUCCESS, return
1511 * KERN_INVALID_ADDRESS instead.
1513 * The addressability of the range is limited to that which can
1514 * be described by a vm_address_t.
1517 * KERN_INVALID_TASK Bad task parameter
1518 * KERN_INVALID_ARGUMENT both sync and async were specified.
1519 * KERN_SUCCESS The usual.
1520 * KERN_INVALID_ADDRESS There was a hole in the region.
1526 vm_address_t address
,
1528 vm_sync_t sync_flags
)
1530 if (map
== VM_MAP_NULL
) {
1531 return KERN_INVALID_TASK
;
1534 return vm_map_msync(map
, (vm_map_address_t
)address
,
1535 (vm_map_size_t
)size
, sync_flags
);
1540 vm_toggle_entry_reuse(int toggle
, int *old_value
)
1542 vm_map_t map
= current_map();
1544 assert(!map
->is_nested_map
);
1545 if (toggle
== VM_TOGGLE_GETVALUE
&& old_value
!= NULL
) {
1546 *old_value
= map
->disable_vmentry_reuse
;
1547 } else if (toggle
== VM_TOGGLE_SET
) {
1548 vm_map_entry_t map_to_entry
;
1551 vm_map_disable_hole_optimization(map
);
1552 map
->disable_vmentry_reuse
= TRUE
;
1553 __IGNORE_WCASTALIGN(map_to_entry
= vm_map_to_entry(map
));
1554 if (map
->first_free
== map_to_entry
) {
1555 map
->highest_entry_end
= vm_map_min(map
);
1557 map
->highest_entry_end
= map
->first_free
->vme_end
;
1560 } else if (toggle
== VM_TOGGLE_CLEAR
) {
1562 map
->disable_vmentry_reuse
= FALSE
;
1565 return KERN_INVALID_ARGUMENT
;
1568 return KERN_SUCCESS
;
1572 * mach_vm_behavior_set
1574 * Sets the paging behavior attribute for the specified range
1575 * in the specified map.
1577 * This routine will fail with KERN_INVALID_ADDRESS if any address
1578 * in [start,start+size) is not a valid allocated memory region.
1581 mach_vm_behavior_set(
1583 mach_vm_offset_t start
,
1584 mach_vm_size_t size
,
1585 vm_behavior_t new_behavior
)
1587 vm_map_offset_t align_mask
;
1589 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
)) {
1590 return KERN_INVALID_ARGUMENT
;
1594 return KERN_SUCCESS
;
1597 switch (new_behavior
) {
1598 case VM_BEHAVIOR_REUSABLE
:
1599 case VM_BEHAVIOR_REUSE
:
1600 case VM_BEHAVIOR_CAN_REUSE
:
1602 * Align to the hardware page size, to allow
1603 * malloc() to maximize the amount of re-usability,
1604 * even on systems with larger software page size.
1606 align_mask
= PAGE_MASK
;
1609 align_mask
= VM_MAP_PAGE_MASK(map
);
1613 return vm_map_behavior_set(map
,
1614 vm_map_trunc_page(start
, align_mask
),
1615 vm_map_round_page(start
+ size
, align_mask
),
1622 * Sets the paging behavior attribute for the specified range
1623 * in the specified map.
1625 * This routine will fail with KERN_INVALID_ADDRESS if any address
1626 * in [start,start+size) is not a valid allocated memory region.
1628 * This routine is potentially limited in addressibility by the
1629 * use of vm_offset_t (if the map provided is larger than the
1637 vm_behavior_t new_behavior
)
1639 if (start
+ size
< start
) {
1640 return KERN_INVALID_ARGUMENT
;
1643 return mach_vm_behavior_set(map
,
1644 (mach_vm_offset_t
) start
,
1645 (mach_vm_size_t
) size
,
1652 * User call to obtain information about a region in
1653 * a task's address map. Currently, only one flavor is
1656 * XXX The reserved and behavior fields cannot be filled
1657 * in until the vm merge from the IK is completed, and
1658 * vm_reserve is implemented.
1660 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1666 mach_vm_offset_t
*address
, /* IN/OUT */
1667 mach_vm_size_t
*size
, /* OUT */
1668 vm_region_flavor_t flavor
, /* IN */
1669 vm_region_info_t info
, /* OUT */
1670 mach_msg_type_number_t
*count
, /* IN/OUT */
1671 mach_port_t
*object_name
) /* OUT */
1673 vm_map_offset_t map_addr
;
1674 vm_map_size_t map_size
;
1677 if (VM_MAP_NULL
== map
) {
1678 return KERN_INVALID_ARGUMENT
;
1681 map_addr
= (vm_map_offset_t
)*address
;
1682 map_size
= (vm_map_size_t
)*size
;
1684 /* legacy conversion */
1685 if (VM_REGION_BASIC_INFO
== flavor
) {
1686 flavor
= VM_REGION_BASIC_INFO_64
;
1689 kr
= vm_map_region(map
,
1690 &map_addr
, &map_size
,
1691 flavor
, info
, count
,
1694 *address
= map_addr
;
1700 * vm_region_64 and vm_region:
1702 * User call to obtain information about a region in
1703 * a task's address map. Currently, only one flavor is
1706 * XXX The reserved and behavior fields cannot be filled
1707 * in until the vm merge from the IK is completed, and
1708 * vm_reserve is implemented.
1710 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1716 vm_offset_t
*address
, /* IN/OUT */
1717 vm_size_t
*size
, /* OUT */
1718 vm_region_flavor_t flavor
, /* IN */
1719 vm_region_info_t info
, /* OUT */
1720 mach_msg_type_number_t
*count
, /* IN/OUT */
1721 mach_port_t
*object_name
) /* OUT */
1723 vm_map_offset_t map_addr
;
1724 vm_map_size_t map_size
;
1727 if (VM_MAP_NULL
== map
) {
1728 return KERN_INVALID_ARGUMENT
;
1731 map_addr
= (vm_map_offset_t
)*address
;
1732 map_size
= (vm_map_size_t
)*size
;
1734 /* legacy conversion */
1735 if (VM_REGION_BASIC_INFO
== flavor
) {
1736 flavor
= VM_REGION_BASIC_INFO_64
;
1739 kr
= vm_map_region(map
,
1740 &map_addr
, &map_size
,
1741 flavor
, info
, count
,
1744 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1745 *size
= CAST_DOWN(vm_size_t
, map_size
);
1747 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
) {
1748 return KERN_INVALID_ADDRESS
;
1756 vm_address_t
*address
, /* IN/OUT */
1757 vm_size_t
*size
, /* OUT */
1758 vm_region_flavor_t flavor
, /* IN */
1759 vm_region_info_t info
, /* OUT */
1760 mach_msg_type_number_t
*count
, /* IN/OUT */
1761 mach_port_t
*object_name
) /* OUT */
1763 vm_map_address_t map_addr
;
1764 vm_map_size_t map_size
;
1767 if (VM_MAP_NULL
== map
) {
1768 return KERN_INVALID_ARGUMENT
;
1771 map_addr
= (vm_map_address_t
)*address
;
1772 map_size
= (vm_map_size_t
)*size
;
1774 kr
= vm_map_region(map
,
1775 &map_addr
, &map_size
,
1776 flavor
, info
, count
,
1779 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1780 *size
= CAST_DOWN(vm_size_t
, map_size
);
1782 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
) {
1783 return KERN_INVALID_ADDRESS
;
1789 * vm_region_recurse: A form of vm_region which follows the
1790 * submaps in a target map
1794 mach_vm_region_recurse(
1796 mach_vm_address_t
*address
,
1797 mach_vm_size_t
*size
,
1799 vm_region_recurse_info_t info
,
1800 mach_msg_type_number_t
*infoCnt
)
1802 vm_map_address_t map_addr
;
1803 vm_map_size_t map_size
;
1806 if (VM_MAP_NULL
== map
) {
1807 return KERN_INVALID_ARGUMENT
;
1810 map_addr
= (vm_map_address_t
)*address
;
1811 map_size
= (vm_map_size_t
)*size
;
1813 kr
= vm_map_region_recurse_64(
1818 (vm_region_submap_info_64_t
)info
,
1821 *address
= map_addr
;
1827 * vm_region_recurse: A form of vm_region which follows the
1828 * submaps in a target map
1832 vm_region_recurse_64(
1834 vm_address_t
*address
,
1837 vm_region_recurse_info_64_t info
,
1838 mach_msg_type_number_t
*infoCnt
)
1840 vm_map_address_t map_addr
;
1841 vm_map_size_t map_size
;
1844 if (VM_MAP_NULL
== map
) {
1845 return KERN_INVALID_ARGUMENT
;
1848 map_addr
= (vm_map_address_t
)*address
;
1849 map_size
= (vm_map_size_t
)*size
;
1851 kr
= vm_map_region_recurse_64(
1856 (vm_region_submap_info_64_t
)info
,
1859 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1860 *size
= CAST_DOWN(vm_size_t
, map_size
);
1862 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
) {
1863 return KERN_INVALID_ADDRESS
;
1871 vm_offset_t
*address
, /* IN/OUT */
1872 vm_size_t
*size
, /* OUT */
1873 natural_t
*depth
, /* IN/OUT */
1874 vm_region_recurse_info_t info32
, /* IN/OUT */
1875 mach_msg_type_number_t
*infoCnt
) /* IN/OUT */
1877 vm_region_submap_info_data_64_t info64
;
1878 vm_region_submap_info_t info
;
1879 vm_map_address_t map_addr
;
1880 vm_map_size_t map_size
;
1883 if (VM_MAP_NULL
== map
|| *infoCnt
< VM_REGION_SUBMAP_INFO_COUNT
) {
1884 return KERN_INVALID_ARGUMENT
;
1888 map_addr
= (vm_map_address_t
)*address
;
1889 map_size
= (vm_map_size_t
)*size
;
1890 info
= (vm_region_submap_info_t
)info32
;
1891 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT_64
;
1893 kr
= vm_map_region_recurse_64(map
, &map_addr
, &map_size
,
1894 depth
, &info64
, infoCnt
);
1896 info
->protection
= info64
.protection
;
1897 info
->max_protection
= info64
.max_protection
;
1898 info
->inheritance
= info64
.inheritance
;
1899 info
->offset
= (uint32_t)info64
.offset
; /* trouble-maker */
1900 info
->user_tag
= info64
.user_tag
;
1901 info
->pages_resident
= info64
.pages_resident
;
1902 info
->pages_shared_now_private
= info64
.pages_shared_now_private
;
1903 info
->pages_swapped_out
= info64
.pages_swapped_out
;
1904 info
->pages_dirtied
= info64
.pages_dirtied
;
1905 info
->ref_count
= info64
.ref_count
;
1906 info
->shadow_depth
= info64
.shadow_depth
;
1907 info
->external_pager
= info64
.external_pager
;
1908 info
->share_mode
= info64
.share_mode
;
1909 info
->is_submap
= info64
.is_submap
;
1910 info
->behavior
= info64
.behavior
;
1911 info
->object_id
= info64
.object_id
;
1912 info
->user_wired_count
= info64
.user_wired_count
;
1914 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1915 *size
= CAST_DOWN(vm_size_t
, map_size
);
1916 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT
;
1918 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
) {
1919 return KERN_INVALID_ADDRESS
;
1925 mach_vm_purgable_control(
1927 mach_vm_offset_t address
,
1928 vm_purgable_t control
,
1931 if (VM_MAP_NULL
== map
) {
1932 return KERN_INVALID_ARGUMENT
;
1935 if (control
== VM_PURGABLE_SET_STATE_FROM_KERNEL
) {
1936 /* not allowed from user-space */
1937 return KERN_INVALID_ARGUMENT
;
1940 return vm_map_purgable_control(map
,
1941 vm_map_trunc_page(address
, PAGE_MASK
),
1947 vm_purgable_control(
1949 vm_offset_t address
,
1950 vm_purgable_t control
,
1953 if (VM_MAP_NULL
== map
) {
1954 return KERN_INVALID_ARGUMENT
;
1957 if (control
== VM_PURGABLE_SET_STATE_FROM_KERNEL
) {
1958 /* not allowed from user-space */
1959 return KERN_INVALID_ARGUMENT
;
1962 return vm_map_purgable_control(map
,
1963 vm_map_trunc_page(address
, PAGE_MASK
),
1970 * Ordinarily, the right to allocate CPM is restricted
1971 * to privileged applications (those that can gain access
1972 * to the host priv port). Set this variable to zero if
1973 * you want to let any application allocate CPM.
1975 unsigned int vm_allocate_cpm_privileged
= 0;
1978 * Allocate memory in the specified map, with the caveat that
1979 * the memory is physically contiguous. This call may fail
1980 * if the system can't find sufficient contiguous memory.
1981 * This call may cause or lead to heart-stopping amounts of
1984 * Memory obtained from this call should be freed in the
1985 * normal way, viz., via vm_deallocate.
1989 host_priv_t host_priv
,
1995 vm_map_address_t map_addr
;
1996 vm_map_size_t map_size
;
1999 if (vm_allocate_cpm_privileged
&& HOST_PRIV_NULL
== host_priv
) {
2000 return KERN_INVALID_HOST
;
2003 if (VM_MAP_NULL
== map
) {
2004 return KERN_INVALID_ARGUMENT
;
2007 map_addr
= (vm_map_address_t
)*addr
;
2008 map_size
= (vm_map_size_t
)size
;
2010 kr
= vm_map_enter_cpm(map
,
2015 *addr
= CAST_DOWN(vm_address_t
, map_addr
);
2023 mach_vm_offset_t offset
,
2027 if (VM_MAP_NULL
== map
) {
2028 return KERN_INVALID_ARGUMENT
;
2031 return vm_map_page_query_internal(
2033 vm_map_trunc_page(offset
, PAGE_MASK
),
2034 disposition
, ref_count
);
2044 if (VM_MAP_NULL
== map
) {
2045 return KERN_INVALID_ARGUMENT
;
2048 return vm_map_page_query_internal(
2050 vm_map_trunc_page(offset
, PAGE_MASK
),
2051 disposition
, ref_count
);
2055 mach_vm_page_range_query(
2057 mach_vm_offset_t address
,
2058 mach_vm_size_t size
,
2059 mach_vm_address_t dispositions_addr
,
2060 mach_vm_size_t
*dispositions_count
)
2062 kern_return_t kr
= KERN_SUCCESS
;
2063 int num_pages
= 0, i
= 0;
2064 mach_vm_size_t curr_sz
= 0, copy_sz
= 0;
2065 mach_vm_size_t disp_buf_req_size
= 0, disp_buf_total_size
= 0;
2066 mach_msg_type_number_t count
= 0;
2069 void *local_disp
= NULL
;;
2070 vm_map_size_t info_size
= 0, local_disp_size
= 0;
2071 mach_vm_offset_t start
= 0, end
= 0;
2073 if (map
== VM_MAP_NULL
|| dispositions_count
== NULL
) {
2074 return KERN_INVALID_ARGUMENT
;
2077 disp_buf_req_size
= (*dispositions_count
* sizeof(int));
2078 start
= mach_vm_trunc_page(address
);
2079 end
= mach_vm_round_page(address
+ size
);
2082 return KERN_INVALID_ARGUMENT
;
2085 if ((end
- start
) < size
) {
2087 * Aligned size is less than unaligned size.
2089 return KERN_INVALID_ARGUMENT
;
2092 if (disp_buf_req_size
== 0 || (end
== start
)) {
2093 return KERN_SUCCESS
;
2097 * For large requests, we will go through them
2098 * MAX_PAGE_RANGE_QUERY chunk at a time.
2101 curr_sz
= MIN(end
- start
, MAX_PAGE_RANGE_QUERY
);
2102 num_pages
= (int) (curr_sz
>> PAGE_SHIFT
);
2104 info_size
= num_pages
* sizeof(vm_page_info_basic_data_t
);
2105 info
= kalloc(info_size
);
2108 return KERN_RESOURCE_SHORTAGE
;
2111 local_disp_size
= num_pages
* sizeof(int);
2112 local_disp
= kalloc(local_disp_size
);
2114 if (local_disp
== NULL
) {
2115 kfree(info
, info_size
);
2117 return KERN_RESOURCE_SHORTAGE
;
2121 count
= VM_PAGE_INFO_BASIC_COUNT
;
2122 kr
= vm_map_page_range_info_internal(
2125 mach_vm_round_page(start
+ curr_sz
),
2127 (vm_page_info_t
) info
,
2130 assert(kr
== KERN_SUCCESS
);
2132 for (i
= 0; i
< num_pages
; i
++) {
2133 ((int*)local_disp
)[i
] = ((vm_page_info_basic_t
)info
)[i
].disposition
;
2136 copy_sz
= MIN(disp_buf_req_size
, num_pages
* sizeof(int) /* an int per page */);
2137 kr
= copyout(local_disp
, (mach_vm_address_t
)dispositions_addr
, copy_sz
);
2140 disp_buf_req_size
-= copy_sz
;
2141 disp_buf_total_size
+= copy_sz
;
2147 if ((disp_buf_req_size
== 0) || (curr_sz
>= size
)) {
2149 * We might have inspected the full range OR
2150 * more than it esp. if the user passed in
2151 * non-page aligned start/size and/or if we
2152 * descended into a submap. We are done here.
2157 dispositions_addr
+= copy_sz
;
2161 curr_sz
= MIN(mach_vm_round_page(size
), MAX_PAGE_RANGE_QUERY
);
2162 num_pages
= (int)(curr_sz
>> PAGE_SHIFT
);
2166 *dispositions_count
= disp_buf_total_size
/ sizeof(int);
2168 kfree(local_disp
, local_disp_size
);
2171 kfree(info
, info_size
);
2180 mach_vm_address_t address
,
2181 vm_page_info_flavor_t flavor
,
2182 vm_page_info_t info
,
2183 mach_msg_type_number_t
*count
)
2187 if (map
== VM_MAP_NULL
) {
2188 return KERN_INVALID_ARGUMENT
;
2191 kr
= vm_map_page_info(map
, address
, flavor
, info
, count
);
2195 /* map a (whole) upl into an address space */
2200 vm_address_t
*dst_addr
)
2202 vm_map_offset_t map_addr
;
2205 if (VM_MAP_NULL
== map
) {
2206 return KERN_INVALID_ARGUMENT
;
2209 kr
= vm_map_enter_upl(map
, upl
, &map_addr
);
2210 *dst_addr
= CAST_DOWN(vm_address_t
, map_addr
);
2219 if (VM_MAP_NULL
== map
) {
2220 return KERN_INVALID_ARGUMENT
;
2223 return vm_map_remove_upl(map
, upl
);
2226 /* Retrieve a upl for an object underlying an address range in a map */
2231 vm_map_offset_t map_offset
,
2232 upl_size_t
*upl_size
,
2234 upl_page_info_array_t page_list
,
2235 unsigned int *count
,
2236 upl_control_flags_t
*flags
,
2238 int force_data_sync
)
2240 upl_control_flags_t map_flags
;
2243 if (VM_MAP_NULL
== map
) {
2244 return KERN_INVALID_ARGUMENT
;
2247 map_flags
= *flags
& ~UPL_NOZEROFILL
;
2248 if (force_data_sync
) {
2249 map_flags
|= UPL_FORCE_DATA_SYNC
;
2252 kr
= vm_map_create_upl(map
,
2261 *flags
= (map_flags
& ~UPL_FORCE_DATA_SYNC
);
2266 extern int proc_selfpid(void);
2267 extern char *proc_name_address(void *p
);
2268 int cs_executable_mem_entry
= 0;
2269 int log_executable_mem_entry
= 0;
2270 #endif /* CONFIG_EMBEDDED */
2273 * mach_make_memory_entry_64
2275 * Think of it as a two-stage vm_remap() operation. First
2276 * you get a handle. Second, you get map that handle in
2277 * somewhere else. Rather than doing it all at once (and
2278 * without needing access to the other whole map).
2281 mach_make_memory_entry_64(
2282 vm_map_t target_map
,
2283 memory_object_size_t
*size
,
2284 memory_object_offset_t offset
,
2285 vm_prot_t permission
,
2286 ipc_port_t
*object_handle
,
2287 ipc_port_t parent_handle
)
2289 if ((permission
& MAP_MEM_FLAGS_MASK
) & ~MAP_MEM_FLAGS_USER
) {
2291 * Unknown flag: reject for forward compatibility.
2293 return KERN_INVALID_VALUE
;
2296 return mach_make_memory_entry_internal(target_map
,
2305 mach_make_memory_entry_internal(
2306 vm_map_t target_map
,
2307 memory_object_size_t
*size
,
2308 memory_object_offset_t offset
,
2309 vm_prot_t permission
,
2310 ipc_port_t
*object_handle
,
2311 ipc_port_t parent_handle
)
2313 vm_map_version_t version
;
2314 vm_named_entry_t parent_entry
;
2315 vm_named_entry_t user_entry
;
2316 ipc_port_t user_handle
;
2320 /* needed for call to vm_map_lookup_locked */
2323 vm_object_offset_t obj_off
;
2325 struct vm_object_fault_info fault_info
= {};
2327 vm_object_t shadow_object
;
2329 /* needed for direct map entry manipulation */
2330 vm_map_entry_t map_entry
;
2331 vm_map_entry_t next_entry
;
2333 vm_map_t original_map
= target_map
;
2334 vm_map_size_t total_size
, map_size
;
2335 vm_map_offset_t map_start
, map_end
;
2336 vm_map_offset_t local_offset
;
2337 vm_object_size_t mappable_size
;
2340 * Stash the offset in the page for use by vm_map_enter_mem_object()
2341 * in the VM_FLAGS_RETURN_DATA_ADDR/MAP_MEM_USE_DATA_ADDR case.
2343 vm_object_offset_t offset_in_page
;
2345 unsigned int access
;
2346 vm_prot_t protections
;
2347 vm_prot_t original_protections
, mask_protections
;
2348 unsigned int wimg_mode
;
2350 boolean_t force_shadow
= FALSE
;
2351 boolean_t use_data_addr
;
2352 boolean_t use_4K_compat
;
2353 #if VM_NAMED_ENTRY_LIST
2355 #endif /* VM_NAMED_ENTRY_LIST */
2357 if ((permission
& MAP_MEM_FLAGS_MASK
) & ~MAP_MEM_FLAGS_ALL
) {
2359 * Unknown flag: reject for forward compatibility.
2361 return KERN_INVALID_VALUE
;
2364 if (IP_VALID(parent_handle
) &&
2365 ip_kotype(parent_handle
) == IKOT_NAMED_ENTRY
) {
2366 parent_entry
= (vm_named_entry_t
) parent_handle
->ip_kobject
;
2368 parent_entry
= NULL
;
2371 if (parent_entry
&& parent_entry
->is_copy
) {
2372 return KERN_INVALID_ARGUMENT
;
2375 original_protections
= permission
& VM_PROT_ALL
;
2376 protections
= original_protections
;
2377 mask_protections
= permission
& VM_PROT_IS_MASK
;
2378 access
= GET_MAP_MEM(permission
);
2379 use_data_addr
= ((permission
& MAP_MEM_USE_DATA_ADDR
) != 0);
2380 use_4K_compat
= ((permission
& MAP_MEM_4K_DATA_ADDR
) != 0);
2382 user_handle
= IP_NULL
;
2385 map_start
= vm_map_trunc_page(offset
, PAGE_MASK
);
2387 if (permission
& MAP_MEM_ONLY
) {
2388 boolean_t parent_is_object
;
2390 map_end
= vm_map_round_page(offset
+ *size
, PAGE_MASK
);
2391 map_size
= map_end
- map_start
;
2393 if (use_data_addr
|| use_4K_compat
|| parent_entry
== NULL
) {
2394 return KERN_INVALID_ARGUMENT
;
2397 parent_is_object
= !parent_entry
->is_sub_map
;
2398 object
= parent_entry
->backing
.object
;
2399 if (parent_is_object
&& object
!= VM_OBJECT_NULL
) {
2400 wimg_mode
= object
->wimg_bits
;
2402 wimg_mode
= VM_WIMG_USE_DEFAULT
;
2404 if ((access
!= GET_MAP_MEM(parent_entry
->protection
)) &&
2405 !(parent_entry
->protection
& VM_PROT_WRITE
)) {
2406 return KERN_INVALID_RIGHT
;
2408 vm_prot_to_wimg(access
, &wimg_mode
);
2409 if (access
!= MAP_MEM_NOOP
) {
2410 SET_MAP_MEM(access
, parent_entry
->protection
);
2412 if (parent_is_object
&& object
&&
2413 (access
!= MAP_MEM_NOOP
) &&
2414 (!(object
->nophyscache
))) {
2415 if (object
->wimg_bits
!= wimg_mode
) {
2416 vm_object_lock(object
);
2417 vm_object_change_wimg_mode(object
, wimg_mode
);
2418 vm_object_unlock(object
);
2421 if (object_handle
) {
2422 *object_handle
= IP_NULL
;
2424 return KERN_SUCCESS
;
2425 } else if (permission
& MAP_MEM_NAMED_CREATE
) {
2426 map_end
= vm_map_round_page(offset
+ *size
, PAGE_MASK
);
2427 map_size
= map_end
- map_start
;
2429 if (use_data_addr
|| use_4K_compat
) {
2430 return KERN_INVALID_ARGUMENT
;
2433 kr
= mach_memory_entry_allocate(&user_entry
, &user_handle
);
2434 if (kr
!= KERN_SUCCESS
) {
2435 return KERN_FAILURE
;
2439 * Force the creation of the VM object now.
2441 if (map_size
> (vm_map_size_t
) ANON_MAX_SIZE
) {
2443 * LP64todo - for now, we can only allocate 4GB-4096
2444 * internal objects because the default pager can't
2445 * page bigger ones. Remove this when it can.
2451 object
= vm_object_allocate(map_size
);
2452 assert(object
!= VM_OBJECT_NULL
);
2454 if (permission
& MAP_MEM_PURGABLE
) {
2457 if (!(permission
& VM_PROT_WRITE
)) {
2458 /* if we can't write, we can't purge */
2459 vm_object_deallocate(object
);
2460 kr
= KERN_INVALID_ARGUMENT
;
2463 object
->purgable
= VM_PURGABLE_NONVOLATILE
;
2464 if (permission
& MAP_MEM_PURGABLE_KERNEL_ONLY
) {
2465 object
->purgeable_only_by_kernel
= TRUE
;
2467 assert(object
->vo_owner
== NULL
);
2468 assert(object
->resident_page_count
== 0);
2469 assert(object
->wired_page_count
== 0);
2470 vm_object_lock(object
);
2471 owner
= current_task();
2473 if (owner
->task_legacy_footprint
) {
2475 * For ios11, we failed to account for
2476 * this memory. Keep doing that for
2477 * legacy apps (built before ios12),
2478 * for backwards compatibility's sake...
2480 owner
= kernel_task
;
2482 #endif /* __arm64__ */
2483 vm_purgeable_nonvolatile_enqueue(object
, owner
);
2484 vm_object_unlock(object
);
2487 if (permission
& MAP_MEM_LEDGER_TAG_NETWORK
) {
2488 /* make this object owned by the calling task */
2489 vm_object_lock(object
);
2490 vm_object_ownership_change(
2492 VM_OBJECT_LEDGER_TAG_NETWORK
,
2493 current_task(), /* new owner */
2494 FALSE
); /* task_objq locked? */
2495 vm_object_unlock(object
);
2498 #if CONFIG_SECLUDED_MEMORY
2499 if (secluded_for_iokit
&& /* global boot-arg */
2500 ((permission
& MAP_MEM_GRAB_SECLUDED
)
2502 /* XXX FBDP for my testing only */
2503 || (secluded_for_fbdp
&& map_size
== 97550336)
2507 if (!(permission
& MAP_MEM_GRAB_SECLUDED
) &&
2508 secluded_for_fbdp
) {
2509 printf("FBDP: object %p size %lld can grab secluded\n", object
, (uint64_t) map_size
);
2512 object
->can_grab_secluded
= TRUE
;
2513 assert(!object
->eligible_for_secluded
);
2515 #endif /* CONFIG_SECLUDED_MEMORY */
2518 * The VM object is brand new and nobody else knows about it,
2519 * so we don't need to lock it.
2522 wimg_mode
= object
->wimg_bits
;
2523 vm_prot_to_wimg(access
, &wimg_mode
);
2524 if (access
!= MAP_MEM_NOOP
) {
2525 object
->wimg_bits
= wimg_mode
;
2528 /* the object has no pages, so no WIMG bits to update here */
2532 * We use this path when we want to make sure that
2533 * nobody messes with the object (coalesce, for
2534 * example) before we map it.
2535 * We might want to use these objects for transposition via
2536 * vm_object_transpose() too, so we don't want any copy or
2537 * shadow objects either...
2539 object
->copy_strategy
= MEMORY_OBJECT_COPY_NONE
;
2540 object
->true_share
= TRUE
;
2542 user_entry
->backing
.object
= object
;
2543 user_entry
->internal
= TRUE
;
2544 user_entry
->is_sub_map
= FALSE
;
2545 user_entry
->offset
= 0;
2546 user_entry
->data_offset
= 0;
2547 user_entry
->protection
= protections
;
2548 SET_MAP_MEM(access
, user_entry
->protection
);
2549 user_entry
->size
= map_size
;
2551 /* user_object pager and internal fields are not used */
2552 /* when the object field is filled in. */
2554 *size
= CAST_DOWN(vm_size_t
, (user_entry
->size
-
2555 user_entry
->data_offset
));
2556 *object_handle
= user_handle
;
2557 return KERN_SUCCESS
;
2560 if (permission
& MAP_MEM_VM_COPY
) {
2563 if (target_map
== VM_MAP_NULL
) {
2564 return KERN_INVALID_TASK
;
2567 map_end
= vm_map_round_page(offset
+ *size
, PAGE_MASK
);
2568 map_size
= map_end
- map_start
;
2569 if (use_data_addr
|| use_4K_compat
) {
2570 offset_in_page
= offset
- map_start
;
2571 if (use_4K_compat
) {
2572 offset_in_page
&= ~((signed)(0xFFF));
2578 kr
= vm_map_copyin_internal(target_map
,
2581 VM_MAP_COPYIN_ENTRY_LIST
,
2583 if (kr
!= KERN_SUCCESS
) {
2587 kr
= mach_memory_entry_allocate(&user_entry
, &user_handle
);
2588 if (kr
!= KERN_SUCCESS
) {
2589 vm_map_copy_discard(copy
);
2590 return KERN_FAILURE
;
2593 user_entry
->backing
.copy
= copy
;
2594 user_entry
->internal
= FALSE
;
2595 user_entry
->is_sub_map
= FALSE
;
2596 user_entry
->is_copy
= TRUE
;
2597 user_entry
->offset
= 0;
2598 user_entry
->protection
= protections
;
2599 user_entry
->size
= map_size
;
2600 user_entry
->data_offset
= offset_in_page
;
2602 *size
= CAST_DOWN(vm_size_t
, (user_entry
->size
-
2603 user_entry
->data_offset
));
2604 *object_handle
= user_handle
;
2605 return KERN_SUCCESS
;
2608 if (permission
& MAP_MEM_VM_SHARE
) {
2610 vm_prot_t cur_prot
, max_prot
;
2612 if (target_map
== VM_MAP_NULL
) {
2613 return KERN_INVALID_TASK
;
2616 map_end
= vm_map_round_page(offset
+ *size
, PAGE_MASK
);
2617 map_size
= map_end
- map_start
;
2618 if (use_data_addr
|| use_4K_compat
) {
2619 offset_in_page
= offset
- map_start
;
2620 if (use_4K_compat
) {
2621 offset_in_page
&= ~((signed)(0xFFF));
2627 cur_prot
= VM_PROT_ALL
;
2628 kr
= vm_map_copy_extract(target_map
,
2634 if (kr
!= KERN_SUCCESS
) {
2638 if (mask_protections
) {
2640 * We just want as much of "original_protections"
2641 * as we can get out of the actual "cur_prot".
2643 protections
&= cur_prot
;
2644 if (protections
== VM_PROT_NONE
) {
2645 /* no access at all: fail */
2646 vm_map_copy_discard(copy
);
2647 return KERN_PROTECTION_FAILURE
;
2651 * We want exactly "original_protections"
2652 * out of "cur_prot".
2654 if ((cur_prot
& protections
) != protections
) {
2655 vm_map_copy_discard(copy
);
2656 return KERN_PROTECTION_FAILURE
;
2660 kr
= mach_memory_entry_allocate(&user_entry
, &user_handle
);
2661 if (kr
!= KERN_SUCCESS
) {
2662 vm_map_copy_discard(copy
);
2663 return KERN_FAILURE
;
2666 user_entry
->backing
.copy
= copy
;
2667 user_entry
->internal
= FALSE
;
2668 user_entry
->is_sub_map
= FALSE
;
2669 user_entry
->is_copy
= TRUE
;
2670 user_entry
->offset
= 0;
2671 user_entry
->protection
= protections
;
2672 user_entry
->size
= map_size
;
2673 user_entry
->data_offset
= offset_in_page
;
2675 *size
= CAST_DOWN(vm_size_t
, (user_entry
->size
-
2676 user_entry
->data_offset
));
2677 *object_handle
= user_handle
;
2678 return KERN_SUCCESS
;
2681 if (parent_entry
== NULL
||
2682 (permission
& MAP_MEM_NAMED_REUSE
)) {
2683 map_end
= vm_map_round_page(offset
+ *size
, PAGE_MASK
);
2684 map_size
= map_end
- map_start
;
2685 if (use_data_addr
|| use_4K_compat
) {
2686 offset_in_page
= offset
- map_start
;
2687 if (use_4K_compat
) {
2688 offset_in_page
&= ~((signed)(0xFFF));
2694 /* Create a named object based on address range within the task map */
2695 /* Go find the object at given address */
2697 if (target_map
== VM_MAP_NULL
) {
2698 return KERN_INVALID_TASK
;
2702 protections
= original_protections
;
2703 vm_map_lock_read(target_map
);
2705 /* get the object associated with the target address */
2706 /* note we check the permission of the range against */
2707 /* that requested by the caller */
2709 kr
= vm_map_lookup_locked(&target_map
, map_start
,
2710 protections
| mask_protections
,
2711 OBJECT_LOCK_EXCLUSIVE
, &version
,
2712 &object
, &obj_off
, &prot
, &wired
,
2715 if (kr
!= KERN_SUCCESS
) {
2716 vm_map_unlock_read(target_map
);
2719 if (mask_protections
) {
2721 * The caller asked us to use the "protections" as
2722 * a mask, so restrict "protections" to what this
2723 * mapping actually allows.
2725 protections
&= prot
;
2729 * Wiring would copy the pages to a shadow object.
2730 * The shadow object would not be code-signed so
2731 * attempting to execute code from these copied pages
2732 * would trigger a code-signing violation.
2734 if (prot
& VM_PROT_EXECUTE
) {
2735 if (log_executable_mem_entry
) {
2737 bsd_info
= current_task()->bsd_info
;
2738 printf("pid %d[%s] making memory entry out of "
2739 "executable range from 0x%llx to 0x%llx:"
2740 "might cause code-signing issues "
2744 ? proc_name_address(bsd_info
)
2746 (uint64_t) map_start
,
2747 (uint64_t) map_end
);
2749 DTRACE_VM2(cs_executable_mem_entry
,
2750 uint64_t, (uint64_t)map_start
,
2751 uint64_t, (uint64_t)map_end
);
2752 cs_executable_mem_entry
++;
2756 * We don't know how the memory entry will be used.
2757 * It might never get wired and might not cause any
2758 * trouble, so let's not reject this request...
2761 kr
= KERN_PROTECTION_FAILURE
;
2762 vm_object_unlock(object
);
2763 vm_map_unlock_read(target_map
);
2764 if (real_map
!= target_map
) {
2765 vm_map_unlock_read(real_map
);
2770 #endif /* CONFIG_EMBEDDED */
2772 if (((prot
& protections
) != protections
)
2773 || (object
== kernel_object
)) {
2774 kr
= KERN_INVALID_RIGHT
;
2775 vm_object_unlock(object
);
2776 vm_map_unlock_read(target_map
);
2777 if (real_map
!= target_map
) {
2778 vm_map_unlock_read(real_map
);
2780 if (object
== kernel_object
) {
2781 printf("Warning: Attempt to create a named"
2782 " entry from the kernel_object\n");
2787 /* We have an object, now check to see if this object */
2788 /* is suitable. If not, create a shadow and share that */
2791 * We have to unlock the VM object to avoid deadlocking with
2792 * a VM map lock (the lock ordering is map, the object), if we
2793 * need to modify the VM map to create a shadow object. Since
2794 * we might release the VM map lock below anyway, we have
2795 * to release the VM map lock now.
2796 * XXX FBDP There must be a way to avoid this double lookup...
2798 * Take an extra reference on the VM object to make sure it's
2799 * not going to disappear.
2801 vm_object_reference_locked(object
); /* extra ref to hold obj */
2802 vm_object_unlock(object
);
2804 local_map
= original_map
;
2805 local_offset
= map_start
;
2806 if (target_map
!= local_map
) {
2807 vm_map_unlock_read(target_map
);
2808 if (real_map
!= target_map
) {
2809 vm_map_unlock_read(real_map
);
2811 vm_map_lock_read(local_map
);
2812 target_map
= local_map
;
2813 real_map
= local_map
;
2816 if (!vm_map_lookup_entry(local_map
,
2817 local_offset
, &map_entry
)) {
2818 kr
= KERN_INVALID_ARGUMENT
;
2819 vm_map_unlock_read(target_map
);
2820 if (real_map
!= target_map
) {
2821 vm_map_unlock_read(real_map
);
2823 vm_object_deallocate(object
); /* release extra ref */
2824 object
= VM_OBJECT_NULL
;
2827 iskernel
= (local_map
->pmap
== kernel_pmap
);
2828 if (!(map_entry
->is_sub_map
)) {
2829 if (VME_OBJECT(map_entry
) != object
) {
2830 kr
= KERN_INVALID_ARGUMENT
;
2831 vm_map_unlock_read(target_map
);
2832 if (real_map
!= target_map
) {
2833 vm_map_unlock_read(real_map
);
2835 vm_object_deallocate(object
); /* release extra ref */
2836 object
= VM_OBJECT_NULL
;
2843 local_map
= VME_SUBMAP(map_entry
);
2845 vm_map_lock_read(local_map
);
2846 vm_map_unlock_read(tmap
);
2847 target_map
= local_map
;
2848 real_map
= local_map
;
2849 local_offset
= local_offset
- map_entry
->vme_start
;
2850 local_offset
+= VME_OFFSET(map_entry
);
2854 #if VM_NAMED_ENTRY_LIST
2855 alias
= VME_ALIAS(map_entry
);
2856 #endif /* VM_NAMED_ENTRY_LIST */
2859 * We found the VM map entry, lock the VM object again.
2861 vm_object_lock(object
);
2862 if (map_entry
->wired_count
) {
2863 /* JMM - The check below should be reworked instead. */
2864 object
->true_share
= TRUE
;
2866 if (mask_protections
) {
2868 * The caller asked us to use the "protections" as
2869 * a mask, so restrict "protections" to what this
2870 * mapping actually allows.
2872 protections
&= map_entry
->max_protection
;
2874 if (((map_entry
->max_protection
) & protections
) != protections
) {
2875 kr
= KERN_INVALID_RIGHT
;
2876 vm_object_unlock(object
);
2877 vm_map_unlock_read(target_map
);
2878 if (real_map
!= target_map
) {
2879 vm_map_unlock_read(real_map
);
2881 vm_object_deallocate(object
);
2882 object
= VM_OBJECT_NULL
;
2886 mappable_size
= fault_info
.hi_offset
- obj_off
;
2887 total_size
= map_entry
->vme_end
- map_entry
->vme_start
;
2888 if (map_size
> mappable_size
) {
2889 /* try to extend mappable size if the entries */
2890 /* following are from the same object and are */
2892 next_entry
= map_entry
->vme_next
;
2893 /* lets see if the next map entry is still */
2894 /* pointing at this object and is contiguous */
2895 while (map_size
> mappable_size
) {
2896 if ((VME_OBJECT(next_entry
) == object
) &&
2897 (next_entry
->vme_start
==
2898 next_entry
->vme_prev
->vme_end
) &&
2899 (VME_OFFSET(next_entry
) ==
2900 (VME_OFFSET(next_entry
->vme_prev
) +
2901 (next_entry
->vme_prev
->vme_end
-
2902 next_entry
->vme_prev
->vme_start
)))) {
2903 if (mask_protections
) {
2905 * The caller asked us to use
2906 * the "protections" as a mask,
2907 * so restrict "protections" to
2908 * what this mapping actually
2911 protections
&= next_entry
->max_protection
;
2913 if ((next_entry
->wired_count
) &&
2914 (map_entry
->wired_count
== 0)) {
2917 if (((next_entry
->max_protection
)
2918 & protections
) != protections
) {
2921 if (next_entry
->needs_copy
!=
2922 map_entry
->needs_copy
) {
2925 mappable_size
+= next_entry
->vme_end
2926 - next_entry
->vme_start
;
2927 total_size
+= next_entry
->vme_end
2928 - next_entry
->vme_start
;
2929 next_entry
= next_entry
->vme_next
;
2936 /* vm_map_entry_should_cow_for_true_share() checks for malloc tags,
2937 * never true in kernel */
2938 if (!iskernel
&& vm_map_entry_should_cow_for_true_share(map_entry
) &&
2939 object
->vo_size
> map_size
&&
2942 * Set up the targeted range for copy-on-write to
2943 * limit the impact of "true_share"/"copy_delay" to
2944 * that range instead of the entire VM object...
2947 vm_object_unlock(object
);
2948 if (vm_map_lock_read_to_write(target_map
)) {
2949 vm_object_deallocate(object
);
2950 target_map
= original_map
;
2954 vm_map_clip_start(target_map
,
2956 vm_map_trunc_page(map_start
,
2957 VM_MAP_PAGE_MASK(target_map
)));
2958 vm_map_clip_end(target_map
,
2960 (vm_map_round_page(map_end
,
2961 VM_MAP_PAGE_MASK(target_map
))));
2962 force_shadow
= TRUE
;
2964 if ((map_entry
->vme_end
- offset
) < map_size
) {
2965 map_size
= map_entry
->vme_end
- map_start
;
2967 total_size
= map_entry
->vme_end
- map_entry
->vme_start
;
2969 vm_map_lock_write_to_read(target_map
);
2970 vm_object_lock(object
);
2973 if (object
->internal
) {
2974 /* vm_map_lookup_locked will create a shadow if */
2975 /* needs_copy is set but does not check for the */
2976 /* other two conditions shown. It is important to */
2977 /* set up an object which will not be pulled from */
2981 ((map_entry
->needs_copy
||
2983 (object
->vo_size
> total_size
&&
2984 (VME_OFFSET(map_entry
) != 0 ||
2986 vm_map_round_page(total_size
,
2987 VM_MAP_PAGE_MASK(target_map
)))))
2988 && !object
->true_share
2989 && object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)) {
2991 * We have to unlock the VM object before
2992 * trying to upgrade the VM map lock, to
2993 * honor lock ordering (map then object).
2994 * Otherwise, we would deadlock if another
2995 * thread holds a read lock on the VM map and
2996 * is trying to acquire the VM object's lock.
2997 * We still hold an extra reference on the
2998 * VM object, guaranteeing that it won't
3001 vm_object_unlock(object
);
3003 if (vm_map_lock_read_to_write(target_map
)) {
3005 * We couldn't upgrade our VM map lock
3006 * from "read" to "write" and we lost
3008 * Start all over again...
3010 vm_object_deallocate(object
); /* extra ref */
3011 target_map
= original_map
;
3015 vm_object_lock(object
);
3019 * JMM - We need to avoid coming here when the object
3020 * is wired by anybody, not just the current map. Why
3021 * couldn't we use the standard vm_object_copy_quickly()
3025 /* create a shadow object */
3026 VME_OBJECT_SHADOW(map_entry
, total_size
);
3027 shadow_object
= VME_OBJECT(map_entry
);
3029 vm_object_unlock(object
);
3032 prot
= map_entry
->protection
& ~VM_PROT_WRITE
;
3034 if (override_nx(target_map
,
3035 VME_ALIAS(map_entry
))
3037 prot
|= VM_PROT_EXECUTE
;
3040 vm_object_pmap_protect(
3041 object
, VME_OFFSET(map_entry
),
3043 ((map_entry
->is_shared
3044 || target_map
->mapped_in_other_pmaps
)
3047 map_entry
->vme_start
,
3049 total_size
-= (map_entry
->vme_end
3050 - map_entry
->vme_start
);
3051 next_entry
= map_entry
->vme_next
;
3052 map_entry
->needs_copy
= FALSE
;
3054 vm_object_lock(shadow_object
);
3055 while (total_size
) {
3056 assert((next_entry
->wired_count
== 0) ||
3057 (map_entry
->wired_count
));
3059 if (VME_OBJECT(next_entry
) == object
) {
3060 vm_object_reference_locked(shadow_object
);
3061 VME_OBJECT_SET(next_entry
,
3063 vm_object_deallocate(object
);
3066 (VME_OFFSET(next_entry
->vme_prev
) +
3067 (next_entry
->vme_prev
->vme_end
3068 - next_entry
->vme_prev
->vme_start
)));
3069 next_entry
->use_pmap
= TRUE
;
3070 next_entry
->needs_copy
= FALSE
;
3072 panic("mach_make_memory_entry_64:"
3073 " map entries out of sync\n");
3077 - next_entry
->vme_start
;
3078 next_entry
= next_entry
->vme_next
;
3082 * Transfer our extra reference to the
3085 vm_object_reference_locked(shadow_object
);
3086 vm_object_deallocate(object
); /* extra ref */
3087 object
= shadow_object
;
3089 obj_off
= ((local_offset
- map_entry
->vme_start
)
3090 + VME_OFFSET(map_entry
));
3092 vm_map_lock_write_to_read(target_map
);
3096 /* note: in the future we can (if necessary) allow for */
3097 /* memory object lists, this will better support */
3098 /* fragmentation, but is it necessary? The user should */
3099 /* be encouraged to create address space oriented */
3100 /* shared objects from CLEAN memory regions which have */
3101 /* a known and defined history. i.e. no inheritence */
3102 /* share, make this call before making the region the */
3103 /* target of ipc's, etc. The code above, protecting */
3104 /* against delayed copy, etc. is mostly defensive. */
3106 wimg_mode
= object
->wimg_bits
;
3107 if (!(object
->nophyscache
)) {
3108 vm_prot_to_wimg(access
, &wimg_mode
);
3111 #if VM_OBJECT_TRACKING_OP_TRUESHARE
3112 if (!object
->true_share
&&
3113 vm_object_tracking_inited
) {
3114 void *bt
[VM_OBJECT_TRACKING_BTDEPTH
];
3117 num
= OSBacktrace(bt
,
3118 VM_OBJECT_TRACKING_BTDEPTH
);
3119 btlog_add_entry(vm_object_tracking_btlog
,
3121 VM_OBJECT_TRACKING_OP_TRUESHARE
,
3125 #endif /* VM_OBJECT_TRACKING_OP_TRUESHARE */
3127 vm_object_lock_assert_exclusive(object
);
3128 object
->true_share
= TRUE
;
3129 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
) {
3130 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
3134 * The memory entry now points to this VM object and we
3135 * need to hold a reference on the VM object. Use the extra
3136 * reference we took earlier to keep the object alive when we
3140 vm_map_unlock_read(target_map
);
3141 if (real_map
!= target_map
) {
3142 vm_map_unlock_read(real_map
);
3145 if (object
->wimg_bits
!= wimg_mode
) {
3146 vm_object_change_wimg_mode(object
, wimg_mode
);
3149 /* the size of mapped entry that overlaps with our region */
3150 /* which is targeted for share. */
3151 /* (entry_end - entry_start) - */
3152 /* offset of our beg addr within entry */
3153 /* it corresponds to this: */
3155 if (map_size
> mappable_size
) {
3156 map_size
= mappable_size
;
3159 if (permission
& MAP_MEM_NAMED_REUSE
) {
3161 * Compare what we got with the "parent_entry".
3162 * If they match, re-use the "parent_entry" instead
3163 * of creating a new one.
3165 if (parent_entry
!= NULL
&&
3166 parent_entry
->backing
.object
== object
&&
3167 parent_entry
->internal
== object
->internal
&&
3168 parent_entry
->is_sub_map
== FALSE
&&
3169 parent_entry
->offset
== obj_off
&&
3170 parent_entry
->protection
== protections
&&
3171 parent_entry
->size
== map_size
&&
3172 ((!(use_data_addr
|| use_4K_compat
) &&
3173 (parent_entry
->data_offset
== 0)) ||
3174 ((use_data_addr
|| use_4K_compat
) &&
3175 (parent_entry
->data_offset
== offset_in_page
)))) {
3177 * We have a match: re-use "parent_entry".
3179 /* release our extra reference on object */
3180 vm_object_unlock(object
);
3181 vm_object_deallocate(object
);
3182 /* parent_entry->ref_count++; XXX ? */
3183 /* Get an extra send-right on handle */
3184 ipc_port_copy_send(parent_handle
);
3186 *size
= CAST_DOWN(vm_size_t
,
3187 (parent_entry
->size
-
3188 parent_entry
->data_offset
));
3189 *object_handle
= parent_handle
;
3190 return KERN_SUCCESS
;
3193 * No match: we need to create a new entry.
3199 vm_object_unlock(object
);
3200 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
3202 /* release our unused reference on the object */
3203 vm_object_deallocate(object
);
3204 return KERN_FAILURE
;
3207 user_entry
->backing
.object
= object
;
3208 user_entry
->internal
= object
->internal
;
3209 user_entry
->is_sub_map
= FALSE
;
3210 user_entry
->offset
= obj_off
;
3211 user_entry
->data_offset
= offset_in_page
;
3212 user_entry
->protection
= protections
;
3213 SET_MAP_MEM(GET_MAP_MEM(permission
), user_entry
->protection
);
3214 user_entry
->size
= map_size
;
3215 #if VM_NAMED_ENTRY_LIST
3216 user_entry
->named_entry_alias
= alias
;
3217 #endif /* VM_NAMED_ENTRY_LIST */
3219 /* user_object pager and internal fields are not used */
3220 /* when the object field is filled in. */
3222 *size
= CAST_DOWN(vm_size_t
, (user_entry
->size
-
3223 user_entry
->data_offset
));
3224 *object_handle
= user_handle
;
3225 return KERN_SUCCESS
;
3227 /* The new object will be base on an existing named object */
3228 if (parent_entry
== NULL
) {
3229 kr
= KERN_INVALID_ARGUMENT
;
3233 if (use_data_addr
|| use_4K_compat
) {
3235 * submaps and pagers should only be accessible from within
3236 * the kernel, which shouldn't use the data address flag, so can fail here.
3238 if (parent_entry
->is_sub_map
) {
3239 panic("Shouldn't be using data address with a parent entry that is a submap.");
3242 * Account for offset to data in parent entry and
3243 * compute our own offset to data.
3245 if ((offset
+ *size
+ parent_entry
->data_offset
) > parent_entry
->size
) {
3246 kr
= KERN_INVALID_ARGUMENT
;
3250 map_start
= vm_map_trunc_page(offset
+ parent_entry
->data_offset
, PAGE_MASK
);
3251 offset_in_page
= (offset
+ parent_entry
->data_offset
) - map_start
;
3252 if (use_4K_compat
) {
3253 offset_in_page
&= ~((signed)(0xFFF));
3255 map_end
= vm_map_round_page(offset
+ parent_entry
->data_offset
+ *size
, PAGE_MASK
);
3256 map_size
= map_end
- map_start
;
3258 map_end
= vm_map_round_page(offset
+ *size
, PAGE_MASK
);
3259 map_size
= map_end
- map_start
;
3262 if ((offset
+ map_size
) > parent_entry
->size
) {
3263 kr
= KERN_INVALID_ARGUMENT
;
3268 if (mask_protections
) {
3270 * The caller asked us to use the "protections" as
3271 * a mask, so restrict "protections" to what this
3272 * mapping actually allows.
3274 protections
&= parent_entry
->protection
;
3276 if ((protections
& parent_entry
->protection
) != protections
) {
3277 kr
= KERN_PROTECTION_FAILURE
;
3281 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
3287 user_entry
->size
= map_size
;
3288 user_entry
->offset
= parent_entry
->offset
+ map_start
;
3289 user_entry
->data_offset
= offset_in_page
;
3290 user_entry
->is_sub_map
= parent_entry
->is_sub_map
;
3291 user_entry
->is_copy
= parent_entry
->is_copy
;
3292 user_entry
->internal
= parent_entry
->internal
;
3293 user_entry
->protection
= protections
;
3295 if (access
!= MAP_MEM_NOOP
) {
3296 SET_MAP_MEM(access
, user_entry
->protection
);
3299 if (parent_entry
->is_sub_map
) {
3300 user_entry
->backing
.map
= parent_entry
->backing
.map
;
3301 vm_map_lock(user_entry
->backing
.map
);
3302 user_entry
->backing
.map
->map_refcnt
++;
3303 vm_map_unlock(user_entry
->backing
.map
);
3305 object
= parent_entry
->backing
.object
;
3306 assert(object
!= VM_OBJECT_NULL
);
3307 user_entry
->backing
.object
= object
;
3308 /* we now point to this object, hold on */
3309 vm_object_lock(object
);
3310 vm_object_reference_locked(object
);
3311 #if VM_OBJECT_TRACKING_OP_TRUESHARE
3312 if (!object
->true_share
&&
3313 vm_object_tracking_inited
) {
3314 void *bt
[VM_OBJECT_TRACKING_BTDEPTH
];
3317 num
= OSBacktrace(bt
,
3318 VM_OBJECT_TRACKING_BTDEPTH
);
3319 btlog_add_entry(vm_object_tracking_btlog
,
3321 VM_OBJECT_TRACKING_OP_TRUESHARE
,
3325 #endif /* VM_OBJECT_TRACKING_OP_TRUESHARE */
3327 object
->true_share
= TRUE
;
3328 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
) {
3329 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
3331 vm_object_unlock(object
);
3333 *size
= CAST_DOWN(vm_size_t
, (user_entry
->size
-
3334 user_entry
->data_offset
));
3335 *object_handle
= user_handle
;
3336 return KERN_SUCCESS
;
3340 if (user_handle
!= IP_NULL
) {
3342 * Releasing "user_handle" causes the kernel object
3343 * associated with it ("user_entry" here) to also be
3344 * released and freed.
3346 mach_memory_entry_port_release(user_handle
);
3352 _mach_make_memory_entry(
3353 vm_map_t target_map
,
3354 memory_object_size_t
*size
,
3355 memory_object_offset_t offset
,
3356 vm_prot_t permission
,
3357 ipc_port_t
*object_handle
,
3358 ipc_port_t parent_entry
)
3360 memory_object_size_t mo_size
;
3363 mo_size
= (memory_object_size_t
)*size
;
3364 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
3365 (memory_object_offset_t
)offset
, permission
, object_handle
,
3372 mach_make_memory_entry(
3373 vm_map_t target_map
,
3376 vm_prot_t permission
,
3377 ipc_port_t
*object_handle
,
3378 ipc_port_t parent_entry
)
3380 memory_object_size_t mo_size
;
3383 mo_size
= (memory_object_size_t
)*size
;
3384 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
3385 (memory_object_offset_t
)offset
, permission
, object_handle
,
3387 *size
= CAST_DOWN(vm_size_t
, mo_size
);
3394 * Set or clear the map's wiring_required flag. This flag, if set,
3395 * will cause all future virtual memory allocation to allocate
3396 * user wired memory. Unwiring pages wired down as a result of
3397 * this routine is done with the vm_wire interface.
3402 boolean_t must_wire
)
3404 if (map
== VM_MAP_NULL
) {
3405 return KERN_INVALID_ARGUMENT
;
3409 map
->wiring_required
= (must_wire
== TRUE
);
3412 return KERN_SUCCESS
;
3416 vm_map_exec_lockdown(
3419 if (map
== VM_MAP_NULL
) {
3420 return KERN_INVALID_ARGUMENT
;
3424 map
->map_disallow_new_exec
= TRUE
;
3427 return KERN_SUCCESS
;
3430 #if VM_NAMED_ENTRY_LIST
3431 queue_head_t vm_named_entry_list
;
3432 int vm_named_entry_count
= 0;
3433 lck_mtx_t vm_named_entry_list_lock_data
;
3434 lck_mtx_ext_t vm_named_entry_list_lock_data_ext
;
3435 #endif /* VM_NAMED_ENTRY_LIST */
3437 void vm_named_entry_init(void);
3439 vm_named_entry_init(void)
3441 #if VM_NAMED_ENTRY_LIST
3442 queue_init(&vm_named_entry_list
);
3443 vm_named_entry_count
= 0;
3444 lck_mtx_init_ext(&vm_named_entry_list_lock_data
,
3445 &vm_named_entry_list_lock_data_ext
,
3447 &vm_object_lck_attr
);
3448 #endif /* VM_NAMED_ENTRY_LIST */
3451 __private_extern__ kern_return_t
3452 mach_memory_entry_allocate(
3453 vm_named_entry_t
*user_entry_p
,
3454 ipc_port_t
*user_handle_p
)
3456 vm_named_entry_t user_entry
;
3457 ipc_port_t user_handle
;
3458 ipc_port_t previous
;
3460 user_entry
= (vm_named_entry_t
) kalloc(sizeof *user_entry
);
3461 if (user_entry
== NULL
) {
3462 return KERN_FAILURE
;
3464 bzero(user_entry
, sizeof(*user_entry
));
3466 named_entry_lock_init(user_entry
);
3468 user_handle
= ipc_port_alloc_kernel();
3469 if (user_handle
== IP_NULL
) {
3470 kfree(user_entry
, sizeof *user_entry
);
3471 return KERN_FAILURE
;
3473 ip_lock(user_handle
);
3475 /* make a sonce right */
3476 user_handle
->ip_sorights
++;
3477 ip_reference(user_handle
);
3479 /* make a send right */
3480 user_handle
->ip_mscount
++;
3481 user_handle
->ip_srights
++;
3482 ip_reference(user_handle
);
3484 ipc_port_nsrequest(user_handle
, 1, user_handle
, &previous
);
3485 /* nsrequest unlocks user_handle */
3487 user_entry
->backing
.object
= NULL
;
3488 user_entry
->is_sub_map
= FALSE
;
3489 user_entry
->is_copy
= FALSE
;
3490 user_entry
->internal
= FALSE
;
3491 user_entry
->size
= 0;
3492 user_entry
->offset
= 0;
3493 user_entry
->data_offset
= 0;
3494 user_entry
->protection
= VM_PROT_NONE
;
3495 user_entry
->ref_count
= 1;
3497 ipc_kobject_set(user_handle
, (ipc_kobject_t
) user_entry
,
3500 *user_entry_p
= user_entry
;
3501 *user_handle_p
= user_handle
;
3503 #if VM_NAMED_ENTRY_LIST
3504 /* keep a loose (no reference) pointer to the Mach port, for debugging only */
3505 user_entry
->named_entry_port
= user_handle
;
3506 /* backtrace at allocation time, for debugging only */
3507 OSBacktrace(&user_entry
->named_entry_bt
[0],
3508 NAMED_ENTRY_BT_DEPTH
);
3510 /* add this new named entry to the global list */
3511 lck_mtx_lock_spin(&vm_named_entry_list_lock_data
);
3512 queue_enter(&vm_named_entry_list
, user_entry
,
3513 vm_named_entry_t
, named_entry_list
);
3514 vm_named_entry_count
++;
3515 lck_mtx_unlock(&vm_named_entry_list_lock_data
);
3516 #endif /* VM_NAMED_ENTRY_LIST */
3518 return KERN_SUCCESS
;
3522 * mach_memory_object_memory_entry_64
3524 * Create a named entry backed by the provided pager.
3528 mach_memory_object_memory_entry_64(
3531 vm_object_offset_t size
,
3532 vm_prot_t permission
,
3533 memory_object_t pager
,
3534 ipc_port_t
*entry_handle
)
3536 unsigned int access
;
3537 vm_named_entry_t user_entry
;
3538 ipc_port_t user_handle
;
3541 if (host
== HOST_NULL
) {
3542 return KERN_INVALID_HOST
;
3545 if (pager
== MEMORY_OBJECT_NULL
&& internal
) {
3546 object
= vm_object_allocate(size
);
3547 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
) {
3548 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
3551 object
= memory_object_to_vm_object(pager
);
3552 if (object
!= VM_OBJECT_NULL
) {
3553 vm_object_reference(object
);
3556 if (object
== VM_OBJECT_NULL
) {
3557 return KERN_INVALID_ARGUMENT
;
3560 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
3562 vm_object_deallocate(object
);
3563 return KERN_FAILURE
;
3566 user_entry
->size
= size
;
3567 user_entry
->offset
= 0;
3568 user_entry
->protection
= permission
& VM_PROT_ALL
;
3569 access
= GET_MAP_MEM(permission
);
3570 SET_MAP_MEM(access
, user_entry
->protection
);
3571 user_entry
->is_sub_map
= FALSE
;
3572 assert(user_entry
->ref_count
== 1);
3574 user_entry
->backing
.object
= object
;
3575 user_entry
->internal
= object
->internal
;
3576 assert(object
->internal
== internal
);
3578 *entry_handle
= user_handle
;
3579 return KERN_SUCCESS
;
3583 mach_memory_object_memory_entry(
3587 vm_prot_t permission
,
3588 memory_object_t pager
,
3589 ipc_port_t
*entry_handle
)
3591 return mach_memory_object_memory_entry_64( host
, internal
,
3592 (vm_object_offset_t
)size
, permission
, pager
, entry_handle
);
3597 mach_memory_entry_purgable_control(
3598 ipc_port_t entry_port
,
3599 vm_purgable_t control
,
3602 if (control
== VM_PURGABLE_SET_STATE_FROM_KERNEL
) {
3603 /* not allowed from user-space */
3604 return KERN_INVALID_ARGUMENT
;
3607 return memory_entry_purgeable_control_internal(entry_port
, control
, state
);
3611 memory_entry_purgeable_control_internal(
3612 ipc_port_t entry_port
,
3613 vm_purgable_t control
,
3617 vm_named_entry_t mem_entry
;
3620 if (!IP_VALID(entry_port
) ||
3621 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
3622 return KERN_INVALID_ARGUMENT
;
3624 if (control
!= VM_PURGABLE_SET_STATE
&&
3625 control
!= VM_PURGABLE_GET_STATE
&&
3626 control
!= VM_PURGABLE_SET_STATE_FROM_KERNEL
) {
3627 return KERN_INVALID_ARGUMENT
;
3630 if ((control
== VM_PURGABLE_SET_STATE
||
3631 control
== VM_PURGABLE_SET_STATE_FROM_KERNEL
) &&
3632 (((*state
& ~(VM_PURGABLE_ALL_MASKS
)) != 0) ||
3633 ((*state
& VM_PURGABLE_STATE_MASK
) > VM_PURGABLE_STATE_MASK
))) {
3634 return KERN_INVALID_ARGUMENT
;
3637 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
3639 named_entry_lock(mem_entry
);
3641 if (mem_entry
->is_sub_map
||
3642 mem_entry
->is_copy
) {
3643 named_entry_unlock(mem_entry
);
3644 return KERN_INVALID_ARGUMENT
;
3647 object
= mem_entry
->backing
.object
;
3648 if (object
== VM_OBJECT_NULL
) {
3649 named_entry_unlock(mem_entry
);
3650 return KERN_INVALID_ARGUMENT
;
3653 vm_object_lock(object
);
3655 /* check that named entry covers entire object ? */
3656 if (mem_entry
->offset
!= 0 || object
->vo_size
!= mem_entry
->size
) {
3657 vm_object_unlock(object
);
3658 named_entry_unlock(mem_entry
);
3659 return KERN_INVALID_ARGUMENT
;
3662 named_entry_unlock(mem_entry
);
3664 kr
= vm_object_purgable_control(object
, control
, state
);
3666 vm_object_unlock(object
);
3672 mach_memory_entry_access_tracking(
3673 ipc_port_t entry_port
,
3674 int *access_tracking
,
3675 uint32_t *access_tracking_reads
,
3676 uint32_t *access_tracking_writes
)
3678 return memory_entry_access_tracking_internal(entry_port
,
3680 access_tracking_reads
,
3681 access_tracking_writes
);
3685 memory_entry_access_tracking_internal(
3686 ipc_port_t entry_port
,
3687 int *access_tracking
,
3688 uint32_t *access_tracking_reads
,
3689 uint32_t *access_tracking_writes
)
3691 vm_named_entry_t mem_entry
;
3695 if (!IP_VALID(entry_port
) ||
3696 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
3697 return KERN_INVALID_ARGUMENT
;
3700 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
3702 named_entry_lock(mem_entry
);
3704 if (mem_entry
->is_sub_map
||
3705 mem_entry
->is_copy
) {
3706 named_entry_unlock(mem_entry
);
3707 return KERN_INVALID_ARGUMENT
;
3710 object
= mem_entry
->backing
.object
;
3711 if (object
== VM_OBJECT_NULL
) {
3712 named_entry_unlock(mem_entry
);
3713 return KERN_INVALID_ARGUMENT
;
3716 #if VM_OBJECT_ACCESS_TRACKING
3717 vm_object_access_tracking(object
,
3719 access_tracking_reads
,
3720 access_tracking_writes
);
3722 #else /* VM_OBJECT_ACCESS_TRACKING */
3723 (void) access_tracking
;
3724 (void) access_tracking_reads
;
3725 (void) access_tracking_writes
;
3726 kr
= KERN_NOT_SUPPORTED
;
3727 #endif /* VM_OBJECT_ACCESS_TRACKING */
3729 named_entry_unlock(mem_entry
);
3735 mach_memory_entry_get_page_counts(
3736 ipc_port_t entry_port
,
3737 unsigned int *resident_page_count
,
3738 unsigned int *dirty_page_count
)
3741 vm_named_entry_t mem_entry
;
3743 vm_object_offset_t offset
;
3744 vm_object_size_t size
;
3746 if (!IP_VALID(entry_port
) ||
3747 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
3748 return KERN_INVALID_ARGUMENT
;
3751 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
3753 named_entry_lock(mem_entry
);
3755 if (mem_entry
->is_sub_map
||
3756 mem_entry
->is_copy
) {
3757 named_entry_unlock(mem_entry
);
3758 return KERN_INVALID_ARGUMENT
;
3761 object
= mem_entry
->backing
.object
;
3762 if (object
== VM_OBJECT_NULL
) {
3763 named_entry_unlock(mem_entry
);
3764 return KERN_INVALID_ARGUMENT
;
3767 vm_object_lock(object
);
3769 offset
= mem_entry
->offset
;
3770 size
= mem_entry
->size
;
3772 named_entry_unlock(mem_entry
);
3774 kr
= vm_object_get_page_counts(object
, offset
, size
, resident_page_count
, dirty_page_count
);
3776 vm_object_unlock(object
);
3782 * mach_memory_entry_port_release:
3784 * Release a send right on a named entry port. This is the correct
3785 * way to destroy a named entry. When the last right on the port is
3786 * released, ipc_kobject_destroy() will call mach_destroy_memory_entry().
3789 mach_memory_entry_port_release(
3792 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
3793 ipc_port_release_send(port
);
3797 * mach_destroy_memory_entry:
3799 * Drops a reference on a memory entry and destroys the memory entry if
3800 * there are no more references on it.
3801 * NOTE: This routine should not be called to destroy a memory entry from the
3802 * kernel, as it will not release the Mach port associated with the memory
3803 * entry. The proper way to destroy a memory entry in the kernel is to
3804 * call mach_memort_entry_port_release() to release the kernel's send-right on
3805 * the memory entry's port. When the last send right is released, the memory
3806 * entry will be destroyed via ipc_kobject_destroy().
3809 mach_destroy_memory_entry(
3812 vm_named_entry_t named_entry
;
3814 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
3815 #endif /* MACH_ASSERT */
3816 named_entry
= (vm_named_entry_t
)port
->ip_kobject
;
3818 named_entry_lock(named_entry
);
3819 named_entry
->ref_count
-= 1;
3821 if (named_entry
->ref_count
== 0) {
3822 if (named_entry
->is_sub_map
) {
3823 vm_map_deallocate(named_entry
->backing
.map
);
3824 } else if (named_entry
->is_copy
) {
3825 vm_map_copy_discard(named_entry
->backing
.copy
);
3827 /* release the VM object we've been pointing to */
3828 vm_object_deallocate(named_entry
->backing
.object
);
3831 named_entry_unlock(named_entry
);
3832 named_entry_lock_destroy(named_entry
);
3834 #if VM_NAMED_ENTRY_LIST
3835 lck_mtx_lock_spin(&vm_named_entry_list_lock_data
);
3836 queue_remove(&vm_named_entry_list
, named_entry
,
3837 vm_named_entry_t
, named_entry_list
);
3838 assert(vm_named_entry_count
> 0);
3839 vm_named_entry_count
--;
3840 lck_mtx_unlock(&vm_named_entry_list_lock_data
);
3841 #endif /* VM_NAMED_ENTRY_LIST */
3843 kfree(port
->ip_kobject
,
3844 sizeof(struct vm_named_entry
));
3846 named_entry_unlock(named_entry
);
3850 /* Allow manipulation of individual page state. This is actually part of */
3851 /* the UPL regimen but takes place on the memory entry rather than on a UPL */
3854 mach_memory_entry_page_op(
3855 ipc_port_t entry_port
,
3856 vm_object_offset_t offset
,
3858 ppnum_t
*phys_entry
,
3861 vm_named_entry_t mem_entry
;
3865 if (!IP_VALID(entry_port
) ||
3866 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
3867 return KERN_INVALID_ARGUMENT
;
3870 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
3872 named_entry_lock(mem_entry
);
3874 if (mem_entry
->is_sub_map
||
3875 mem_entry
->is_copy
) {
3876 named_entry_unlock(mem_entry
);
3877 return KERN_INVALID_ARGUMENT
;
3880 object
= mem_entry
->backing
.object
;
3881 if (object
== VM_OBJECT_NULL
) {
3882 named_entry_unlock(mem_entry
);
3883 return KERN_INVALID_ARGUMENT
;
3886 vm_object_reference(object
);
3887 named_entry_unlock(mem_entry
);
3889 kr
= vm_object_page_op(object
, offset
, ops
, phys_entry
, flags
);
3891 vm_object_deallocate(object
);
3897 * mach_memory_entry_range_op offers performance enhancement over
3898 * mach_memory_entry_page_op for page_op functions which do not require page
3899 * level state to be returned from the call. Page_op was created to provide
3900 * a low-cost alternative to page manipulation via UPLs when only a single
3901 * page was involved. The range_op call establishes the ability in the _op
3902 * family of functions to work on multiple pages where the lack of page level
3903 * state handling allows the caller to avoid the overhead of the upl structures.
3907 mach_memory_entry_range_op(
3908 ipc_port_t entry_port
,
3909 vm_object_offset_t offset_beg
,
3910 vm_object_offset_t offset_end
,
3914 vm_named_entry_t mem_entry
;
3918 if (!IP_VALID(entry_port
) ||
3919 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
3920 return KERN_INVALID_ARGUMENT
;
3923 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
3925 named_entry_lock(mem_entry
);
3927 if (mem_entry
->is_sub_map
||
3928 mem_entry
->is_copy
) {
3929 named_entry_unlock(mem_entry
);
3930 return KERN_INVALID_ARGUMENT
;
3933 object
= mem_entry
->backing
.object
;
3934 if (object
== VM_OBJECT_NULL
) {
3935 named_entry_unlock(mem_entry
);
3936 return KERN_INVALID_ARGUMENT
;
3939 vm_object_reference(object
);
3940 named_entry_unlock(mem_entry
);
3942 kr
= vm_object_range_op(object
,
3946 (uint32_t *) range
);
3948 vm_object_deallocate(object
);
3953 /* ******* Temporary Internal calls to UPL for BSD ***** */
3955 extern int kernel_upl_map(
3958 vm_offset_t
*dst_addr
);
3960 extern int kernel_upl_unmap(
3964 extern int kernel_upl_commit(
3966 upl_page_info_t
*pl
,
3967 mach_msg_type_number_t count
);
3969 extern int kernel_upl_commit_range(
3971 upl_offset_t offset
,
3974 upl_page_info_array_t pl
,
3975 mach_msg_type_number_t count
);
3977 extern int kernel_upl_abort(
3981 extern int kernel_upl_abort_range(
3983 upl_offset_t offset
,
3992 vm_offset_t
*dst_addr
)
3994 return vm_upl_map(map
, upl
, dst_addr
);
4003 return vm_upl_unmap(map
, upl
);
4009 upl_page_info_t
*pl
,
4010 mach_msg_type_number_t count
)
4014 kr
= upl_commit(upl
, pl
, count
);
4015 upl_deallocate(upl
);
4021 kernel_upl_commit_range(
4023 upl_offset_t offset
,
4026 upl_page_info_array_t pl
,
4027 mach_msg_type_number_t count
)
4029 boolean_t finished
= FALSE
;
4032 if (flags
& UPL_COMMIT_FREE_ON_EMPTY
) {
4033 flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
4036 if (flags
& UPL_COMMIT_KERNEL_ONLY_FLAGS
) {
4037 return KERN_INVALID_ARGUMENT
;
4040 kr
= upl_commit_range(upl
, offset
, size
, flags
, pl
, count
, &finished
);
4042 if ((flags
& UPL_COMMIT_NOTIFY_EMPTY
) && finished
) {
4043 upl_deallocate(upl
);
4050 kernel_upl_abort_range(
4052 upl_offset_t offset
,
4057 boolean_t finished
= FALSE
;
4059 if (abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
) {
4060 abort_flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
4063 kr
= upl_abort_range(upl
, offset
, size
, abort_flags
, &finished
);
4065 if ((abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
) && finished
) {
4066 upl_deallocate(upl
);
4079 kr
= upl_abort(upl
, abort_type
);
4080 upl_deallocate(upl
);
4085 * Now a kernel-private interface (for BootCache
4086 * use only). Need a cleaner way to create an
4087 * empty vm_map() and return a handle to it.
4091 vm_region_object_create(
4092 __unused vm_map_t target_map
,
4094 ipc_port_t
*object_handle
)
4096 vm_named_entry_t user_entry
;
4097 ipc_port_t user_handle
;
4101 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
4103 return KERN_FAILURE
;
4106 /* Create a named object based on a submap of specified size */
4108 new_map
= vm_map_create(PMAP_NULL
, VM_MAP_MIN_ADDRESS
,
4109 vm_map_round_page(size
,
4110 VM_MAP_PAGE_MASK(target_map
)),
4112 vm_map_set_page_shift(new_map
, VM_MAP_PAGE_SHIFT(target_map
));
4114 user_entry
->backing
.map
= new_map
;
4115 user_entry
->internal
= TRUE
;
4116 user_entry
->is_sub_map
= TRUE
;
4117 user_entry
->offset
= 0;
4118 user_entry
->protection
= VM_PROT_ALL
;
4119 user_entry
->size
= size
;
4120 assert(user_entry
->ref_count
== 1);
4122 *object_handle
= user_handle
;
4123 return KERN_SUCCESS
;
4126 ppnum_t
vm_map_get_phys_page( /* forward */
4128 vm_offset_t offset
);
4131 vm_map_get_phys_page(
4135 vm_object_offset_t offset
;
4137 vm_map_offset_t map_offset
;
4138 vm_map_entry_t entry
;
4139 ppnum_t phys_page
= 0;
4141 map_offset
= vm_map_trunc_page(addr
, PAGE_MASK
);
4144 while (vm_map_lookup_entry(map
, map_offset
, &entry
)) {
4145 if (VME_OBJECT(entry
) == VM_OBJECT_NULL
) {
4149 if (entry
->is_sub_map
) {
4151 vm_map_lock(VME_SUBMAP(entry
));
4153 map
= VME_SUBMAP(entry
);
4154 map_offset
= (VME_OFFSET(entry
) +
4155 (map_offset
- entry
->vme_start
));
4156 vm_map_unlock(old_map
);
4159 if (VME_OBJECT(entry
)->phys_contiguous
) {
4160 /* These are not standard pageable memory mappings */
4161 /* If they are not present in the object they will */
4162 /* have to be picked up from the pager through the */
4163 /* fault mechanism. */
4164 if (VME_OBJECT(entry
)->vo_shadow_offset
== 0) {
4165 /* need to call vm_fault */
4167 vm_fault(map
, map_offset
, VM_PROT_NONE
,
4168 FALSE
/* change_wiring */, VM_KERN_MEMORY_NONE
,
4169 THREAD_UNINT
, NULL
, 0);
4173 offset
= (VME_OFFSET(entry
) +
4174 (map_offset
- entry
->vme_start
));
4175 phys_page
= (ppnum_t
)
4176 ((VME_OBJECT(entry
)->vo_shadow_offset
4177 + offset
) >> PAGE_SHIFT
);
4180 offset
= (VME_OFFSET(entry
) + (map_offset
- entry
->vme_start
));
4181 object
= VME_OBJECT(entry
);
4182 vm_object_lock(object
);
4184 vm_page_t dst_page
= vm_page_lookup(object
, offset
);
4185 if (dst_page
== VM_PAGE_NULL
) {
4186 if (object
->shadow
) {
4187 vm_object_t old_object
;
4188 vm_object_lock(object
->shadow
);
4189 old_object
= object
;
4190 offset
= offset
+ object
->vo_shadow_offset
;
4191 object
= object
->shadow
;
4192 vm_object_unlock(old_object
);
4194 vm_object_unlock(object
);
4198 phys_page
= (ppnum_t
)(VM_PAGE_GET_PHYS_PAGE(dst_page
));
4199 vm_object_unlock(object
);
4211 kern_return_t
kernel_object_iopl_request( /* forward */
4212 vm_named_entry_t named_entry
,
4213 memory_object_offset_t offset
,
4214 upl_size_t
*upl_size
,
4216 upl_page_info_array_t user_page_list
,
4217 unsigned int *page_list_count
,
4221 kernel_object_iopl_request(
4222 vm_named_entry_t named_entry
,
4223 memory_object_offset_t offset
,
4224 upl_size_t
*upl_size
,
4226 upl_page_info_array_t user_page_list
,
4227 unsigned int *page_list_count
,
4235 caller_flags
= *flags
;
4237 if (caller_flags
& ~UPL_VALID_FLAGS
) {
4239 * For forward compatibility's sake,
4240 * reject any unknown flag.
4242 return KERN_INVALID_VALUE
;
4245 /* a few checks to make sure user is obeying rules */
4246 if (*upl_size
== 0) {
4247 if (offset
>= named_entry
->size
) {
4248 return KERN_INVALID_RIGHT
;
4250 *upl_size
= (upl_size_t
) (named_entry
->size
- offset
);
4251 if (*upl_size
!= named_entry
->size
- offset
) {
4252 return KERN_INVALID_ARGUMENT
;
4255 if (caller_flags
& UPL_COPYOUT_FROM
) {
4256 if ((named_entry
->protection
& VM_PROT_READ
)
4258 return KERN_INVALID_RIGHT
;
4261 if ((named_entry
->protection
&
4262 (VM_PROT_READ
| VM_PROT_WRITE
))
4263 != (VM_PROT_READ
| VM_PROT_WRITE
)) {
4264 return KERN_INVALID_RIGHT
;
4267 if (named_entry
->size
< (offset
+ *upl_size
)) {
4268 return KERN_INVALID_ARGUMENT
;
4271 /* the callers parameter offset is defined to be the */
4272 /* offset from beginning of named entry offset in object */
4273 offset
= offset
+ named_entry
->offset
;
4275 if (named_entry
->is_sub_map
||
4276 named_entry
->is_copy
) {
4277 return KERN_INVALID_ARGUMENT
;
4280 named_entry_lock(named_entry
);
4282 /* This is the case where we are going to operate */
4283 /* on an already known object. If the object is */
4284 /* not ready it is internal. An external */
4285 /* object cannot be mapped until it is ready */
4286 /* we can therefore avoid the ready check */
4288 object
= named_entry
->backing
.object
;
4289 vm_object_reference(object
);
4290 named_entry_unlock(named_entry
);
4292 if (!object
->private) {
4293 if (*upl_size
> MAX_UPL_TRANSFER_BYTES
) {
4294 *upl_size
= MAX_UPL_TRANSFER_BYTES
;
4296 if (object
->phys_contiguous
) {
4297 *flags
= UPL_PHYS_CONTIG
;
4302 *flags
= UPL_DEV_MEMORY
| UPL_PHYS_CONTIG
;
4305 ret
= vm_object_iopl_request(object
,
4311 (upl_control_flags_t
)(unsigned int)caller_flags
);
4312 vm_object_deallocate(object
);
4318 * These symbols are looked up at runtime by vmware, VirtualBox,
4319 * despite not being exported in the symbol sets.
4322 #if defined(__x86_64__)
4326 vm_map_t target_map
,
4327 mach_vm_offset_t
*address
,
4328 mach_vm_size_t initial_size
,
4329 mach_vm_offset_t mask
,
4332 vm_object_offset_t offset
,
4334 vm_prot_t cur_protection
,
4335 vm_prot_t max_protection
,
4336 vm_inherit_t inheritance
);
4340 vm_map_t target_map
,
4341 mach_vm_offset_t
*address
,
4342 mach_vm_size_t size
,
4343 mach_vm_offset_t mask
,
4346 mach_vm_offset_t memory_address
,
4348 vm_prot_t
*cur_protection
,
4349 vm_prot_t
*max_protection
,
4350 vm_inherit_t inheritance
);
4354 vm_map_t target_map
,
4355 mach_vm_offset_t
*address
,
4356 mach_vm_size_t initial_size
,
4357 mach_vm_offset_t mask
,
4360 vm_object_offset_t offset
,
4362 vm_prot_t cur_protection
,
4363 vm_prot_t max_protection
,
4364 vm_inherit_t inheritance
)
4366 return mach_vm_map_external(target_map
, address
, initial_size
, mask
, flags
, port
,
4367 offset
, copy
, cur_protection
, max_protection
, inheritance
);
4372 vm_map_t target_map
,
4373 mach_vm_offset_t
*address
,
4374 mach_vm_size_t size
,
4375 mach_vm_offset_t mask
,
4378 mach_vm_offset_t memory_address
,
4380 vm_prot_t
*cur_protection
,
4381 vm_prot_t
*max_protection
,
4382 vm_inherit_t inheritance
)
4384 return mach_vm_remap_external(target_map
, address
, size
, mask
, flags
, src_map
, memory_address
,
4385 copy
, cur_protection
, max_protection
, inheritance
);
4390 vm_map_t target_map
,
4391 vm_offset_t
*address
,
4398 vm_prot_t cur_protection
,
4399 vm_prot_t max_protection
,
4400 vm_inherit_t inheritance
);
4404 vm_map_t target_map
,
4405 vm_offset_t
*address
,
4412 vm_prot_t cur_protection
,
4413 vm_prot_t max_protection
,
4414 vm_inherit_t inheritance
)
4418 VM_GET_FLAGS_ALIAS(flags
, tag
);
4419 return vm_map_kernel(target_map
, address
, size
, mask
,
4420 flags
, VM_MAP_KERNEL_FLAGS_NONE
, tag
,
4422 cur_protection
, max_protection
, inheritance
);
4425 #endif /* __x86_64__ */