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.
68 #include <mach/boolean.h>
69 #include <mach/kern_return.h>
70 #include <mach/mach_types.h> /* to get vm_address_t */
71 #include <mach/memory_object.h>
72 #include <mach/std_types.h> /* to get pointer_t */
74 #include <mach/vm_attributes.h>
75 #include <mach/vm_param.h>
76 #include <mach/vm_statistics.h>
77 #include <mach/mach_syscalls.h>
79 #include <mach/host_priv_server.h>
80 #include <mach/mach_vm_server.h>
81 #include <mach/vm_map_server.h>
83 #include <kern/host.h>
84 #include <kern/kalloc.h>
85 #include <kern/task.h>
86 #include <kern/misc_protos.h>
87 #include <vm/vm_fault.h>
88 #include <vm/vm_map.h>
89 #include <vm/vm_object.h>
90 #include <vm/vm_page.h>
91 #include <vm/memory_object.h>
92 #include <vm/vm_pageout.h>
93 #include <vm/vm_protos.h>
95 vm_size_t upl_offset_to_pagelist
= 0;
101 ipc_port_t dynamic_pager_control_port
=NULL
;
104 * mach_vm_allocate allocates "zero fill" memory in the specfied
110 mach_vm_offset_t
*addr
,
114 vm_map_offset_t map_addr
;
115 vm_map_size_t map_size
;
116 kern_return_t result
;
119 /* filter out any kernel-only flags */
120 if (flags
& ~VM_FLAGS_USER_ALLOCATE
)
121 return KERN_INVALID_ARGUMENT
;
123 if (map
== VM_MAP_NULL
)
124 return(KERN_INVALID_ARGUMENT
);
127 return(KERN_SUCCESS
);
130 anywhere
= ((VM_FLAGS_ANYWHERE
& flags
) != 0);
133 * No specific address requested, so start candidate address
134 * search at the minimum address in the map. However, if that
135 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
136 * allocations of PAGEZERO to explicit requests since its
137 * normal use is to catch dereferences of NULL and many
138 * applications also treat pointers with a value of 0 as
139 * special and suddenly having address 0 contain useable
140 * memory would tend to confuse those applications.
142 map_addr
= vm_map_min(map
);
144 map_addr
+= PAGE_SIZE
;
146 map_addr
= vm_map_trunc_page(*addr
);
147 map_size
= vm_map_round_page(size
);
149 return(KERN_INVALID_ARGUMENT
);
152 result
= vm_map_enter(
159 (vm_object_offset_t
)0,
171 * Legacy routine that allocates "zero fill" memory in the specfied
172 * map (which is limited to the same size as the kernel).
181 vm_map_offset_t map_addr
;
182 vm_map_size_t map_size
;
183 kern_return_t result
;
186 /* filter out any kernel-only flags */
187 if (flags
& ~VM_FLAGS_USER_ALLOCATE
)
188 return KERN_INVALID_ARGUMENT
;
190 if (map
== VM_MAP_NULL
)
191 return(KERN_INVALID_ARGUMENT
);
194 return(KERN_SUCCESS
);
197 anywhere
= ((VM_FLAGS_ANYWHERE
& flags
) != 0);
200 * No specific address requested, so start candidate address
201 * search at the minimum address in the map. However, if that
202 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
203 * allocations of PAGEZERO to explicit requests since its
204 * normal use is to catch dereferences of NULL and many
205 * applications also treat pointers with a value of 0 as
206 * special and suddenly having address 0 contain useable
207 * memory would tend to confuse those applications.
209 map_addr
= vm_map_min(map
);
211 map_addr
+= PAGE_SIZE
;
213 map_addr
= vm_map_trunc_page(*addr
);
214 map_size
= vm_map_round_page(size
);
216 return(KERN_INVALID_ARGUMENT
);
219 result
= vm_map_enter(
226 (vm_object_offset_t
)0,
232 *addr
= CAST_DOWN(vm_offset_t
, map_addr
);
237 * mach_vm_deallocate -
238 * deallocates the specified range of addresses in the
239 * specified address map.
244 mach_vm_offset_t start
,
247 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
248 return(KERN_INVALID_ARGUMENT
);
250 if (size
== (mach_vm_offset_t
) 0)
251 return(KERN_SUCCESS
);
253 return(vm_map_remove(map
, vm_map_trunc_page(start
),
254 vm_map_round_page(start
+size
), VM_MAP_NO_FLAGS
));
259 * deallocates the specified range of addresses in the
260 * specified address map (limited to addresses the same
261 * size as the kernel).
265 register vm_map_t map
,
269 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
270 return(KERN_INVALID_ARGUMENT
);
272 if (size
== (vm_offset_t
) 0)
273 return(KERN_SUCCESS
);
275 return(vm_map_remove(map
, vm_map_trunc_page(start
),
276 vm_map_round_page(start
+size
), VM_MAP_NO_FLAGS
));
281 * Sets the inheritance of the specified range in the
287 mach_vm_offset_t start
,
289 vm_inherit_t new_inheritance
)
291 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
292 (new_inheritance
> VM_INHERIT_LAST_VALID
))
293 return(KERN_INVALID_ARGUMENT
);
298 return(vm_map_inherit(map
,
299 vm_map_trunc_page(start
),
300 vm_map_round_page(start
+size
),
306 * Sets the inheritance of the specified range in the
307 * specified map (range limited to addresses
311 register vm_map_t map
,
314 vm_inherit_t new_inheritance
)
316 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
317 (new_inheritance
> VM_INHERIT_LAST_VALID
))
318 return(KERN_INVALID_ARGUMENT
);
323 return(vm_map_inherit(map
,
324 vm_map_trunc_page(start
),
325 vm_map_round_page(start
+size
),
331 * Sets the protection of the specified range in the
338 mach_vm_offset_t start
,
340 boolean_t set_maximum
,
341 vm_prot_t new_protection
)
343 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
344 (new_protection
& ~(VM_PROT_ALL
| VM_PROT_COPY
)))
345 return(KERN_INVALID_ARGUMENT
);
350 return(vm_map_protect(map
,
351 vm_map_trunc_page(start
),
352 vm_map_round_page(start
+size
),
359 * Sets the protection of the specified range in the
360 * specified map. Addressability of the range limited
361 * to the same size as the kernel.
369 boolean_t set_maximum
,
370 vm_prot_t new_protection
)
372 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
373 (new_protection
& ~(VM_PROT_ALL
| VM_PROT_COPY
)))
374 return(KERN_INVALID_ARGUMENT
);
379 return(vm_map_protect(map
,
380 vm_map_trunc_page(start
),
381 vm_map_round_page(start
+size
),
387 * mach_vm_machine_attributes -
388 * Handle machine-specific attributes for a mapping, such
389 * as cachability, migrability, etc.
392 mach_vm_machine_attribute(
394 mach_vm_address_t addr
,
396 vm_machine_attribute_t attribute
,
397 vm_machine_attribute_val_t
* value
) /* IN/OUT */
399 if ((map
== VM_MAP_NULL
) || (addr
+ size
< addr
))
400 return(KERN_INVALID_ARGUMENT
);
405 return vm_map_machine_attribute(map
,
406 vm_map_trunc_page(addr
),
407 vm_map_round_page(addr
+size
),
413 * vm_machine_attribute -
414 * Handle machine-specific attributes for a mapping, such
415 * as cachability, migrability, etc. Limited addressability
416 * (same range limits as for the native kernel map).
419 vm_machine_attribute(
423 vm_machine_attribute_t attribute
,
424 vm_machine_attribute_val_t
* value
) /* IN/OUT */
426 if ((map
== VM_MAP_NULL
) || (addr
+ size
< addr
))
427 return(KERN_INVALID_ARGUMENT
);
432 return vm_map_machine_attribute(map
,
433 vm_map_trunc_page(addr
),
434 vm_map_round_page(addr
+size
),
441 * Read/copy a range from one address space and return it to the caller.
443 * It is assumed that the address for the returned memory is selected by
444 * the IPC implementation as part of receiving the reply to this call.
445 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
446 * that gets returned.
448 * JMM - because of mach_msg_type_number_t, this call is limited to a
449 * single 4GB region at this time.
455 mach_vm_address_t addr
,
458 mach_msg_type_number_t
*data_size
)
461 vm_map_copy_t ipc_address
;
463 if (map
== VM_MAP_NULL
)
464 return(KERN_INVALID_ARGUMENT
);
467 error
= vm_map_copyin(map
,
468 (vm_map_address_t
)addr
,
470 FALSE
, /* src_destroy */
473 if (KERN_SUCCESS
== error
) {
474 *data
= (pointer_t
) ipc_address
;
482 * Read/copy a range from one address space and return it to the caller.
483 * Limited addressability (same range limits as for the native kernel map).
485 * It is assumed that the address for the returned memory is selected by
486 * the IPC implementation as part of receiving the reply to this call.
487 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
488 * that gets returned.
496 mach_msg_type_number_t
*data_size
)
499 vm_map_copy_t ipc_address
;
501 if (map
== VM_MAP_NULL
)
502 return(KERN_INVALID_ARGUMENT
);
504 error
= vm_map_copyin(map
,
505 (vm_map_address_t
)addr
,
507 FALSE
, /* src_destroy */
510 if (KERN_SUCCESS
== error
) {
511 *data
= (pointer_t
) ipc_address
;
518 * mach_vm_read_list -
519 * Read/copy a list of address ranges from specified map.
521 * MIG does not know how to deal with a returned array of
522 * vm_map_copy_t structures, so we have to do the copyout
528 mach_vm_read_entry_t data_list
,
531 mach_msg_type_number_t i
;
535 if (map
== VM_MAP_NULL
||
536 count
> VM_MAP_ENTRY_MAX
)
537 return(KERN_INVALID_ARGUMENT
);
539 error
= KERN_SUCCESS
;
540 for(i
=0; i
<count
; i
++) {
541 vm_map_address_t map_addr
;
542 vm_map_size_t map_size
;
544 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
545 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
548 error
= vm_map_copyin(map
,
551 FALSE
, /* src_destroy */
553 if (KERN_SUCCESS
== error
) {
554 error
= vm_map_copyout(
558 if (KERN_SUCCESS
== error
) {
559 data_list
[i
].address
= map_addr
;
562 vm_map_copy_discard(copy
);
565 data_list
[i
].address
= (mach_vm_address_t
)0;
566 data_list
[i
].size
= (mach_vm_size_t
)0;
573 * Read/copy a list of address ranges from specified map.
575 * MIG does not know how to deal with a returned array of
576 * vm_map_copy_t structures, so we have to do the copyout
579 * The source and destination ranges are limited to those
580 * that can be described with a vm_address_t (i.e. same
581 * size map as the kernel).
583 * JMM - If the result of the copyout is an address range
584 * that cannot be described with a vm_address_t (i.e. the
585 * caller had a larger address space but used this call
586 * anyway), it will result in a truncated address being
587 * returned (and a likely confused caller).
593 vm_read_entry_t data_list
,
596 mach_msg_type_number_t i
;
600 if (map
== VM_MAP_NULL
||
601 count
> VM_MAP_ENTRY_MAX
)
602 return(KERN_INVALID_ARGUMENT
);
604 error
= KERN_SUCCESS
;
605 for(i
=0; i
<count
; i
++) {
606 vm_map_address_t map_addr
;
607 vm_map_size_t map_size
;
609 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
610 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
613 error
= vm_map_copyin(map
,
616 FALSE
, /* src_destroy */
618 if (KERN_SUCCESS
== error
) {
619 error
= vm_map_copyout(current_task()->map
,
622 if (KERN_SUCCESS
== error
) {
623 data_list
[i
].address
=
624 CAST_DOWN(vm_offset_t
, map_addr
);
627 vm_map_copy_discard(copy
);
630 data_list
[i
].address
= (mach_vm_address_t
)0;
631 data_list
[i
].size
= (mach_vm_size_t
)0;
637 * mach_vm_read_overwrite -
638 * Overwrite a range of the current map with data from the specified
641 * In making an assumption that the current thread is local, it is
642 * no longer cluster-safe without a fully supportive local proxy
643 * thread/task (but we don't support cluster's anymore so this is moot).
647 mach_vm_read_overwrite(
649 mach_vm_address_t address
,
651 mach_vm_address_t data
,
652 mach_vm_size_t
*data_size
)
657 if (map
== VM_MAP_NULL
)
658 return(KERN_INVALID_ARGUMENT
);
660 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
661 (vm_map_size_t
)size
, FALSE
, ©
);
663 if (KERN_SUCCESS
== error
) {
664 error
= vm_map_copy_overwrite(current_thread()->map
,
665 (vm_map_address_t
)data
,
667 if (KERN_SUCCESS
== error
) {
671 vm_map_copy_discard(copy
);
677 * vm_read_overwrite -
678 * Overwrite a range of the current map with data from the specified
681 * This routine adds the additional limitation that the source and
682 * destination ranges must be describable with vm_address_t values
683 * (i.e. the same size address spaces as the kernel, or at least the
684 * the ranges are in that first portion of the respective address
691 vm_address_t address
,
694 vm_size_t
*data_size
)
699 if (map
== VM_MAP_NULL
)
700 return(KERN_INVALID_ARGUMENT
);
702 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
703 (vm_map_size_t
)size
, FALSE
, ©
);
705 if (KERN_SUCCESS
== error
) {
706 error
= vm_map_copy_overwrite(current_thread()->map
,
707 (vm_map_address_t
)data
,
709 if (KERN_SUCCESS
== error
) {
713 vm_map_copy_discard(copy
);
721 * Overwrite the specified address range with the data provided
722 * (from the current map).
727 mach_vm_address_t address
,
729 __unused mach_msg_type_number_t size
)
731 if (map
== VM_MAP_NULL
)
732 return KERN_INVALID_ARGUMENT
;
734 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
735 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
740 * Overwrite the specified address range with the data provided
741 * (from the current map).
743 * The addressability of the range of addresses to overwrite is
744 * limited bu the use of a vm_address_t (same size as kernel map).
745 * Either the target map is also small, or the range is in the
746 * low addresses within it.
751 vm_address_t address
,
753 __unused mach_msg_type_number_t size
)
755 if (map
== VM_MAP_NULL
)
756 return KERN_INVALID_ARGUMENT
;
758 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
759 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
764 * Overwrite one range of the specified map with the contents of
765 * another range within that same map (i.e. both address ranges
771 mach_vm_address_t source_address
,
773 mach_vm_address_t dest_address
)
778 if (map
== VM_MAP_NULL
)
779 return KERN_INVALID_ARGUMENT
;
781 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
782 (vm_map_size_t
)size
, FALSE
, ©
);
784 if (KERN_SUCCESS
== kr
) {
785 kr
= vm_map_copy_overwrite(map
,
786 (vm_map_address_t
)dest_address
,
787 copy
, FALSE
/* interruptible XXX */);
789 if (KERN_SUCCESS
!= kr
)
790 vm_map_copy_discard(copy
);
798 vm_address_t source_address
,
800 vm_address_t dest_address
)
805 if (map
== VM_MAP_NULL
)
806 return KERN_INVALID_ARGUMENT
;
808 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
809 (vm_map_size_t
)size
, FALSE
, ©
);
811 if (KERN_SUCCESS
== kr
) {
812 kr
= vm_map_copy_overwrite(map
,
813 (vm_map_address_t
)dest_address
,
814 copy
, FALSE
/* interruptible XXX */);
816 if (KERN_SUCCESS
!= kr
)
817 vm_map_copy_discard(copy
);
824 * Map some range of an object into an address space.
826 * The object can be one of several types of objects:
827 * NULL - anonymous memory
828 * a named entry - a range within another address space
829 * or a range within a memory object
830 * a whole memory object
836 mach_vm_offset_t
*address
,
837 mach_vm_size_t initial_size
,
838 mach_vm_offset_t mask
,
841 vm_object_offset_t offset
,
843 vm_prot_t cur_protection
,
844 vm_prot_t max_protection
,
845 vm_inherit_t inheritance
)
847 /* filter out any kernel-only flags */
848 if (flags
& ~VM_FLAGS_USER_MAP
)
849 return KERN_INVALID_ARGUMENT
;
851 return vm_map_enter_mem_object(target_map
,
865 /* legacy interface */
869 vm_offset_t
*address
,
874 vm_object_offset_t offset
,
876 vm_prot_t cur_protection
,
877 vm_prot_t max_protection
,
878 vm_inherit_t inheritance
)
880 mach_vm_address_t map_addr
;
881 mach_vm_size_t map_size
;
882 mach_vm_offset_t map_mask
;
885 map_addr
= (mach_vm_address_t
)*address
;
886 map_size
= (mach_vm_size_t
)size
;
887 map_mask
= (mach_vm_offset_t
)mask
;
889 kr
= mach_vm_map(target_map
, &map_addr
, map_size
, map_mask
, flags
,
891 cur_protection
, max_protection
, inheritance
);
892 *address
= CAST_DOWN(vm_address_t
, map_addr
);
896 /* temporary, until world build */
900 vm_offset_t
*address
,
907 vm_prot_t cur_protection
,
908 vm_prot_t max_protection
,
909 vm_inherit_t inheritance
)
911 mach_vm_address_t map_addr
;
912 mach_vm_size_t map_size
;
913 mach_vm_offset_t map_mask
;
914 vm_object_offset_t obj_offset
;
917 map_addr
= (mach_vm_address_t
)*address
;
918 map_size
= (mach_vm_size_t
)size
;
919 map_mask
= (mach_vm_offset_t
)mask
;
920 obj_offset
= (vm_object_offset_t
)offset
;
922 kr
= mach_vm_map(target_map
, &map_addr
, map_size
, map_mask
, flags
,
923 port
, obj_offset
, copy
,
924 cur_protection
, max_protection
, inheritance
);
925 *address
= CAST_DOWN(vm_address_t
, map_addr
);
931 * Remap a range of memory from one task into another,
932 * to another address range within the same task, or
933 * over top of itself (with altered permissions and/or
934 * as an in-place copy of itself).
940 mach_vm_offset_t
*address
,
942 mach_vm_offset_t mask
,
945 mach_vm_offset_t memory_address
,
947 vm_prot_t
*cur_protection
,
948 vm_prot_t
*max_protection
,
949 vm_inherit_t inheritance
)
951 vm_map_offset_t map_addr
;
954 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
)
955 return KERN_INVALID_ARGUMENT
;
957 map_addr
= (vm_map_offset_t
)*address
;
959 kr
= vm_map_remap(target_map
,
976 * Remap a range of memory from one task into another,
977 * to another address range within the same task, or
978 * over top of itself (with altered permissions and/or
979 * as an in-place copy of itself).
981 * The addressability of the source and target address
982 * range is limited by the size of vm_address_t (in the
988 vm_offset_t
*address
,
993 vm_offset_t memory_address
,
995 vm_prot_t
*cur_protection
,
996 vm_prot_t
*max_protection
,
997 vm_inherit_t inheritance
)
999 vm_map_offset_t map_addr
;
1002 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
)
1003 return KERN_INVALID_ARGUMENT
;
1005 map_addr
= (vm_map_offset_t
)*address
;
1007 kr
= vm_map_remap(target_map
,
1018 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1023 * NOTE: these routine (and this file) will no longer require mach_host_server.h
1024 * when mach_vm_wire and vm_wire are changed to use ledgers.
1026 #include <mach/mach_host_server.h>
1029 * Specify that the range of the virtual address space
1030 * of the target task must not cause page faults for
1031 * the indicated accesses.
1033 * [ To unwire the pages, specify VM_PROT_NONE. ]
1037 host_priv_t host_priv
,
1039 mach_vm_offset_t start
,
1040 mach_vm_size_t size
,
1045 if (host_priv
== HOST_PRIV_NULL
)
1046 return KERN_INVALID_HOST
;
1048 assert(host_priv
== &realhost
);
1050 if (map
== VM_MAP_NULL
)
1051 return KERN_INVALID_TASK
;
1053 if (access
& ~VM_PROT_ALL
)
1054 return KERN_INVALID_ARGUMENT
;
1056 if (access
!= VM_PROT_NONE
) {
1057 rc
= vm_map_wire(map
, vm_map_trunc_page(start
),
1058 vm_map_round_page(start
+size
), access
, TRUE
);
1060 rc
= vm_map_unwire(map
, vm_map_trunc_page(start
),
1061 vm_map_round_page(start
+size
), TRUE
);
1068 * Specify that the range of the virtual address space
1069 * of the target task must not cause page faults for
1070 * the indicated accesses.
1072 * [ To unwire the pages, specify VM_PROT_NONE. ]
1076 host_priv_t host_priv
,
1077 register vm_map_t map
,
1084 if (host_priv
== HOST_PRIV_NULL
)
1085 return KERN_INVALID_HOST
;
1087 assert(host_priv
== &realhost
);
1089 if (map
== VM_MAP_NULL
)
1090 return KERN_INVALID_TASK
;
1092 if ((access
& ~VM_PROT_ALL
) || (start
+ size
< start
))
1093 return KERN_INVALID_ARGUMENT
;
1097 } else if (access
!= VM_PROT_NONE
) {
1098 rc
= vm_map_wire(map
, vm_map_trunc_page(start
),
1099 vm_map_round_page(start
+size
), access
, TRUE
);
1101 rc
= vm_map_unwire(map
, vm_map_trunc_page(start
),
1102 vm_map_round_page(start
+size
), TRUE
);
1110 * Synchronises the memory range specified with its backing store
1111 * image by either flushing or cleaning the contents to the appropriate
1114 * interpretation of sync_flags
1115 * VM_SYNC_INVALIDATE - discard pages, only return precious
1118 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1119 * - discard pages, write dirty or precious
1120 * pages back to memory manager.
1122 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1123 * - write dirty or precious pages back to
1124 * the memory manager.
1126 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1127 * is a hole in the region, and we would
1128 * have returned KERN_SUCCESS, return
1129 * KERN_INVALID_ADDRESS instead.
1132 * KERN_INVALID_TASK Bad task parameter
1133 * KERN_INVALID_ARGUMENT both sync and async were specified.
1134 * KERN_SUCCESS The usual.
1135 * KERN_INVALID_ADDRESS There was a hole in the region.
1141 mach_vm_address_t address
,
1142 mach_vm_size_t size
,
1143 vm_sync_t sync_flags
)
1146 if (map
== VM_MAP_NULL
)
1147 return(KERN_INVALID_TASK
);
1149 return vm_map_msync(map
, (vm_map_address_t
)address
,
1150 (vm_map_size_t
)size
, sync_flags
);
1156 * Synchronises the memory range specified with its backing store
1157 * image by either flushing or cleaning the contents to the appropriate
1160 * interpretation of sync_flags
1161 * VM_SYNC_INVALIDATE - discard pages, only return precious
1164 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1165 * - discard pages, write dirty or precious
1166 * pages back to memory manager.
1168 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1169 * - write dirty or precious pages back to
1170 * the memory manager.
1172 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1173 * is a hole in the region, and we would
1174 * have returned KERN_SUCCESS, return
1175 * KERN_INVALID_ADDRESS instead.
1177 * The addressability of the range is limited to that which can
1178 * be described by a vm_address_t.
1181 * KERN_INVALID_TASK Bad task parameter
1182 * KERN_INVALID_ARGUMENT both sync and async were specified.
1183 * KERN_SUCCESS The usual.
1184 * KERN_INVALID_ADDRESS There was a hole in the region.
1190 vm_address_t address
,
1192 vm_sync_t sync_flags
)
1195 if (map
== VM_MAP_NULL
)
1196 return(KERN_INVALID_TASK
);
1198 return vm_map_msync(map
, (vm_map_address_t
)address
,
1199 (vm_map_size_t
)size
, sync_flags
);
1204 * mach_vm_behavior_set
1206 * Sets the paging behavior attribute for the specified range
1207 * in the specified map.
1209 * This routine will fail with KERN_INVALID_ADDRESS if any address
1210 * in [start,start+size) is not a valid allocated memory region.
1213 mach_vm_behavior_set(
1215 mach_vm_offset_t start
,
1216 mach_vm_size_t size
,
1217 vm_behavior_t new_behavior
)
1219 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
1220 return(KERN_INVALID_ARGUMENT
);
1223 return KERN_SUCCESS
;
1225 return(vm_map_behavior_set(map
, vm_map_trunc_page(start
),
1226 vm_map_round_page(start
+size
), new_behavior
));
1232 * Sets the paging behavior attribute for the specified range
1233 * in the specified map.
1235 * This routine will fail with KERN_INVALID_ADDRESS if any address
1236 * in [start,start+size) is not a valid allocated memory region.
1238 * This routine is potentially limited in addressibility by the
1239 * use of vm_offset_t (if the map provided is larger than the
1247 vm_behavior_t new_behavior
)
1249 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
1250 return(KERN_INVALID_ARGUMENT
);
1253 return KERN_SUCCESS
;
1255 return(vm_map_behavior_set(map
, vm_map_trunc_page(start
),
1256 vm_map_round_page(start
+size
), new_behavior
));
1262 * User call to obtain information about a region in
1263 * a task's address map. Currently, only one flavor is
1266 * XXX The reserved and behavior fields cannot be filled
1267 * in until the vm merge from the IK is completed, and
1268 * vm_reserve is implemented.
1270 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1276 mach_vm_offset_t
*address
, /* IN/OUT */
1277 mach_vm_size_t
*size
, /* OUT */
1278 vm_region_flavor_t flavor
, /* IN */
1279 vm_region_info_t info
, /* OUT */
1280 mach_msg_type_number_t
*count
, /* IN/OUT */
1281 mach_port_t
*object_name
) /* OUT */
1283 vm_map_offset_t map_addr
;
1284 vm_map_size_t map_size
;
1287 if (VM_MAP_NULL
== map
)
1288 return KERN_INVALID_ARGUMENT
;
1290 map_addr
= (vm_map_offset_t
)*address
;
1291 map_size
= (vm_map_size_t
)*size
;
1293 /* legacy conversion */
1294 if (VM_REGION_BASIC_INFO
== flavor
)
1295 flavor
= VM_REGION_BASIC_INFO_64
;
1297 kr
= vm_map_region(map
,
1298 &map_addr
, &map_size
,
1299 flavor
, info
, count
,
1302 *address
= map_addr
;
1308 * vm_region_64 and vm_region:
1310 * User call to obtain information about a region in
1311 * a task's address map. Currently, only one flavor is
1314 * XXX The reserved and behavior fields cannot be filled
1315 * in until the vm merge from the IK is completed, and
1316 * vm_reserve is implemented.
1318 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1324 vm_offset_t
*address
, /* IN/OUT */
1325 vm_size_t
*size
, /* OUT */
1326 vm_region_flavor_t flavor
, /* IN */
1327 vm_region_info_t info
, /* OUT */
1328 mach_msg_type_number_t
*count
, /* IN/OUT */
1329 mach_port_t
*object_name
) /* OUT */
1331 vm_map_offset_t map_addr
;
1332 vm_map_size_t map_size
;
1335 if (VM_MAP_NULL
== map
)
1336 return KERN_INVALID_ARGUMENT
;
1338 map_addr
= (vm_map_offset_t
)*address
;
1339 map_size
= (vm_map_size_t
)*size
;
1341 /* legacy conversion */
1342 if (VM_REGION_BASIC_INFO
== flavor
)
1343 flavor
= VM_REGION_BASIC_INFO_64
;
1345 kr
= vm_map_region(map
,
1346 &map_addr
, &map_size
,
1347 flavor
, info
, count
,
1350 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1351 *size
= CAST_DOWN(vm_size_t
, map_size
);
1353 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1354 return KERN_INVALID_ADDRESS
;
1361 vm_address_t
*address
, /* IN/OUT */
1362 vm_size_t
*size
, /* OUT */
1363 vm_region_flavor_t flavor
, /* IN */
1364 vm_region_info_t info
, /* OUT */
1365 mach_msg_type_number_t
*count
, /* IN/OUT */
1366 mach_port_t
*object_name
) /* OUT */
1368 vm_map_address_t map_addr
;
1369 vm_map_size_t map_size
;
1372 if (VM_MAP_NULL
== map
)
1373 return KERN_INVALID_ARGUMENT
;
1375 map_addr
= (vm_map_address_t
)*address
;
1376 map_size
= (vm_map_size_t
)*size
;
1378 kr
= vm_map_region(map
,
1379 &map_addr
, &map_size
,
1380 flavor
, info
, count
,
1383 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1384 *size
= CAST_DOWN(vm_size_t
, map_size
);
1386 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1387 return KERN_INVALID_ADDRESS
;
1392 * vm_region_recurse: A form of vm_region which follows the
1393 * submaps in a target map
1397 mach_vm_region_recurse(
1399 mach_vm_address_t
*address
,
1400 mach_vm_size_t
*size
,
1402 vm_region_recurse_info_t info
,
1403 mach_msg_type_number_t
*infoCnt
)
1405 vm_map_address_t map_addr
;
1406 vm_map_size_t map_size
;
1409 if (VM_MAP_NULL
== map
)
1410 return KERN_INVALID_ARGUMENT
;
1412 map_addr
= (vm_map_address_t
)*address
;
1413 map_size
= (vm_map_size_t
)*size
;
1415 kr
= vm_map_region_recurse_64(
1420 (vm_region_submap_info_64_t
)info
,
1423 *address
= map_addr
;
1429 * vm_region_recurse: A form of vm_region which follows the
1430 * submaps in a target map
1434 vm_region_recurse_64(
1436 vm_address_t
*address
,
1439 vm_region_recurse_info_64_t info
,
1440 mach_msg_type_number_t
*infoCnt
)
1442 vm_map_address_t map_addr
;
1443 vm_map_size_t map_size
;
1446 if (VM_MAP_NULL
== map
)
1447 return KERN_INVALID_ARGUMENT
;
1449 map_addr
= (vm_map_address_t
)*address
;
1450 map_size
= (vm_map_size_t
)*size
;
1452 kr
= vm_map_region_recurse_64(
1457 (vm_region_submap_info_64_t
)info
,
1460 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1461 *size
= CAST_DOWN(vm_size_t
, map_size
);
1463 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1464 return KERN_INVALID_ADDRESS
;
1471 vm_offset_t
*address
, /* IN/OUT */
1472 vm_size_t
*size
, /* OUT */
1473 natural_t
*depth
, /* IN/OUT */
1474 vm_region_recurse_info_t info32
, /* IN/OUT */
1475 mach_msg_type_number_t
*infoCnt
) /* IN/OUT */
1477 vm_region_submap_info_data_64_t info64
;
1478 vm_region_submap_info_t info
;
1479 vm_map_address_t map_addr
;
1480 vm_map_size_t map_size
;
1483 if (VM_MAP_NULL
== map
|| *infoCnt
< VM_REGION_SUBMAP_INFO_COUNT
)
1484 return KERN_INVALID_ARGUMENT
;
1487 map_addr
= (vm_map_address_t
)*address
;
1488 map_size
= (vm_map_size_t
)*size
;
1489 info
= (vm_region_submap_info_t
)info32
;
1490 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT_64
;
1492 kr
= vm_map_region_recurse_64(map
, &map_addr
,&map_size
,
1493 depth
, &info64
, infoCnt
);
1495 info
->protection
= info64
.protection
;
1496 info
->max_protection
= info64
.max_protection
;
1497 info
->inheritance
= info64
.inheritance
;
1498 info
->offset
= (uint32_t)info64
.offset
; /* trouble-maker */
1499 info
->user_tag
= info64
.user_tag
;
1500 info
->pages_resident
= info64
.pages_resident
;
1501 info
->pages_shared_now_private
= info64
.pages_shared_now_private
;
1502 info
->pages_swapped_out
= info64
.pages_swapped_out
;
1503 info
->pages_dirtied
= info64
.pages_dirtied
;
1504 info
->ref_count
= info64
.ref_count
;
1505 info
->shadow_depth
= info64
.shadow_depth
;
1506 info
->external_pager
= info64
.external_pager
;
1507 info
->share_mode
= info64
.share_mode
;
1508 info
->is_submap
= info64
.is_submap
;
1509 info
->behavior
= info64
.behavior
;
1510 info
->object_id
= info64
.object_id
;
1511 info
->user_wired_count
= info64
.user_wired_count
;
1513 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1514 *size
= CAST_DOWN(vm_size_t
, map_size
);
1515 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT
;
1517 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1518 return KERN_INVALID_ADDRESS
;
1523 mach_vm_purgable_control(
1525 mach_vm_offset_t address
,
1526 vm_purgable_t control
,
1529 if (VM_MAP_NULL
== map
)
1530 return KERN_INVALID_ARGUMENT
;
1532 return vm_map_purgable_control(map
,
1533 vm_map_trunc_page(address
),
1539 vm_purgable_control(
1541 vm_offset_t address
,
1542 vm_purgable_t control
,
1545 if (VM_MAP_NULL
== map
)
1546 return KERN_INVALID_ARGUMENT
;
1548 return vm_map_purgable_control(map
,
1549 vm_map_trunc_page(address
),
1556 * Ordinarily, the right to allocate CPM is restricted
1557 * to privileged applications (those that can gain access
1558 * to the host priv port). Set this variable to zero if
1559 * you want to let any application allocate CPM.
1561 unsigned int vm_allocate_cpm_privileged
= 0;
1564 * Allocate memory in the specified map, with the caveat that
1565 * the memory is physically contiguous. This call may fail
1566 * if the system can't find sufficient contiguous memory.
1567 * This call may cause or lead to heart-stopping amounts of
1570 * Memory obtained from this call should be freed in the
1571 * normal way, viz., via vm_deallocate.
1575 host_priv_t host_priv
,
1581 vm_map_address_t map_addr
;
1582 vm_map_size_t map_size
;
1585 if (vm_allocate_cpm_privileged
&& HOST_PRIV_NULL
== host_priv
)
1586 return KERN_INVALID_HOST
;
1588 if (VM_MAP_NULL
== map
)
1589 return KERN_INVALID_ARGUMENT
;
1591 map_addr
= (vm_map_address_t
)*addr
;
1592 map_size
= (vm_map_size_t
)size
;
1594 kr
= vm_map_enter_cpm(map
,
1599 *addr
= CAST_DOWN(vm_address_t
, map_addr
);
1607 mach_vm_offset_t offset
,
1611 if (VM_MAP_NULL
== map
)
1612 return KERN_INVALID_ARGUMENT
;
1614 return vm_map_page_info(map
,
1615 vm_map_trunc_page(offset
),
1616 disposition
, ref_count
);
1626 if (VM_MAP_NULL
== map
)
1627 return KERN_INVALID_ARGUMENT
;
1629 return vm_map_page_info(map
,
1630 vm_map_trunc_page(offset
),
1631 disposition
, ref_count
);
1634 /* map a (whole) upl into an address space */
1639 vm_offset_t
*dst_addr
)
1641 vm_map_offset_t map_addr
;
1644 if (VM_MAP_NULL
== map
)
1645 return KERN_INVALID_ARGUMENT
;
1647 kr
= vm_map_enter_upl(map
, upl
, &map_addr
);
1648 *dst_addr
= CAST_DOWN(vm_offset_t
, map_addr
);
1657 if (VM_MAP_NULL
== map
)
1658 return KERN_INVALID_ARGUMENT
;
1660 return (vm_map_remove_upl(map
, upl
));
1663 /* Retrieve a upl for an object underlying an address range in a map */
1668 vm_map_offset_t map_offset
,
1669 upl_size_t
*upl_size
,
1671 upl_page_info_array_t page_list
,
1672 unsigned int *count
,
1674 int force_data_sync
)
1679 if (VM_MAP_NULL
== map
)
1680 return KERN_INVALID_ARGUMENT
;
1682 map_flags
= *flags
& ~UPL_NOZEROFILL
;
1683 if (force_data_sync
)
1684 map_flags
|= UPL_FORCE_DATA_SYNC
;
1686 kr
= vm_map_create_upl(map
,
1694 *flags
= (map_flags
& ~UPL_FORCE_DATA_SYNC
);
1699 * mach_make_memory_entry_64
1701 * Think of it as a two-stage vm_remap() operation. First
1702 * you get a handle. Second, you get map that handle in
1703 * somewhere else. Rather than doing it all at once (and
1704 * without needing access to the other whole map).
1708 mach_make_memory_entry_64(
1709 vm_map_t target_map
,
1710 memory_object_size_t
*size
,
1711 memory_object_offset_t offset
,
1712 vm_prot_t permission
,
1713 ipc_port_t
*object_handle
,
1714 ipc_port_t parent_handle
)
1716 vm_map_version_t version
;
1717 vm_named_entry_t parent_entry
;
1718 vm_named_entry_t user_entry
;
1719 ipc_port_t user_handle
;
1723 /* needed for call to vm_map_lookup_locked */
1725 vm_object_offset_t obj_off
;
1727 struct vm_object_fault_info fault_info
;
1729 vm_object_t shadow_object
;
1731 /* needed for direct map entry manipulation */
1732 vm_map_entry_t map_entry
;
1733 vm_map_entry_t next_entry
;
1735 vm_map_t original_map
= target_map
;
1736 vm_map_size_t total_size
;
1737 vm_map_size_t map_size
;
1738 vm_map_offset_t map_offset
;
1739 vm_map_offset_t local_offset
;
1740 vm_object_size_t mappable_size
;
1742 unsigned int access
;
1743 vm_prot_t protections
;
1744 unsigned int wimg_mode
;
1745 boolean_t cache_attr
= FALSE
;
1747 if (((permission
& 0x00FF0000) &
1749 MAP_MEM_NAMED_CREATE
|
1751 MAP_MEM_NAMED_REUSE
))) {
1753 * Unknown flag: reject for forward compatibility.
1755 return KERN_INVALID_VALUE
;
1758 if (parent_handle
!= IP_NULL
&&
1759 ip_kotype(parent_handle
) == IKOT_NAMED_ENTRY
) {
1760 parent_entry
= (vm_named_entry_t
) parent_handle
->ip_kobject
;
1762 parent_entry
= NULL
;
1765 protections
= permission
& VM_PROT_ALL
;
1766 access
= GET_MAP_MEM(permission
);
1768 user_handle
= IP_NULL
;
1771 map_offset
= vm_map_trunc_page(offset
);
1772 map_size
= vm_map_round_page(*size
);
1774 if (permission
& MAP_MEM_ONLY
) {
1775 boolean_t parent_is_object
;
1777 if (parent_entry
== NULL
) {
1778 return KERN_INVALID_ARGUMENT
;
1781 parent_is_object
= !(parent_entry
->is_sub_map
|| parent_entry
->is_pager
);
1782 object
= parent_entry
->backing
.object
;
1783 if(parent_is_object
&& object
!= VM_OBJECT_NULL
)
1784 wimg_mode
= object
->wimg_bits
;
1786 wimg_mode
= VM_WIMG_DEFAULT
;
1787 if((access
!= GET_MAP_MEM(parent_entry
->protection
)) &&
1788 !(parent_entry
->protection
& VM_PROT_WRITE
)) {
1789 return KERN_INVALID_RIGHT
;
1791 if(access
== MAP_MEM_IO
) {
1792 SET_MAP_MEM(access
, parent_entry
->protection
);
1793 wimg_mode
= VM_WIMG_IO
;
1794 } else if (access
== MAP_MEM_COPYBACK
) {
1795 SET_MAP_MEM(access
, parent_entry
->protection
);
1796 wimg_mode
= VM_WIMG_DEFAULT
;
1797 } else if (access
== MAP_MEM_WTHRU
) {
1798 SET_MAP_MEM(access
, parent_entry
->protection
);
1799 wimg_mode
= VM_WIMG_WTHRU
;
1800 } else if (access
== MAP_MEM_WCOMB
) {
1801 SET_MAP_MEM(access
, parent_entry
->protection
);
1802 wimg_mode
= VM_WIMG_WCOMB
;
1804 if(parent_is_object
&& object
&&
1805 (access
!= MAP_MEM_NOOP
) &&
1806 (!(object
->nophyscache
))) {
1807 if(object
->wimg_bits
!= wimg_mode
) {
1809 if ((wimg_mode
== VM_WIMG_IO
)
1810 || (wimg_mode
== VM_WIMG_WCOMB
))
1814 vm_object_lock(object
);
1815 vm_object_paging_wait(object
, THREAD_UNINT
);
1816 object
->wimg_bits
= wimg_mode
;
1817 queue_iterate(&object
->memq
,
1818 p
, vm_page_t
, listq
) {
1819 if (!p
->fictitious
) {
1821 pmap_disconnect(p
->phys_page
);
1823 pmap_sync_page_attributes_phys(p
->phys_page
);
1826 vm_object_unlock(object
);
1830 *object_handle
= IP_NULL
;
1831 return KERN_SUCCESS
;
1834 if(permission
& MAP_MEM_NAMED_CREATE
) {
1835 kr
= mach_memory_entry_allocate(&user_entry
, &user_handle
);
1836 if (kr
!= KERN_SUCCESS
) {
1837 return KERN_FAILURE
;
1841 * Force the creation of the VM object now.
1843 if (map_size
> (vm_map_size_t
) VM_MAX_ADDRESS
) {
1845 * LP64todo - for now, we can only allocate 4GB
1846 * internal objects because the default pager can't
1847 * page bigger ones. Remove this when it can.
1853 object
= vm_object_allocate(map_size
);
1854 assert(object
!= VM_OBJECT_NULL
);
1856 if (permission
& MAP_MEM_PURGABLE
) {
1857 if (! (permission
& VM_PROT_WRITE
)) {
1858 /* if we can't write, we can't purge */
1859 vm_object_deallocate(object
);
1860 kr
= KERN_INVALID_ARGUMENT
;
1863 object
->purgable
= VM_PURGABLE_NONVOLATILE
;
1867 * The VM object is brand new and nobody else knows about it,
1868 * so we don't need to lock it.
1871 wimg_mode
= object
->wimg_bits
;
1872 if (access
== MAP_MEM_IO
) {
1873 wimg_mode
= VM_WIMG_IO
;
1874 } else if (access
== MAP_MEM_COPYBACK
) {
1875 wimg_mode
= VM_WIMG_DEFAULT
;
1876 } else if (access
== MAP_MEM_WTHRU
) {
1877 wimg_mode
= VM_WIMG_WTHRU
;
1878 } else if (access
== MAP_MEM_WCOMB
) {
1879 wimg_mode
= VM_WIMG_WCOMB
;
1881 if (access
!= MAP_MEM_NOOP
) {
1882 object
->wimg_bits
= wimg_mode
;
1884 /* the object has no pages, so no WIMG bits to update here */
1888 * We use this path when we want to make sure that
1889 * nobody messes with the object (coalesce, for
1890 * example) before we map it.
1891 * We might want to use these objects for transposition via
1892 * vm_object_transpose() too, so we don't want any copy or
1893 * shadow objects either...
1895 object
->copy_strategy
= MEMORY_OBJECT_COPY_NONE
;
1897 user_entry
->backing
.object
= object
;
1898 user_entry
->internal
= TRUE
;
1899 user_entry
->is_sub_map
= FALSE
;
1900 user_entry
->is_pager
= FALSE
;
1901 user_entry
->offset
= 0;
1902 user_entry
->protection
= protections
;
1903 SET_MAP_MEM(access
, user_entry
->protection
);
1904 user_entry
->size
= map_size
;
1906 /* user_object pager and internal fields are not used */
1907 /* when the object field is filled in. */
1909 *size
= CAST_DOWN(vm_size_t
, map_size
);
1910 *object_handle
= user_handle
;
1911 return KERN_SUCCESS
;
1914 if (parent_entry
== NULL
||
1915 (permission
& MAP_MEM_NAMED_REUSE
)) {
1917 /* Create a named object based on address range within the task map */
1918 /* Go find the object at given address */
1920 if (target_map
== VM_MAP_NULL
) {
1921 return KERN_INVALID_TASK
;
1925 vm_map_lock_read(target_map
);
1927 /* get the object associated with the target address */
1928 /* note we check the permission of the range against */
1929 /* that requested by the caller */
1931 kr
= vm_map_lookup_locked(&target_map
, map_offset
,
1932 protections
, OBJECT_LOCK_EXCLUSIVE
, &version
,
1933 &object
, &obj_off
, &prot
, &wired
,
1936 if (kr
!= KERN_SUCCESS
) {
1937 vm_map_unlock_read(target_map
);
1940 if (((prot
& protections
) != protections
)
1941 || (object
== kernel_object
)) {
1942 kr
= KERN_INVALID_RIGHT
;
1943 vm_object_unlock(object
);
1944 vm_map_unlock_read(target_map
);
1945 if(real_map
!= target_map
)
1946 vm_map_unlock_read(real_map
);
1947 if(object
== kernel_object
) {
1948 printf("Warning: Attempt to create a named"
1949 " entry from the kernel_object\n");
1954 /* We have an object, now check to see if this object */
1955 /* is suitable. If not, create a shadow and share that */
1958 * We have to unlock the VM object to avoid deadlocking with
1959 * a VM map lock (the lock ordering is map, the object), if we
1960 * need to modify the VM map to create a shadow object. Since
1961 * we might release the VM map lock below anyway, we have
1962 * to release the VM map lock now.
1963 * XXX FBDP There must be a way to avoid this double lookup...
1965 * Take an extra reference on the VM object to make sure it's
1966 * not going to disappear.
1968 vm_object_reference_locked(object
); /* extra ref to hold obj */
1969 vm_object_unlock(object
);
1971 local_map
= original_map
;
1972 local_offset
= map_offset
;
1973 if(target_map
!= local_map
) {
1974 vm_map_unlock_read(target_map
);
1975 if(real_map
!= target_map
)
1976 vm_map_unlock_read(real_map
);
1977 vm_map_lock_read(local_map
);
1978 target_map
= local_map
;
1979 real_map
= local_map
;
1982 if(!vm_map_lookup_entry(local_map
,
1983 local_offset
, &map_entry
)) {
1984 kr
= KERN_INVALID_ARGUMENT
;
1985 vm_map_unlock_read(target_map
);
1986 if(real_map
!= target_map
)
1987 vm_map_unlock_read(real_map
);
1988 vm_object_deallocate(object
); /* release extra ref */
1989 object
= VM_OBJECT_NULL
;
1992 if(!(map_entry
->is_sub_map
)) {
1993 if(map_entry
->object
.vm_object
!= object
) {
1994 kr
= KERN_INVALID_ARGUMENT
;
1995 vm_map_unlock_read(target_map
);
1996 if(real_map
!= target_map
)
1997 vm_map_unlock_read(real_map
);
1998 vm_object_deallocate(object
); /* release extra ref */
1999 object
= VM_OBJECT_NULL
;
2006 local_map
= map_entry
->object
.sub_map
;
2008 vm_map_lock_read(local_map
);
2009 vm_map_unlock_read(tmap
);
2010 target_map
= local_map
;
2011 real_map
= local_map
;
2012 local_offset
= local_offset
- map_entry
->vme_start
;
2013 local_offset
+= map_entry
->offset
;
2018 * We found the VM map entry, lock the VM object again.
2020 vm_object_lock(object
);
2021 if(map_entry
->wired_count
) {
2022 /* JMM - The check below should be reworked instead. */
2023 object
->true_share
= TRUE
;
2025 if(((map_entry
->max_protection
) & protections
) != protections
) {
2026 kr
= KERN_INVALID_RIGHT
;
2027 vm_object_unlock(object
);
2028 vm_map_unlock_read(target_map
);
2029 if(real_map
!= target_map
)
2030 vm_map_unlock_read(real_map
);
2031 vm_object_deallocate(object
);
2032 object
= VM_OBJECT_NULL
;
2036 mappable_size
= fault_info
.hi_offset
- obj_off
;
2037 total_size
= map_entry
->vme_end
- map_entry
->vme_start
;
2038 if(map_size
> mappable_size
) {
2039 /* try to extend mappable size if the entries */
2040 /* following are from the same object and are */
2042 next_entry
= map_entry
->vme_next
;
2043 /* lets see if the next map entry is still */
2044 /* pointing at this object and is contiguous */
2045 while(map_size
> mappable_size
) {
2046 if((next_entry
->object
.vm_object
== object
) &&
2047 (next_entry
->vme_start
==
2048 next_entry
->vme_prev
->vme_end
) &&
2049 (next_entry
->offset
==
2050 next_entry
->vme_prev
->offset
+
2051 (next_entry
->vme_prev
->vme_end
-
2052 next_entry
->vme_prev
->vme_start
))) {
2053 if(((next_entry
->max_protection
)
2054 & protections
) != protections
) {
2057 if (next_entry
->needs_copy
!=
2058 map_entry
->needs_copy
)
2060 mappable_size
+= next_entry
->vme_end
2061 - next_entry
->vme_start
;
2062 total_size
+= next_entry
->vme_end
2063 - next_entry
->vme_start
;
2064 next_entry
= next_entry
->vme_next
;
2072 if(object
->internal
) {
2073 /* vm_map_lookup_locked will create a shadow if */
2074 /* needs_copy is set but does not check for the */
2075 /* other two conditions shown. It is important to */
2076 /* set up an object which will not be pulled from */
2079 if ((map_entry
->needs_copy
|| object
->shadowed
||
2080 (object
->size
> total_size
))
2081 && !object
->true_share
) {
2083 * We have to unlock the VM object before
2084 * trying to upgrade the VM map lock, to
2085 * honor lock ordering (map then object).
2086 * Otherwise, we would deadlock if another
2087 * thread holds a read lock on the VM map and
2088 * is trying to acquire the VM object's lock.
2089 * We still hold an extra reference on the
2090 * VM object, guaranteeing that it won't
2093 vm_object_unlock(object
);
2095 if (vm_map_lock_read_to_write(target_map
)) {
2097 * We couldn't upgrade our VM map lock
2098 * from "read" to "write" and we lost
2100 * Start all over again...
2102 vm_object_deallocate(object
); /* extra ref */
2103 target_map
= original_map
;
2106 vm_object_lock(object
);
2109 * JMM - We need to avoid coming here when the object
2110 * is wired by anybody, not just the current map. Why
2111 * couldn't we use the standard vm_object_copy_quickly()
2115 /* create a shadow object */
2116 vm_object_shadow(&map_entry
->object
.vm_object
,
2117 &map_entry
->offset
, total_size
);
2118 shadow_object
= map_entry
->object
.vm_object
;
2119 vm_object_unlock(object
);
2121 prot
= map_entry
->protection
& ~VM_PROT_WRITE
;
2123 if (override_nx(target_map
, map_entry
->alias
) && prot
)
2124 prot
|= VM_PROT_EXECUTE
;
2126 vm_object_pmap_protect(
2127 object
, map_entry
->offset
,
2129 ((map_entry
->is_shared
2130 || target_map
->mapped
)
2133 map_entry
->vme_start
,
2135 total_size
-= (map_entry
->vme_end
2136 - map_entry
->vme_start
);
2137 next_entry
= map_entry
->vme_next
;
2138 map_entry
->needs_copy
= FALSE
;
2140 vm_object_lock(shadow_object
);
2141 while (total_size
) {
2142 if(next_entry
->object
.vm_object
== object
) {
2143 vm_object_reference_locked(shadow_object
);
2144 next_entry
->object
.vm_object
2146 vm_object_deallocate(object
);
2148 = next_entry
->vme_prev
->offset
+
2149 (next_entry
->vme_prev
->vme_end
2150 - next_entry
->vme_prev
->vme_start
);
2151 next_entry
->needs_copy
= FALSE
;
2153 panic("mach_make_memory_entry_64:"
2154 " map entries out of sync\n");
2158 - next_entry
->vme_start
;
2159 next_entry
= next_entry
->vme_next
;
2163 * Transfer our extra reference to the
2166 vm_object_reference_locked(shadow_object
);
2167 vm_object_deallocate(object
); /* extra ref */
2168 object
= shadow_object
;
2170 obj_off
= (local_offset
- map_entry
->vme_start
)
2171 + map_entry
->offset
;
2173 vm_map_lock_write_to_read(target_map
);
2177 /* note: in the future we can (if necessary) allow for */
2178 /* memory object lists, this will better support */
2179 /* fragmentation, but is it necessary? The user should */
2180 /* be encouraged to create address space oriented */
2181 /* shared objects from CLEAN memory regions which have */
2182 /* a known and defined history. i.e. no inheritence */
2183 /* share, make this call before making the region the */
2184 /* target of ipc's, etc. The code above, protecting */
2185 /* against delayed copy, etc. is mostly defensive. */
2187 wimg_mode
= object
->wimg_bits
;
2188 if(!(object
->nophyscache
)) {
2189 if(access
== MAP_MEM_IO
) {
2190 wimg_mode
= VM_WIMG_IO
;
2191 } else if (access
== MAP_MEM_COPYBACK
) {
2192 wimg_mode
= VM_WIMG_USE_DEFAULT
;
2193 } else if (access
== MAP_MEM_WTHRU
) {
2194 wimg_mode
= VM_WIMG_WTHRU
;
2195 } else if (access
== MAP_MEM_WCOMB
) {
2196 wimg_mode
= VM_WIMG_WCOMB
;
2200 object
->true_share
= TRUE
;
2201 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
2202 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
2205 * The memory entry now points to this VM object and we
2206 * need to hold a reference on the VM object. Use the extra
2207 * reference we took earlier to keep the object alive when we
2211 vm_map_unlock_read(target_map
);
2212 if(real_map
!= target_map
)
2213 vm_map_unlock_read(real_map
);
2215 if(object
->wimg_bits
!= wimg_mode
) {
2218 vm_object_paging_wait(object
, THREAD_UNINT
);
2220 if ((wimg_mode
== VM_WIMG_IO
)
2221 || (wimg_mode
== VM_WIMG_WCOMB
))
2226 queue_iterate(&object
->memq
,
2227 p
, vm_page_t
, listq
) {
2228 if (!p
->fictitious
) {
2230 pmap_disconnect(p
->phys_page
);
2232 pmap_sync_page_attributes_phys(p
->phys_page
);
2235 object
->wimg_bits
= wimg_mode
;
2238 /* the size of mapped entry that overlaps with our region */
2239 /* which is targeted for share. */
2240 /* (entry_end - entry_start) - */
2241 /* offset of our beg addr within entry */
2242 /* it corresponds to this: */
2244 if(map_size
> mappable_size
)
2245 map_size
= mappable_size
;
2247 if (permission
& MAP_MEM_NAMED_REUSE
) {
2249 * Compare what we got with the "parent_entry".
2250 * If they match, re-use the "parent_entry" instead
2251 * of creating a new one.
2253 if (parent_entry
!= NULL
&&
2254 parent_entry
->backing
.object
== object
&&
2255 parent_entry
->internal
== object
->internal
&&
2256 parent_entry
->is_sub_map
== FALSE
&&
2257 parent_entry
->is_pager
== FALSE
&&
2258 parent_entry
->offset
== obj_off
&&
2259 parent_entry
->protection
== protections
&&
2260 parent_entry
->size
== map_size
) {
2262 * We have a match: re-use "parent_entry".
2264 /* release our extra reference on object */
2265 vm_object_unlock(object
);
2266 vm_object_deallocate(object
);
2267 /* parent_entry->ref_count++; XXX ? */
2268 /* Get an extra send-right on handle */
2269 ipc_port_copy_send(parent_handle
);
2270 *object_handle
= parent_handle
;
2271 return KERN_SUCCESS
;
2274 * No match: we need to create a new entry.
2280 vm_object_unlock(object
);
2281 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2283 /* release our unused reference on the object */
2284 vm_object_deallocate(object
);
2285 return KERN_FAILURE
;
2288 user_entry
->backing
.object
= object
;
2289 user_entry
->internal
= object
->internal
;
2290 user_entry
->is_sub_map
= FALSE
;
2291 user_entry
->is_pager
= FALSE
;
2292 user_entry
->offset
= obj_off
;
2293 user_entry
->protection
= permission
;
2294 user_entry
->size
= map_size
;
2296 /* user_object pager and internal fields are not used */
2297 /* when the object field is filled in. */
2299 *size
= CAST_DOWN(vm_size_t
, map_size
);
2300 *object_handle
= user_handle
;
2301 return KERN_SUCCESS
;
2304 /* The new object will be base on an existing named object */
2306 if (parent_entry
== NULL
) {
2307 kr
= KERN_INVALID_ARGUMENT
;
2310 if((offset
+ map_size
) > parent_entry
->size
) {
2311 kr
= KERN_INVALID_ARGUMENT
;
2315 if((protections
& parent_entry
->protection
) != protections
) {
2316 kr
= KERN_PROTECTION_FAILURE
;
2320 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2326 user_entry
->size
= map_size
;
2327 user_entry
->offset
= parent_entry
->offset
+ map_offset
;
2328 user_entry
->is_sub_map
= parent_entry
->is_sub_map
;
2329 user_entry
->is_pager
= parent_entry
->is_pager
;
2330 user_entry
->internal
= parent_entry
->internal
;
2331 user_entry
->protection
= protections
;
2333 if(access
!= MAP_MEM_NOOP
) {
2334 SET_MAP_MEM(access
, user_entry
->protection
);
2337 if(parent_entry
->is_sub_map
) {
2338 user_entry
->backing
.map
= parent_entry
->backing
.map
;
2339 vm_map_lock(user_entry
->backing
.map
);
2340 user_entry
->backing
.map
->ref_count
++;
2341 vm_map_unlock(user_entry
->backing
.map
);
2343 else if (parent_entry
->is_pager
) {
2344 user_entry
->backing
.pager
= parent_entry
->backing
.pager
;
2345 /* JMM - don't we need a reference here? */
2347 object
= parent_entry
->backing
.object
;
2348 assert(object
!= VM_OBJECT_NULL
);
2349 user_entry
->backing
.object
= object
;
2350 /* we now point to this object, hold on */
2351 vm_object_reference(object
);
2352 vm_object_lock(object
);
2353 object
->true_share
= TRUE
;
2354 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
2355 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
2356 vm_object_unlock(object
);
2358 *size
= CAST_DOWN(vm_size_t
, map_size
);
2359 *object_handle
= user_handle
;
2360 return KERN_SUCCESS
;
2364 if (user_handle
!= IP_NULL
) {
2365 ipc_port_dealloc_kernel(user_handle
);
2367 if (user_entry
!= NULL
) {
2368 kfree(user_entry
, sizeof *user_entry
);
2374 _mach_make_memory_entry(
2375 vm_map_t target_map
,
2376 memory_object_size_t
*size
,
2377 memory_object_offset_t offset
,
2378 vm_prot_t permission
,
2379 ipc_port_t
*object_handle
,
2380 ipc_port_t parent_entry
)
2382 memory_object_size_t mo_size
;
2385 mo_size
= (memory_object_size_t
)*size
;
2386 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
2387 (memory_object_offset_t
)offset
, permission
, object_handle
,
2394 mach_make_memory_entry(
2395 vm_map_t target_map
,
2398 vm_prot_t permission
,
2399 ipc_port_t
*object_handle
,
2400 ipc_port_t parent_entry
)
2402 memory_object_size_t mo_size
;
2405 mo_size
= (memory_object_size_t
)*size
;
2406 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
2407 (memory_object_offset_t
)offset
, permission
, object_handle
,
2409 *size
= CAST_DOWN(vm_size_t
, mo_size
);
2416 * Set or clear the map's wiring_required flag. This flag, if set,
2417 * will cause all future virtual memory allocation to allocate
2418 * user wired memory. Unwiring pages wired down as a result of
2419 * this routine is done with the vm_wire interface.
2424 boolean_t must_wire
)
2426 if (map
== VM_MAP_NULL
)
2427 return(KERN_INVALID_ARGUMENT
);
2430 map
->wiring_required
= TRUE
;
2432 map
->wiring_required
= FALSE
;
2434 return(KERN_SUCCESS
);
2437 __private_extern__ kern_return_t
2438 mach_memory_entry_allocate(
2439 vm_named_entry_t
*user_entry_p
,
2440 ipc_port_t
*user_handle_p
)
2442 vm_named_entry_t user_entry
;
2443 ipc_port_t user_handle
;
2444 ipc_port_t previous
;
2446 user_entry
= (vm_named_entry_t
) kalloc(sizeof *user_entry
);
2447 if (user_entry
== NULL
)
2448 return KERN_FAILURE
;
2450 named_entry_lock_init(user_entry
);
2452 user_handle
= ipc_port_alloc_kernel();
2453 if (user_handle
== IP_NULL
) {
2454 kfree(user_entry
, sizeof *user_entry
);
2455 return KERN_FAILURE
;
2457 ip_lock(user_handle
);
2459 /* make a sonce right */
2460 user_handle
->ip_sorights
++;
2461 ip_reference(user_handle
);
2463 user_handle
->ip_destination
= IP_NULL
;
2464 user_handle
->ip_receiver_name
= MACH_PORT_NULL
;
2465 user_handle
->ip_receiver
= ipc_space_kernel
;
2467 /* make a send right */
2468 user_handle
->ip_mscount
++;
2469 user_handle
->ip_srights
++;
2470 ip_reference(user_handle
);
2472 ipc_port_nsrequest(user_handle
, 1, user_handle
, &previous
);
2473 /* nsrequest unlocks user_handle */
2475 user_entry
->backing
.pager
= NULL
;
2476 user_entry
->is_sub_map
= FALSE
;
2477 user_entry
->is_pager
= FALSE
;
2478 user_entry
->internal
= FALSE
;
2479 user_entry
->size
= 0;
2480 user_entry
->offset
= 0;
2481 user_entry
->protection
= VM_PROT_NONE
;
2482 user_entry
->ref_count
= 1;
2484 ipc_kobject_set(user_handle
, (ipc_kobject_t
) user_entry
,
2487 *user_entry_p
= user_entry
;
2488 *user_handle_p
= user_handle
;
2490 return KERN_SUCCESS
;
2494 * mach_memory_object_memory_entry_64
2496 * Create a named entry backed by the provided pager.
2498 * JMM - we need to hold a reference on the pager -
2499 * and release it when the named entry is destroyed.
2502 mach_memory_object_memory_entry_64(
2505 vm_object_offset_t size
,
2506 vm_prot_t permission
,
2507 memory_object_t pager
,
2508 ipc_port_t
*entry_handle
)
2510 unsigned int access
;
2511 vm_named_entry_t user_entry
;
2512 ipc_port_t user_handle
;
2514 if (host
== HOST_NULL
)
2515 return(KERN_INVALID_HOST
);
2517 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2519 return KERN_FAILURE
;
2522 user_entry
->backing
.pager
= pager
;
2523 user_entry
->size
= size
;
2524 user_entry
->offset
= 0;
2525 user_entry
->protection
= permission
& VM_PROT_ALL
;
2526 access
= GET_MAP_MEM(permission
);
2527 SET_MAP_MEM(access
, user_entry
->protection
);
2528 user_entry
->internal
= internal
;
2529 user_entry
->is_sub_map
= FALSE
;
2530 user_entry
->is_pager
= TRUE
;
2531 assert(user_entry
->ref_count
== 1);
2533 *entry_handle
= user_handle
;
2534 return KERN_SUCCESS
;
2538 mach_memory_object_memory_entry(
2542 vm_prot_t permission
,
2543 memory_object_t pager
,
2544 ipc_port_t
*entry_handle
)
2546 return mach_memory_object_memory_entry_64( host
, internal
,
2547 (vm_object_offset_t
)size
, permission
, pager
, entry_handle
);
2552 mach_memory_entry_purgable_control(
2553 ipc_port_t entry_port
,
2554 vm_purgable_t control
,
2558 vm_named_entry_t mem_entry
;
2561 if (entry_port
== IP_NULL
||
2562 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
2563 return KERN_INVALID_ARGUMENT
;
2565 if (control
!= VM_PURGABLE_SET_STATE
&&
2566 control
!= VM_PURGABLE_GET_STATE
)
2567 return(KERN_INVALID_ARGUMENT
);
2569 if (control
== VM_PURGABLE_SET_STATE
&&
2570 (((*state
& ~(VM_PURGABLE_STATE_MASK
|VM_VOLATILE_ORDER_MASK
|VM_PURGABLE_ORDERING_MASK
|VM_PURGABLE_BEHAVIOR_MASK
|VM_VOLATILE_GROUP_MASK
)) != 0) ||
2571 ((*state
& VM_PURGABLE_STATE_MASK
) > VM_PURGABLE_STATE_MASK
)))
2572 return(KERN_INVALID_ARGUMENT
);
2574 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
2576 named_entry_lock(mem_entry
);
2578 if (mem_entry
->is_sub_map
|| mem_entry
->is_pager
) {
2579 named_entry_unlock(mem_entry
);
2580 return KERN_INVALID_ARGUMENT
;
2583 object
= mem_entry
->backing
.object
;
2584 if (object
== VM_OBJECT_NULL
) {
2585 named_entry_unlock(mem_entry
);
2586 return KERN_INVALID_ARGUMENT
;
2589 vm_object_lock(object
);
2591 /* check that named entry covers entire object ? */
2592 if (mem_entry
->offset
!= 0 || object
->size
!= mem_entry
->size
) {
2593 vm_object_unlock(object
);
2594 named_entry_unlock(mem_entry
);
2595 return KERN_INVALID_ARGUMENT
;
2598 named_entry_unlock(mem_entry
);
2600 kr
= vm_object_purgable_control(object
, control
, state
);
2602 vm_object_unlock(object
);
2608 * mach_memory_entry_port_release:
2610 * Release a send right on a named entry port. This is the correct
2611 * way to destroy a named entry. When the last right on the port is
2612 * released, ipc_kobject_destroy() will call mach_destroy_memory_entry().
2615 mach_memory_entry_port_release(
2618 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
2619 ipc_port_release_send(port
);
2623 * mach_destroy_memory_entry:
2625 * Drops a reference on a memory entry and destroys the memory entry if
2626 * there are no more references on it.
2627 * NOTE: This routine should not be called to destroy a memory entry from the
2628 * kernel, as it will not release the Mach port associated with the memory
2629 * entry. The proper way to destroy a memory entry in the kernel is to
2630 * call mach_memort_entry_port_release() to release the kernel's send-right on
2631 * the memory entry's port. When the last send right is released, the memory
2632 * entry will be destroyed via ipc_kobject_destroy().
2635 mach_destroy_memory_entry(
2638 vm_named_entry_t named_entry
;
2640 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
2641 #endif /* MACH_ASSERT */
2642 named_entry
= (vm_named_entry_t
)port
->ip_kobject
;
2643 mutex_lock(&(named_entry
)->Lock
);
2644 named_entry
->ref_count
-= 1;
2645 if(named_entry
->ref_count
== 0) {
2646 if (named_entry
->is_sub_map
) {
2647 vm_map_deallocate(named_entry
->backing
.map
);
2648 } else if (!named_entry
->is_pager
) {
2649 /* release the memory object we've been pointing to */
2650 vm_object_deallocate(named_entry
->backing
.object
);
2651 } /* else JMM - need to drop reference on pager in that case */
2653 mutex_unlock(&(named_entry
)->Lock
);
2655 kfree((void *) port
->ip_kobject
,
2656 sizeof (struct vm_named_entry
));
2658 mutex_unlock(&(named_entry
)->Lock
);
2661 /* Allow manipulation of individual page state. This is actually part of */
2662 /* the UPL regimen but takes place on the memory entry rather than on a UPL */
2665 mach_memory_entry_page_op(
2666 ipc_port_t entry_port
,
2667 vm_object_offset_t offset
,
2669 ppnum_t
*phys_entry
,
2672 vm_named_entry_t mem_entry
;
2676 if (entry_port
== IP_NULL
||
2677 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
2678 return KERN_INVALID_ARGUMENT
;
2681 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
2683 named_entry_lock(mem_entry
);
2685 if (mem_entry
->is_sub_map
|| mem_entry
->is_pager
) {
2686 named_entry_unlock(mem_entry
);
2687 return KERN_INVALID_ARGUMENT
;
2690 object
= mem_entry
->backing
.object
;
2691 if (object
== VM_OBJECT_NULL
) {
2692 named_entry_unlock(mem_entry
);
2693 return KERN_INVALID_ARGUMENT
;
2696 vm_object_reference(object
);
2697 named_entry_unlock(mem_entry
);
2699 kr
= vm_object_page_op(object
, offset
, ops
, phys_entry
, flags
);
2701 vm_object_deallocate(object
);
2707 * mach_memory_entry_range_op offers performance enhancement over
2708 * mach_memory_entry_page_op for page_op functions which do not require page
2709 * level state to be returned from the call. Page_op was created to provide
2710 * a low-cost alternative to page manipulation via UPLs when only a single
2711 * page was involved. The range_op call establishes the ability in the _op
2712 * family of functions to work on multiple pages where the lack of page level
2713 * state handling allows the caller to avoid the overhead of the upl structures.
2717 mach_memory_entry_range_op(
2718 ipc_port_t entry_port
,
2719 vm_object_offset_t offset_beg
,
2720 vm_object_offset_t offset_end
,
2724 vm_named_entry_t mem_entry
;
2728 if (entry_port
== IP_NULL
||
2729 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
2730 return KERN_INVALID_ARGUMENT
;
2733 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
2735 named_entry_lock(mem_entry
);
2737 if (mem_entry
->is_sub_map
|| mem_entry
->is_pager
) {
2738 named_entry_unlock(mem_entry
);
2739 return KERN_INVALID_ARGUMENT
;
2742 object
= mem_entry
->backing
.object
;
2743 if (object
== VM_OBJECT_NULL
) {
2744 named_entry_unlock(mem_entry
);
2745 return KERN_INVALID_ARGUMENT
;
2748 vm_object_reference(object
);
2749 named_entry_unlock(mem_entry
);
2751 kr
= vm_object_range_op(object
,
2757 vm_object_deallocate(object
);
2764 set_dp_control_port(
2765 host_priv_t host_priv
,
2766 ipc_port_t control_port
)
2768 if (host_priv
== HOST_PRIV_NULL
)
2769 return (KERN_INVALID_HOST
);
2771 if (IP_VALID(dynamic_pager_control_port
))
2772 ipc_port_release_send(dynamic_pager_control_port
);
2774 dynamic_pager_control_port
= control_port
;
2775 return KERN_SUCCESS
;
2779 get_dp_control_port(
2780 host_priv_t host_priv
,
2781 ipc_port_t
*control_port
)
2783 if (host_priv
== HOST_PRIV_NULL
)
2784 return (KERN_INVALID_HOST
);
2786 *control_port
= ipc_port_copy_send(dynamic_pager_control_port
);
2787 return KERN_SUCCESS
;
2791 /* ******* Temporary Internal calls to UPL for BSD ***** */
2793 extern int kernel_upl_map(
2796 vm_offset_t
*dst_addr
);
2798 extern int kernel_upl_unmap(
2802 extern int kernel_upl_commit(
2804 upl_page_info_t
*pl
,
2805 mach_msg_type_number_t count
);
2807 extern int kernel_upl_commit_range(
2809 upl_offset_t offset
,
2812 upl_page_info_array_t pl
,
2813 mach_msg_type_number_t count
);
2815 extern int kernel_upl_abort(
2819 extern int kernel_upl_abort_range(
2821 upl_offset_t offset
,
2830 vm_offset_t
*dst_addr
)
2832 return vm_upl_map(map
, upl
, dst_addr
);
2841 return vm_upl_unmap(map
, upl
);
2847 upl_page_info_t
*pl
,
2848 mach_msg_type_number_t count
)
2852 kr
= upl_commit(upl
, pl
, count
);
2853 upl_deallocate(upl
);
2859 kernel_upl_commit_range(
2861 upl_offset_t offset
,
2864 upl_page_info_array_t pl
,
2865 mach_msg_type_number_t count
)
2867 boolean_t finished
= FALSE
;
2870 if (flags
& UPL_COMMIT_FREE_ON_EMPTY
)
2871 flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
2873 kr
= upl_commit_range(upl
, offset
, size
, flags
, pl
, count
, &finished
);
2875 if ((flags
& UPL_COMMIT_NOTIFY_EMPTY
) && finished
)
2876 upl_deallocate(upl
);
2882 kernel_upl_abort_range(
2884 upl_offset_t offset
,
2889 boolean_t finished
= FALSE
;
2891 if (abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
)
2892 abort_flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
2894 kr
= upl_abort_range(upl
, offset
, size
, abort_flags
, &finished
);
2896 if ((abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
) && finished
)
2897 upl_deallocate(upl
);
2909 kr
= upl_abort(upl
, abort_type
);
2910 upl_deallocate(upl
);
2915 * Now a kernel-private interface (for BootCache
2916 * use only). Need a cleaner way to create an
2917 * empty vm_map() and return a handle to it.
2921 vm_region_object_create(
2922 __unused vm_map_t target_map
,
2924 ipc_port_t
*object_handle
)
2926 vm_named_entry_t user_entry
;
2927 ipc_port_t user_handle
;
2931 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2933 return KERN_FAILURE
;
2936 /* Create a named object based on a submap of specified size */
2938 new_map
= vm_map_create(PMAP_NULL
, VM_MAP_MIN_ADDRESS
,
2939 vm_map_round_page(size
), TRUE
);
2941 user_entry
->backing
.map
= new_map
;
2942 user_entry
->internal
= TRUE
;
2943 user_entry
->is_sub_map
= TRUE
;
2944 user_entry
->offset
= 0;
2945 user_entry
->protection
= VM_PROT_ALL
;
2946 user_entry
->size
= size
;
2947 assert(user_entry
->ref_count
== 1);
2949 *object_handle
= user_handle
;
2950 return KERN_SUCCESS
;
2954 ppnum_t
vm_map_get_phys_page( /* forward */
2956 vm_offset_t offset
);
2959 vm_map_get_phys_page(
2963 vm_object_offset_t offset
;
2965 vm_map_offset_t map_offset
;
2966 vm_map_entry_t entry
;
2967 ppnum_t phys_page
= 0;
2969 map_offset
= vm_map_trunc_page(addr
);
2972 while (vm_map_lookup_entry(map
, map_offset
, &entry
)) {
2974 if (entry
->object
.vm_object
== VM_OBJECT_NULL
) {
2978 if (entry
->is_sub_map
) {
2980 vm_map_lock(entry
->object
.sub_map
);
2982 map
= entry
->object
.sub_map
;
2983 map_offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
2984 vm_map_unlock(old_map
);
2987 if (entry
->object
.vm_object
->phys_contiguous
) {
2988 /* These are not standard pageable memory mappings */
2989 /* If they are not present in the object they will */
2990 /* have to be picked up from the pager through the */
2991 /* fault mechanism. */
2992 if(entry
->object
.vm_object
->shadow_offset
== 0) {
2993 /* need to call vm_fault */
2995 vm_fault(map
, map_offset
, VM_PROT_NONE
,
2996 FALSE
, THREAD_UNINT
, NULL
, 0);
3000 offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3001 phys_page
= (ppnum_t
)
3002 ((entry
->object
.vm_object
->shadow_offset
3007 offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3008 object
= entry
->object
.vm_object
;
3009 vm_object_lock(object
);
3011 vm_page_t dst_page
= vm_page_lookup(object
,offset
);
3012 if(dst_page
== VM_PAGE_NULL
) {
3013 if(object
->shadow
) {
3014 vm_object_t old_object
;
3015 vm_object_lock(object
->shadow
);
3016 old_object
= object
;
3017 offset
= offset
+ object
->shadow_offset
;
3018 object
= object
->shadow
;
3019 vm_object_unlock(old_object
);
3021 vm_object_unlock(object
);
3025 phys_page
= (ppnum_t
)(dst_page
->phys_page
);
3026 vm_object_unlock(object
);
3040 kern_return_t
kernel_object_iopl_request( /* forward */
3041 vm_named_entry_t named_entry
,
3042 memory_object_offset_t offset
,
3043 vm_size_t
*upl_size
,
3045 upl_page_info_array_t user_page_list
,
3046 unsigned int *page_list_count
,
3050 kernel_object_iopl_request(
3051 vm_named_entry_t named_entry
,
3052 memory_object_offset_t offset
,
3053 vm_size_t
*upl_size
,
3055 upl_page_info_array_t user_page_list
,
3056 unsigned int *page_list_count
,
3064 caller_flags
= *flags
;
3066 if (caller_flags
& ~UPL_VALID_FLAGS
) {
3068 * For forward compatibility's sake,
3069 * reject any unknown flag.
3071 return KERN_INVALID_VALUE
;
3074 /* a few checks to make sure user is obeying rules */
3075 if(*upl_size
== 0) {
3076 if(offset
>= named_entry
->size
)
3077 return(KERN_INVALID_RIGHT
);
3078 *upl_size
= named_entry
->size
- offset
;
3080 if(caller_flags
& UPL_COPYOUT_FROM
) {
3081 if((named_entry
->protection
& VM_PROT_READ
)
3083 return(KERN_INVALID_RIGHT
);
3086 if((named_entry
->protection
&
3087 (VM_PROT_READ
| VM_PROT_WRITE
))
3088 != (VM_PROT_READ
| VM_PROT_WRITE
)) {
3089 return(KERN_INVALID_RIGHT
);
3092 if(named_entry
->size
< (offset
+ *upl_size
))
3093 return(KERN_INVALID_ARGUMENT
);
3095 /* the callers parameter offset is defined to be the */
3096 /* offset from beginning of named entry offset in object */
3097 offset
= offset
+ named_entry
->offset
;
3099 if(named_entry
->is_sub_map
)
3100 return (KERN_INVALID_ARGUMENT
);
3102 named_entry_lock(named_entry
);
3104 if (named_entry
->is_pager
) {
3105 object
= vm_object_enter(named_entry
->backing
.pager
,
3106 named_entry
->offset
+ named_entry
->size
,
3107 named_entry
->internal
,
3110 if (object
== VM_OBJECT_NULL
) {
3111 named_entry_unlock(named_entry
);
3112 return(KERN_INVALID_OBJECT
);
3115 /* JMM - drop reference on the pager here? */
3117 /* create an extra reference for the object */
3118 vm_object_lock(object
);
3119 vm_object_reference_locked(object
);
3120 named_entry
->backing
.object
= object
;
3121 named_entry
->is_pager
= FALSE
;
3122 named_entry_unlock(named_entry
);
3124 /* wait for object (if any) to be ready */
3125 if (!named_entry
->internal
) {
3126 while (!object
->pager_ready
) {
3127 vm_object_wait(object
,
3128 VM_OBJECT_EVENT_PAGER_READY
,
3130 vm_object_lock(object
);
3133 vm_object_unlock(object
);
3136 /* This is the case where we are going to operate */
3137 /* an an already known object. If the object is */
3138 /* not ready it is internal. An external */
3139 /* object cannot be mapped until it is ready */
3140 /* we can therefore avoid the ready check */
3142 object
= named_entry
->backing
.object
;
3143 vm_object_reference(object
);
3144 named_entry_unlock(named_entry
);
3147 if (!object
->private) {
3148 if (*upl_size
> (MAX_UPL_TRANSFER
*PAGE_SIZE
))
3149 *upl_size
= (MAX_UPL_TRANSFER
*PAGE_SIZE
);
3150 if (object
->phys_contiguous
) {
3151 *flags
= UPL_PHYS_CONTIG
;
3156 *flags
= UPL_DEV_MEMORY
| UPL_PHYS_CONTIG
;
3159 ret
= vm_object_iopl_request(object
,
3166 vm_object_deallocate(object
);