2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
36 * All Rights Reserved.
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48 * Carnegie Mellon requests users of this software to return to
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
62 * Author: Avadis Tevanian, Jr., Michael Wayne Young
64 * User-exported virtual memory functions.
70 #include <mach/boolean.h>
71 #include <mach/kern_return.h>
72 #include <mach/mach_types.h> /* to get vm_address_t */
73 #include <mach/memory_object.h>
74 #include <mach/std_types.h> /* to get pointer_t */
76 #include <mach/vm_attributes.h>
77 #include <mach/vm_param.h>
78 #include <mach/vm_statistics.h>
79 #include <mach/mach_syscalls.h>
81 #include <mach/host_priv_server.h>
82 #include <mach/mach_vm_server.h>
83 #include <mach/shared_memory_server.h>
84 #include <mach/vm_map_server.h>
85 #include <vm/vm_shared_memory_server.h>
87 #include <kern/host.h>
88 #include <kern/kalloc.h>
89 #include <kern/task.h>
90 #include <kern/misc_protos.h>
91 #include <vm/vm_fault.h>
92 #include <vm/vm_map.h>
93 #include <vm/vm_object.h>
94 #include <vm/vm_page.h>
95 #include <vm/memory_object.h>
96 #include <vm/vm_pageout.h>
97 #include <vm/vm_protos.h>
99 vm_size_t upl_offset_to_pagelist
= 0;
105 ipc_port_t dynamic_pager_control_port
=NULL
;
108 * mach_vm_allocate allocates "zero fill" memory in the specfied
114 mach_vm_offset_t
*addr
,
118 vm_map_offset_t map_addr
;
119 vm_map_size_t map_size
;
120 kern_return_t result
;
121 boolean_t anywhere
= ((VM_FLAGS_ANYWHERE
& flags
) != 0);
123 if (map
== VM_MAP_NULL
)
124 return(KERN_INVALID_ARGUMENT
);
127 return(KERN_SUCCESS
);
132 * No specific address requested, so start candidate address
133 * search at the minimum address in the map. However, if that
134 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
135 * allocations of PAGEZERO to explicit requests since its
136 * normal use is to catch dereferences of NULL and many
137 * applications also treat pointers with a value of 0 as
138 * special and suddenly having address 0 contain useable
139 * memory would tend to confuse those applications.
141 map_addr
= vm_map_min(map
);
143 map_addr
+= PAGE_SIZE
;
145 map_addr
= vm_map_trunc_page(*addr
);
146 map_size
= vm_map_round_page(size
);
148 return(KERN_INVALID_ARGUMENT
);
151 result
= vm_map_enter(
158 (vm_object_offset_t
)0,
170 * Legacy routine that allocates "zero fill" memory in the specfied
171 * map (which is limited to the same size as the kernel).
180 vm_map_offset_t map_addr
;
181 vm_map_size_t map_size
;
182 kern_return_t result
;
183 boolean_t anywhere
= ((VM_FLAGS_ANYWHERE
& flags
) != 0);
185 if (map
== VM_MAP_NULL
)
186 return(KERN_INVALID_ARGUMENT
);
189 return(KERN_SUCCESS
);
194 * No specific address requested, so start candidate address
195 * search at the minimum address in the map. However, if that
196 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
197 * allocations of PAGEZERO to explicit requests since its
198 * normal use is to catch dereferences of NULL and many
199 * applications also treat pointers with a value of 0 as
200 * special and suddenly having address 0 contain useable
201 * memory would tend to confuse those applications.
203 map_addr
= vm_map_min(map
);
205 map_addr
+= PAGE_SIZE
;
207 map_addr
= vm_map_trunc_page(*addr
);
208 map_size
= vm_map_round_page(size
);
210 return(KERN_INVALID_ARGUMENT
);
213 result
= vm_map_enter(
220 (vm_object_offset_t
)0,
226 *addr
= CAST_DOWN(vm_offset_t
, map_addr
);
231 * mach_vm_deallocate -
232 * deallocates the specified range of addresses in the
233 * specified address map.
238 mach_vm_offset_t start
,
241 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
242 return(KERN_INVALID_ARGUMENT
);
244 if (size
== (mach_vm_offset_t
) 0)
245 return(KERN_SUCCESS
);
247 return(vm_map_remove(map
, vm_map_trunc_page(start
),
248 vm_map_round_page(start
+size
), VM_MAP_NO_FLAGS
));
253 * deallocates the specified range of addresses in the
254 * specified address map (limited to addresses the same
255 * size as the kernel).
259 register vm_map_t map
,
263 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
264 return(KERN_INVALID_ARGUMENT
);
266 if (size
== (vm_offset_t
) 0)
267 return(KERN_SUCCESS
);
269 return(vm_map_remove(map
, vm_map_trunc_page(start
),
270 vm_map_round_page(start
+size
), VM_MAP_NO_FLAGS
));
275 * Sets the inheritance of the specified range in the
281 mach_vm_offset_t start
,
283 vm_inherit_t new_inheritance
)
285 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
286 (new_inheritance
> VM_INHERIT_LAST_VALID
))
287 return(KERN_INVALID_ARGUMENT
);
292 return(vm_map_inherit(map
,
293 vm_map_trunc_page(start
),
294 vm_map_round_page(start
+size
),
300 * Sets the inheritance of the specified range in the
301 * specified map (range limited to addresses
305 register vm_map_t map
,
308 vm_inherit_t new_inheritance
)
310 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
311 (new_inheritance
> VM_INHERIT_LAST_VALID
))
312 return(KERN_INVALID_ARGUMENT
);
317 return(vm_map_inherit(map
,
318 vm_map_trunc_page(start
),
319 vm_map_round_page(start
+size
),
325 * Sets the protection of the specified range in the
332 mach_vm_offset_t start
,
334 boolean_t set_maximum
,
335 vm_prot_t new_protection
)
337 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
338 (new_protection
& ~(VM_PROT_ALL
| VM_PROT_COPY
)))
339 return(KERN_INVALID_ARGUMENT
);
344 return(vm_map_protect(map
,
345 vm_map_trunc_page(start
),
346 vm_map_round_page(start
+size
),
353 * Sets the protection of the specified range in the
354 * specified map. Addressability of the range limited
355 * to the same size as the kernel.
363 boolean_t set_maximum
,
364 vm_prot_t new_protection
)
366 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
367 (new_protection
& ~(VM_PROT_ALL
| VM_PROT_COPY
)))
368 return(KERN_INVALID_ARGUMENT
);
373 return(vm_map_protect(map
,
374 vm_map_trunc_page(start
),
375 vm_map_round_page(start
+size
),
381 * mach_vm_machine_attributes -
382 * Handle machine-specific attributes for a mapping, such
383 * as cachability, migrability, etc.
386 mach_vm_machine_attribute(
388 mach_vm_address_t addr
,
390 vm_machine_attribute_t attribute
,
391 vm_machine_attribute_val_t
* value
) /* IN/OUT */
393 if ((map
== VM_MAP_NULL
) || (addr
+ size
< addr
))
394 return(KERN_INVALID_ARGUMENT
);
399 return vm_map_machine_attribute(map
,
400 vm_map_trunc_page(addr
),
401 vm_map_round_page(addr
+size
),
407 * vm_machine_attribute -
408 * Handle machine-specific attributes for a mapping, such
409 * as cachability, migrability, etc. Limited addressability
410 * (same range limits as for the native kernel map).
413 vm_machine_attribute(
417 vm_machine_attribute_t attribute
,
418 vm_machine_attribute_val_t
* value
) /* IN/OUT */
420 if ((map
== VM_MAP_NULL
) || (addr
+ size
< addr
))
421 return(KERN_INVALID_ARGUMENT
);
426 return vm_map_machine_attribute(map
,
427 vm_map_trunc_page(addr
),
428 vm_map_round_page(addr
+size
),
435 * Read/copy a range from one address space and return it to the caller.
437 * It is assumed that the address for the returned memory is selected by
438 * the IPC implementation as part of receiving the reply to this call.
439 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
440 * that gets returned.
442 * JMM - because of mach_msg_type_number_t, this call is limited to a
443 * single 4GB region at this time.
449 mach_vm_address_t addr
,
452 mach_msg_type_number_t
*data_size
)
455 vm_map_copy_t ipc_address
;
457 if (map
== VM_MAP_NULL
)
458 return(KERN_INVALID_ARGUMENT
);
461 error
= vm_map_copyin(map
,
462 (vm_map_address_t
)addr
,
464 FALSE
, /* src_destroy */
467 if (KERN_SUCCESS
== error
) {
468 *data
= (pointer_t
) ipc_address
;
476 * Read/copy a range from one address space and return it to the caller.
477 * Limited addressability (same range limits as for the native kernel map).
479 * It is assumed that the address for the returned memory is selected by
480 * the IPC implementation as part of receiving the reply to this call.
481 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
482 * that gets returned.
490 mach_msg_type_number_t
*data_size
)
493 vm_map_copy_t ipc_address
;
495 if (map
== VM_MAP_NULL
)
496 return(KERN_INVALID_ARGUMENT
);
498 error
= vm_map_copyin(map
,
499 (vm_map_address_t
)addr
,
501 FALSE
, /* src_destroy */
504 if (KERN_SUCCESS
== error
) {
505 *data
= (pointer_t
) ipc_address
;
512 * mach_vm_read_list -
513 * Read/copy a list of address ranges from specified map.
515 * MIG does not know how to deal with a returned array of
516 * vm_map_copy_t structures, so we have to do the copyout
522 mach_vm_read_entry_t data_list
,
525 mach_msg_type_number_t i
;
529 if (map
== VM_MAP_NULL
||
530 count
> VM_MAP_ENTRY_MAX
)
531 return(KERN_INVALID_ARGUMENT
);
533 error
= KERN_SUCCESS
;
534 for(i
=0; i
<count
; i
++) {
535 vm_map_address_t map_addr
;
536 vm_map_size_t map_size
;
538 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
539 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
542 error
= vm_map_copyin(map
,
545 FALSE
, /* src_destroy */
547 if (KERN_SUCCESS
== error
) {
548 error
= vm_map_copyout(
552 if (KERN_SUCCESS
== error
) {
553 data_list
[i
].address
= map_addr
;
556 vm_map_copy_discard(copy
);
559 data_list
[i
].address
= (mach_vm_address_t
)0;
560 data_list
[i
].size
= (mach_vm_size_t
)0;
567 * Read/copy a list of address ranges from specified map.
569 * MIG does not know how to deal with a returned array of
570 * vm_map_copy_t structures, so we have to do the copyout
573 * The source and destination ranges are limited to those
574 * that can be described with a vm_address_t (i.e. same
575 * size map as the kernel).
577 * JMM - If the result of the copyout is an address range
578 * that cannot be described with a vm_address_t (i.e. the
579 * caller had a larger address space but used this call
580 * anyway), it will result in a truncated address being
581 * returned (and a likely confused caller).
587 vm_read_entry_t data_list
,
590 mach_msg_type_number_t i
;
594 if (map
== VM_MAP_NULL
||
595 count
> VM_MAP_ENTRY_MAX
)
596 return(KERN_INVALID_ARGUMENT
);
598 error
= KERN_SUCCESS
;
599 for(i
=0; i
<count
; i
++) {
600 vm_map_address_t map_addr
;
601 vm_map_size_t map_size
;
603 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
604 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
607 error
= vm_map_copyin(map
,
610 FALSE
, /* src_destroy */
612 if (KERN_SUCCESS
== error
) {
613 error
= vm_map_copyout(current_task()->map
,
616 if (KERN_SUCCESS
== error
) {
617 data_list
[i
].address
=
618 CAST_DOWN(vm_offset_t
, map_addr
);
621 vm_map_copy_discard(copy
);
624 data_list
[i
].address
= (mach_vm_address_t
)0;
625 data_list
[i
].size
= (mach_vm_size_t
)0;
631 * mach_vm_read_overwrite -
632 * Overwrite a range of the current map with data from the specified
635 * In making an assumption that the current thread is local, it is
636 * no longer cluster-safe without a fully supportive local proxy
637 * thread/task (but we don't support cluster's anymore so this is moot).
641 mach_vm_read_overwrite(
643 mach_vm_address_t address
,
645 mach_vm_address_t data
,
646 mach_vm_size_t
*data_size
)
651 if (map
== VM_MAP_NULL
)
652 return(KERN_INVALID_ARGUMENT
);
654 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
655 (vm_map_size_t
)size
, FALSE
, ©
);
657 if (KERN_SUCCESS
== error
) {
658 error
= vm_map_copy_overwrite(current_thread()->map
,
659 (vm_map_address_t
)data
,
661 if (KERN_SUCCESS
== error
) {
665 vm_map_copy_discard(copy
);
671 * vm_read_overwrite -
672 * Overwrite a range of the current map with data from the specified
675 * This routine adds the additional limitation that the source and
676 * destination ranges must be describable with vm_address_t values
677 * (i.e. the same size address spaces as the kernel, or at least the
678 * the ranges are in that first portion of the respective address
685 vm_address_t address
,
688 vm_size_t
*data_size
)
693 if (map
== VM_MAP_NULL
)
694 return(KERN_INVALID_ARGUMENT
);
696 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
697 (vm_map_size_t
)size
, FALSE
, ©
);
699 if (KERN_SUCCESS
== error
) {
700 error
= vm_map_copy_overwrite(current_thread()->map
,
701 (vm_map_address_t
)data
,
703 if (KERN_SUCCESS
== error
) {
707 vm_map_copy_discard(copy
);
715 * Overwrite the specified address range with the data provided
716 * (from the current map).
721 mach_vm_address_t address
,
723 __unused mach_msg_type_number_t size
)
725 if (map
== VM_MAP_NULL
)
726 return KERN_INVALID_ARGUMENT
;
728 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
729 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
734 * Overwrite the specified address range with the data provided
735 * (from the current map).
737 * The addressability of the range of addresses to overwrite is
738 * limited bu the use of a vm_address_t (same size as kernel map).
739 * Either the target map is also small, or the range is in the
740 * low addresses within it.
745 vm_address_t address
,
747 __unused mach_msg_type_number_t size
)
749 if (map
== VM_MAP_NULL
)
750 return KERN_INVALID_ARGUMENT
;
752 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
753 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
758 * Overwrite one range of the specified map with the contents of
759 * another range within that same map (i.e. both address ranges
765 mach_vm_address_t source_address
,
767 mach_vm_address_t dest_address
)
772 if (map
== VM_MAP_NULL
)
773 return KERN_INVALID_ARGUMENT
;
775 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
776 (vm_map_size_t
)size
, FALSE
, ©
);
778 if (KERN_SUCCESS
== kr
) {
779 kr
= vm_map_copy_overwrite(map
,
780 (vm_map_address_t
)dest_address
,
781 copy
, FALSE
/* interruptible XXX */);
783 if (KERN_SUCCESS
!= kr
)
784 vm_map_copy_discard(copy
);
792 vm_address_t source_address
,
794 vm_address_t dest_address
)
799 if (map
== VM_MAP_NULL
)
800 return KERN_INVALID_ARGUMENT
;
802 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
803 (vm_map_size_t
)size
, FALSE
, ©
);
805 if (KERN_SUCCESS
== kr
) {
806 kr
= vm_map_copy_overwrite(map
,
807 (vm_map_address_t
)dest_address
,
808 copy
, FALSE
/* interruptible XXX */);
810 if (KERN_SUCCESS
!= kr
)
811 vm_map_copy_discard(copy
);
818 * Map some range of an object into an address space.
820 * The object can be one of several types of objects:
821 * NULL - anonymous memory
822 * a named entry - a range within another address space
823 * or a range within a memory object
824 * a whole memory object
830 mach_vm_offset_t
*address
,
831 mach_vm_size_t initial_size
,
832 mach_vm_offset_t mask
,
835 vm_object_offset_t offset
,
837 vm_prot_t cur_protection
,
838 vm_prot_t max_protection
,
839 vm_inherit_t inheritance
)
841 vm_map_address_t map_addr
;
842 vm_map_size_t map_size
;
844 vm_object_size_t size
;
845 kern_return_t result
;
848 * Check arguments for validity
850 if ((target_map
== VM_MAP_NULL
) ||
851 (cur_protection
& ~VM_PROT_ALL
) ||
852 (max_protection
& ~VM_PROT_ALL
) ||
853 (inheritance
> VM_INHERIT_LAST_VALID
) ||
855 return(KERN_INVALID_ARGUMENT
);
857 map_addr
= vm_map_trunc_page(*address
);
858 map_size
= vm_map_round_page(initial_size
);
859 size
= vm_object_round_page(initial_size
);
862 * Find the vm object (if any) corresponding to this port.
864 if (!IP_VALID(port
)) {
865 object
= VM_OBJECT_NULL
;
868 } else if (ip_kotype(port
) == IKOT_NAMED_ENTRY
) {
869 vm_named_entry_t named_entry
;
871 named_entry
= (vm_named_entry_t
)port
->ip_kobject
;
872 /* a few checks to make sure user is obeying rules */
874 if(offset
>= named_entry
->size
)
875 return(KERN_INVALID_RIGHT
);
876 size
= named_entry
->size
- offset
;
878 if((named_entry
->protection
& max_protection
) != max_protection
)
879 return(KERN_INVALID_RIGHT
);
880 if((named_entry
->protection
& cur_protection
) != cur_protection
)
881 return(KERN_INVALID_RIGHT
);
882 if(named_entry
->size
< (offset
+ size
))
883 return(KERN_INVALID_ARGUMENT
);
885 /* the callers parameter offset is defined to be the */
886 /* offset from beginning of named entry offset in object */
887 offset
= offset
+ named_entry
->offset
;
889 named_entry_lock(named_entry
);
890 if(named_entry
->is_sub_map
) {
891 vm_map_entry_t map_entry
;
893 named_entry_unlock(named_entry
);
894 vm_object_reference(vm_submap_object
);
895 if ((result
= vm_map_enter(target_map
,
897 (vm_map_offset_t
)mask
, flags
,
900 cur_protection
, max_protection
, inheritance
901 )) != KERN_SUCCESS
) {
902 vm_object_deallocate(vm_submap_object
);
906 VM_GET_FLAGS_ALIAS(flags
, alias
);
907 if ((alias
== VM_MEMORY_SHARED_PMAP
) &&
909 vm_map_submap(target_map
, map_addr
,
911 named_entry
->backing
.map
,
912 (vm_map_offset_t
)offset
, TRUE
);
914 vm_map_submap(target_map
, map_addr
,
916 named_entry
->backing
.map
,
917 (vm_map_offset_t
)offset
, FALSE
);
920 if(vm_map_lookup_entry(
921 target_map
, map_addr
, &map_entry
)) {
922 map_entry
->needs_copy
= TRUE
;
929 } else if (named_entry
->is_pager
) {
931 vm_prot_t protections
;
932 unsigned int wimg_mode
;
933 boolean_t cache_attr
;
935 protections
= named_entry
->protection
937 access
= GET_MAP_MEM(named_entry
->protection
);
939 object
= vm_object_enter(
940 named_entry
->backing
.pager
,
942 named_entry
->internal
,
945 if (object
== VM_OBJECT_NULL
) {
946 named_entry_unlock(named_entry
);
947 return(KERN_INVALID_OBJECT
);
950 /* JMM - drop reference on pager here */
952 /* create an extra ref for the named entry */
953 vm_object_lock(object
);
954 vm_object_reference_locked(object
);
955 named_entry
->backing
.object
= object
;
956 named_entry
->is_pager
= FALSE
;
957 named_entry_unlock(named_entry
);
959 wimg_mode
= object
->wimg_bits
;
960 if(access
== MAP_MEM_IO
) {
961 wimg_mode
= VM_WIMG_IO
;
962 } else if (access
== MAP_MEM_COPYBACK
) {
963 wimg_mode
= VM_WIMG_USE_DEFAULT
;
964 } else if (access
== MAP_MEM_WTHRU
) {
965 wimg_mode
= VM_WIMG_WTHRU
;
966 } else if (access
== MAP_MEM_WCOMB
) {
967 wimg_mode
= VM_WIMG_WCOMB
;
969 if ((wimg_mode
== VM_WIMG_IO
)
970 || (wimg_mode
== VM_WIMG_WCOMB
))
975 /* wait for object (if any) to be ready */
976 if (!named_entry
->internal
) {
977 while (!object
->pager_ready
) {
978 vm_object_wait(object
,
979 VM_OBJECT_EVENT_PAGER_READY
,
981 vm_object_lock(object
);
985 if(object
->wimg_bits
!= wimg_mode
) {
988 vm_object_paging_wait(object
, THREAD_UNINT
);
990 object
->wimg_bits
= wimg_mode
;
991 queue_iterate(&object
->memq
, p
, vm_page_t
, listq
) {
992 if (!p
->fictitious
) {
993 pmap_disconnect(p
->phys_page
);
995 pmap_sync_page_attributes_phys(p
->phys_page
);
999 object
->true_share
= TRUE
;
1000 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
1001 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
1002 vm_object_unlock(object
);
1004 /* This is the case where we are going to map */
1005 /* an already mapped object. If the object is */
1006 /* not ready it is internal. An external */
1007 /* object cannot be mapped until it is ready */
1008 /* we can therefore avoid the ready check */
1010 object
= named_entry
->backing
.object
;
1011 assert(object
!= VM_OBJECT_NULL
);
1012 named_entry_unlock(named_entry
);
1013 vm_object_reference(object
);
1015 } else if (ip_kotype(port
) == IKOT_MEMORY_OBJECT
) {
1017 * JMM - This is temporary until we unify named entries
1018 * and raw memory objects.
1020 * Detected fake ip_kotype for a memory object. In
1021 * this case, the port isn't really a port at all, but
1022 * instead is just a raw memory object.
1025 if ((object
= vm_object_enter((memory_object_t
)port
,
1026 size
, FALSE
, FALSE
, FALSE
))
1028 return(KERN_INVALID_OBJECT
);
1030 /* wait for object (if any) to be ready */
1031 if (object
!= VM_OBJECT_NULL
) {
1032 if(object
== kernel_object
) {
1033 printf("Warning: Attempt to map kernel object"
1034 " by a non-private kernel entity\n");
1035 return(KERN_INVALID_OBJECT
);
1037 vm_object_lock(object
);
1038 while (!object
->pager_ready
) {
1039 vm_object_wait(object
,
1040 VM_OBJECT_EVENT_PAGER_READY
,
1042 vm_object_lock(object
);
1044 vm_object_unlock(object
);
1047 return (KERN_INVALID_OBJECT
);
1051 * Perform the copy if requested
1055 vm_object_t new_object
;
1056 vm_object_offset_t new_offset
;
1058 result
= vm_object_copy_strategically(object
, offset
, size
,
1059 &new_object
, &new_offset
,
1063 if (result
== KERN_MEMORY_RESTART_COPY
) {
1065 boolean_t src_needs_copy
;
1069 * We currently ignore src_needs_copy.
1070 * This really is the issue of how to make
1071 * MEMORY_OBJECT_COPY_SYMMETRIC safe for
1072 * non-kernel users to use. Solution forthcoming.
1073 * In the meantime, since we don't allow non-kernel
1074 * memory managers to specify symmetric copy,
1075 * we won't run into problems here.
1077 new_object
= object
;
1078 new_offset
= offset
;
1079 success
= vm_object_copy_quickly(&new_object
,
1084 result
= KERN_SUCCESS
;
1087 * Throw away the reference to the
1088 * original object, as it won't be mapped.
1091 vm_object_deallocate(object
);
1093 if (result
!= KERN_SUCCESS
)
1096 object
= new_object
;
1097 offset
= new_offset
;
1100 if ((result
= vm_map_enter(target_map
,
1101 &map_addr
, map_size
,
1102 (vm_map_offset_t
)mask
,
1106 cur_protection
, max_protection
, inheritance
1108 vm_object_deallocate(object
);
1109 *address
= map_addr
;
1114 /* legacy interface */
1117 vm_map_t target_map
,
1118 vm_offset_t
*address
,
1123 vm_object_offset_t offset
,
1125 vm_prot_t cur_protection
,
1126 vm_prot_t max_protection
,
1127 vm_inherit_t inheritance
)
1129 mach_vm_address_t map_addr
;
1130 mach_vm_size_t map_size
;
1131 mach_vm_offset_t map_mask
;
1134 map_addr
= (mach_vm_address_t
)*address
;
1135 map_size
= (mach_vm_size_t
)size
;
1136 map_mask
= (mach_vm_offset_t
)mask
;
1138 kr
= mach_vm_map(target_map
, &map_addr
, map_size
, map_mask
, flags
,
1140 cur_protection
, max_protection
, inheritance
);
1141 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1145 /* temporary, until world build */
1148 vm_map_t target_map
,
1149 vm_offset_t
*address
,
1156 vm_prot_t cur_protection
,
1157 vm_prot_t max_protection
,
1158 vm_inherit_t inheritance
)
1160 mach_vm_address_t map_addr
;
1161 mach_vm_size_t map_size
;
1162 mach_vm_offset_t map_mask
;
1163 vm_object_offset_t obj_offset
;
1166 map_addr
= (mach_vm_address_t
)*address
;
1167 map_size
= (mach_vm_size_t
)size
;
1168 map_mask
= (mach_vm_offset_t
)mask
;
1169 obj_offset
= (vm_object_offset_t
)offset
;
1171 kr
= mach_vm_map(target_map
, &map_addr
, map_size
, map_mask
, flags
,
1172 port
, obj_offset
, copy
,
1173 cur_protection
, max_protection
, inheritance
);
1174 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1180 * Remap a range of memory from one task into another,
1181 * to another address range within the same task, or
1182 * over top of itself (with altered permissions and/or
1183 * as an in-place copy of itself).
1188 vm_map_t target_map
,
1189 mach_vm_offset_t
*address
,
1190 mach_vm_size_t size
,
1191 mach_vm_offset_t mask
,
1194 mach_vm_offset_t memory_address
,
1196 vm_prot_t
*cur_protection
,
1197 vm_prot_t
*max_protection
,
1198 vm_inherit_t inheritance
)
1200 vm_map_offset_t map_addr
;
1203 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
)
1204 return KERN_INVALID_ARGUMENT
;
1206 map_addr
= (vm_map_offset_t
)*address
;
1208 kr
= vm_map_remap(target_map
,
1219 *address
= map_addr
;
1225 * Remap a range of memory from one task into another,
1226 * to another address range within the same task, or
1227 * over top of itself (with altered permissions and/or
1228 * as an in-place copy of itself).
1230 * The addressability of the source and target address
1231 * range is limited by the size of vm_address_t (in the
1236 vm_map_t target_map
,
1237 vm_offset_t
*address
,
1242 vm_offset_t memory_address
,
1244 vm_prot_t
*cur_protection
,
1245 vm_prot_t
*max_protection
,
1246 vm_inherit_t inheritance
)
1248 vm_map_offset_t map_addr
;
1251 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
)
1252 return KERN_INVALID_ARGUMENT
;
1254 map_addr
= (vm_map_offset_t
)*address
;
1256 kr
= vm_map_remap(target_map
,
1267 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1272 * NOTE: these routine (and this file) will no longer require mach_host_server.h
1273 * when mach_vm_wire and vm_wire are changed to use ledgers.
1275 #include <mach/mach_host_server.h>
1278 * Specify that the range of the virtual address space
1279 * of the target task must not cause page faults for
1280 * the indicated accesses.
1282 * [ To unwire the pages, specify VM_PROT_NONE. ]
1286 host_priv_t host_priv
,
1288 mach_vm_offset_t start
,
1289 mach_vm_size_t size
,
1294 if (host_priv
== HOST_PRIV_NULL
)
1295 return KERN_INVALID_HOST
;
1297 assert(host_priv
== &realhost
);
1299 if (map
== VM_MAP_NULL
)
1300 return KERN_INVALID_TASK
;
1302 if (access
& ~VM_PROT_ALL
)
1303 return KERN_INVALID_ARGUMENT
;
1305 if (access
!= VM_PROT_NONE
) {
1306 rc
= vm_map_wire(map
, vm_map_trunc_page(start
),
1307 vm_map_round_page(start
+size
), access
, TRUE
);
1309 rc
= vm_map_unwire(map
, vm_map_trunc_page(start
),
1310 vm_map_round_page(start
+size
), TRUE
);
1317 * Specify that the range of the virtual address space
1318 * of the target task must not cause page faults for
1319 * the indicated accesses.
1321 * [ To unwire the pages, specify VM_PROT_NONE. ]
1325 host_priv_t host_priv
,
1326 register vm_map_t map
,
1333 if (host_priv
== HOST_PRIV_NULL
)
1334 return KERN_INVALID_HOST
;
1336 assert(host_priv
== &realhost
);
1338 if (map
== VM_MAP_NULL
)
1339 return KERN_INVALID_TASK
;
1341 if ((access
& ~VM_PROT_ALL
) || (start
+ size
< start
))
1342 return KERN_INVALID_ARGUMENT
;
1346 } else if (access
!= VM_PROT_NONE
) {
1347 rc
= vm_map_wire(map
, vm_map_trunc_page(start
),
1348 vm_map_round_page(start
+size
), access
, TRUE
);
1350 rc
= vm_map_unwire(map
, vm_map_trunc_page(start
),
1351 vm_map_round_page(start
+size
), TRUE
);
1359 * Synchronises the memory range specified with its backing store
1360 * image by either flushing or cleaning the contents to the appropriate
1363 * interpretation of sync_flags
1364 * VM_SYNC_INVALIDATE - discard pages, only return precious
1367 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1368 * - discard pages, write dirty or precious
1369 * pages back to memory manager.
1371 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1372 * - write dirty or precious pages back to
1373 * the memory manager.
1375 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1376 * is a hole in the region, and we would
1377 * have returned KERN_SUCCESS, return
1378 * KERN_INVALID_ADDRESS instead.
1381 * KERN_INVALID_TASK Bad task parameter
1382 * KERN_INVALID_ARGUMENT both sync and async were specified.
1383 * KERN_SUCCESS The usual.
1384 * KERN_INVALID_ADDRESS There was a hole in the region.
1390 mach_vm_address_t address
,
1391 mach_vm_size_t size
,
1392 vm_sync_t sync_flags
)
1395 if (map
== VM_MAP_NULL
)
1396 return(KERN_INVALID_TASK
);
1398 return vm_map_msync(map
, (vm_map_address_t
)address
,
1399 (vm_map_size_t
)size
, sync_flags
);
1405 * Synchronises the memory range specified with its backing store
1406 * image by either flushing or cleaning the contents to the appropriate
1409 * interpretation of sync_flags
1410 * VM_SYNC_INVALIDATE - discard pages, only return precious
1413 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1414 * - discard pages, write dirty or precious
1415 * pages back to memory manager.
1417 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1418 * - write dirty or precious pages back to
1419 * the memory manager.
1421 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1422 * is a hole in the region, and we would
1423 * have returned KERN_SUCCESS, return
1424 * KERN_INVALID_ADDRESS instead.
1426 * The addressability of the range is limited to that which can
1427 * be described by a vm_address_t.
1430 * KERN_INVALID_TASK Bad task parameter
1431 * KERN_INVALID_ARGUMENT both sync and async were specified.
1432 * KERN_SUCCESS The usual.
1433 * KERN_INVALID_ADDRESS There was a hole in the region.
1439 vm_address_t address
,
1441 vm_sync_t sync_flags
)
1444 if (map
== VM_MAP_NULL
)
1445 return(KERN_INVALID_TASK
);
1447 return vm_map_msync(map
, (vm_map_address_t
)address
,
1448 (vm_map_size_t
)size
, sync_flags
);
1453 * mach_vm_behavior_set
1455 * Sets the paging behavior attribute for the specified range
1456 * in the specified map.
1458 * This routine will fail with KERN_INVALID_ADDRESS if any address
1459 * in [start,start+size) is not a valid allocated memory region.
1462 mach_vm_behavior_set(
1464 mach_vm_offset_t start
,
1465 mach_vm_size_t size
,
1466 vm_behavior_t new_behavior
)
1468 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
1469 return(KERN_INVALID_ARGUMENT
);
1472 return KERN_SUCCESS
;
1474 return(vm_map_behavior_set(map
, vm_map_trunc_page(start
),
1475 vm_map_round_page(start
+size
), new_behavior
));
1481 * Sets the paging behavior attribute for the specified range
1482 * in the specified map.
1484 * This routine will fail with KERN_INVALID_ADDRESS if any address
1485 * in [start,start+size) is not a valid allocated memory region.
1487 * This routine is potentially limited in addressibility by the
1488 * use of vm_offset_t (if the map provided is larger than the
1496 vm_behavior_t new_behavior
)
1498 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
1499 return(KERN_INVALID_ARGUMENT
);
1502 return KERN_SUCCESS
;
1504 return(vm_map_behavior_set(map
, vm_map_trunc_page(start
),
1505 vm_map_round_page(start
+size
), new_behavior
));
1511 * User call to obtain information about a region in
1512 * a task's address map. Currently, only one flavor is
1515 * XXX The reserved and behavior fields cannot be filled
1516 * in until the vm merge from the IK is completed, and
1517 * vm_reserve is implemented.
1519 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1525 mach_vm_offset_t
*address
, /* IN/OUT */
1526 mach_vm_size_t
*size
, /* OUT */
1527 vm_region_flavor_t flavor
, /* IN */
1528 vm_region_info_t info
, /* OUT */
1529 mach_msg_type_number_t
*count
, /* IN/OUT */
1530 mach_port_t
*object_name
) /* OUT */
1532 vm_map_offset_t map_addr
;
1533 vm_map_size_t map_size
;
1536 if (VM_MAP_NULL
== map
)
1537 return KERN_INVALID_ARGUMENT
;
1539 map_addr
= (vm_map_offset_t
)*address
;
1540 map_size
= (vm_map_size_t
)*size
;
1542 /* legacy conversion */
1543 if (VM_REGION_BASIC_INFO
== flavor
)
1544 flavor
= VM_REGION_BASIC_INFO_64
;
1546 kr
= vm_map_region(map
,
1547 &map_addr
, &map_size
,
1548 flavor
, info
, count
,
1551 *address
= map_addr
;
1557 * vm_region_64 and vm_region:
1559 * User call to obtain information about a region in
1560 * a task's address map. Currently, only one flavor is
1563 * XXX The reserved and behavior fields cannot be filled
1564 * in until the vm merge from the IK is completed, and
1565 * vm_reserve is implemented.
1567 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1573 vm_offset_t
*address
, /* IN/OUT */
1574 vm_size_t
*size
, /* OUT */
1575 vm_region_flavor_t flavor
, /* IN */
1576 vm_region_info_t info
, /* OUT */
1577 mach_msg_type_number_t
*count
, /* IN/OUT */
1578 mach_port_t
*object_name
) /* OUT */
1580 vm_map_offset_t map_addr
;
1581 vm_map_size_t map_size
;
1584 if (VM_MAP_NULL
== map
)
1585 return KERN_INVALID_ARGUMENT
;
1587 map_addr
= (vm_map_offset_t
)*address
;
1588 map_size
= (vm_map_size_t
)*size
;
1590 /* legacy conversion */
1591 if (VM_REGION_BASIC_INFO
== flavor
)
1592 flavor
= VM_REGION_BASIC_INFO_64
;
1594 kr
= vm_map_region(map
,
1595 &map_addr
, &map_size
,
1596 flavor
, info
, count
,
1599 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1600 *size
= CAST_DOWN(vm_size_t
, map_size
);
1602 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1603 return KERN_INVALID_ADDRESS
;
1610 vm_address_t
*address
, /* IN/OUT */
1611 vm_size_t
*size
, /* OUT */
1612 vm_region_flavor_t flavor
, /* IN */
1613 vm_region_info_t info
, /* OUT */
1614 mach_msg_type_number_t
*count
, /* IN/OUT */
1615 mach_port_t
*object_name
) /* OUT */
1617 vm_map_address_t map_addr
;
1618 vm_map_size_t map_size
;
1621 if (VM_MAP_NULL
== map
)
1622 return KERN_INVALID_ARGUMENT
;
1624 map_addr
= (vm_map_address_t
)*address
;
1625 map_size
= (vm_map_size_t
)*size
;
1627 kr
= vm_map_region(map
,
1628 &map_addr
, &map_size
,
1629 flavor
, info
, count
,
1632 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1633 *size
= CAST_DOWN(vm_size_t
, map_size
);
1635 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1636 return KERN_INVALID_ADDRESS
;
1641 * vm_region_recurse: A form of vm_region which follows the
1642 * submaps in a target map
1646 mach_vm_region_recurse(
1648 mach_vm_address_t
*address
,
1649 mach_vm_size_t
*size
,
1651 vm_region_recurse_info_t info
,
1652 mach_msg_type_number_t
*infoCnt
)
1654 vm_map_address_t map_addr
;
1655 vm_map_size_t map_size
;
1658 if (VM_MAP_NULL
== map
)
1659 return KERN_INVALID_ARGUMENT
;
1661 map_addr
= (vm_map_address_t
)*address
;
1662 map_size
= (vm_map_size_t
)*size
;
1664 kr
= vm_map_region_recurse_64(
1669 (vm_region_submap_info_64_t
)info
,
1672 *address
= map_addr
;
1678 * vm_region_recurse: A form of vm_region which follows the
1679 * submaps in a target map
1683 vm_region_recurse_64(
1685 vm_address_t
*address
,
1688 vm_region_recurse_info_64_t info
,
1689 mach_msg_type_number_t
*infoCnt
)
1691 vm_map_address_t map_addr
;
1692 vm_map_size_t map_size
;
1695 if (VM_MAP_NULL
== map
)
1696 return KERN_INVALID_ARGUMENT
;
1698 map_addr
= (vm_map_address_t
)*address
;
1699 map_size
= (vm_map_size_t
)*size
;
1701 kr
= vm_map_region_recurse_64(
1706 (vm_region_submap_info_64_t
)info
,
1709 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1710 *size
= CAST_DOWN(vm_size_t
, map_size
);
1712 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1713 return KERN_INVALID_ADDRESS
;
1720 vm_offset_t
*address
, /* IN/OUT */
1721 vm_size_t
*size
, /* OUT */
1722 natural_t
*depth
, /* IN/OUT */
1723 vm_region_recurse_info_t info32
, /* IN/OUT */
1724 mach_msg_type_number_t
*infoCnt
) /* IN/OUT */
1726 vm_region_submap_info_data_64_t info64
;
1727 vm_region_submap_info_t info
;
1728 vm_map_address_t map_addr
;
1729 vm_map_size_t map_size
;
1732 if (VM_MAP_NULL
== map
|| *infoCnt
< VM_REGION_SUBMAP_INFO_COUNT
)
1733 return KERN_INVALID_ARGUMENT
;
1736 map_addr
= (vm_map_address_t
)*address
;
1737 map_size
= (vm_map_size_t
)*size
;
1738 info
= (vm_region_submap_info_t
)info32
;
1739 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT_64
;
1741 kr
= vm_map_region_recurse_64(map
, &map_addr
,&map_size
,
1742 depth
, &info64
, infoCnt
);
1744 info
->protection
= info64
.protection
;
1745 info
->max_protection
= info64
.max_protection
;
1746 info
->inheritance
= info64
.inheritance
;
1747 info
->offset
= (uint32_t)info64
.offset
; /* trouble-maker */
1748 info
->user_tag
= info64
.user_tag
;
1749 info
->pages_resident
= info64
.pages_resident
;
1750 info
->pages_shared_now_private
= info64
.pages_shared_now_private
;
1751 info
->pages_swapped_out
= info64
.pages_swapped_out
;
1752 info
->pages_dirtied
= info64
.pages_dirtied
;
1753 info
->ref_count
= info64
.ref_count
;
1754 info
->shadow_depth
= info64
.shadow_depth
;
1755 info
->external_pager
= info64
.external_pager
;
1756 info
->share_mode
= info64
.share_mode
;
1757 info
->is_submap
= info64
.is_submap
;
1758 info
->behavior
= info64
.behavior
;
1759 info
->object_id
= info64
.object_id
;
1760 info
->user_wired_count
= info64
.user_wired_count
;
1762 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1763 *size
= CAST_DOWN(vm_size_t
, map_size
);
1764 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT
;
1766 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1767 return KERN_INVALID_ADDRESS
;
1772 vm_purgable_control(
1774 vm_offset_t address
,
1775 vm_purgable_t control
,
1778 if (VM_MAP_NULL
== map
)
1779 return KERN_INVALID_ARGUMENT
;
1781 return vm_map_purgable_control(map
,
1782 vm_map_trunc_page(address
),
1789 * Ordinarily, the right to allocate CPM is restricted
1790 * to privileged applications (those that can gain access
1791 * to the host priv port). Set this variable to zero if
1792 * you want to let any application allocate CPM.
1794 unsigned int vm_allocate_cpm_privileged
= 0;
1797 * Allocate memory in the specified map, with the caveat that
1798 * the memory is physically contiguous. This call may fail
1799 * if the system can't find sufficient contiguous memory.
1800 * This call may cause or lead to heart-stopping amounts of
1803 * Memory obtained from this call should be freed in the
1804 * normal way, viz., via vm_deallocate.
1808 host_priv_t host_priv
,
1814 vm_map_address_t map_addr
;
1815 vm_map_size_t map_size
;
1818 if (vm_allocate_cpm_privileged
&& HOST_PRIV_NULL
== host_priv
)
1819 return KERN_INVALID_HOST
;
1821 if (VM_MAP_NULL
== map
)
1822 return KERN_INVALID_ARGUMENT
;
1824 map_addr
= (vm_map_address_t
)*addr
;
1825 map_size
= (vm_map_size_t
)size
;
1827 kr
= vm_map_enter_cpm(map
,
1832 *addr
= CAST_DOWN(vm_address_t
, map_addr
);
1840 mach_vm_offset_t offset
,
1844 if (VM_MAP_NULL
== map
)
1845 return KERN_INVALID_ARGUMENT
;
1847 return vm_map_page_info(map
,
1848 vm_map_trunc_page(offset
),
1849 disposition
, ref_count
);
1859 if (VM_MAP_NULL
== map
)
1860 return KERN_INVALID_ARGUMENT
;
1862 return vm_map_page_info(map
,
1863 vm_map_trunc_page(offset
),
1864 disposition
, ref_count
);
1867 /* map a (whole) upl into an address space */
1872 vm_offset_t
*dst_addr
)
1874 vm_map_offset_t map_addr
;
1877 if (VM_MAP_NULL
== map
)
1878 return KERN_INVALID_ARGUMENT
;
1880 kr
= vm_map_enter_upl(map
, upl
, &map_addr
);
1881 *dst_addr
= CAST_DOWN(vm_offset_t
, map_addr
);
1890 if (VM_MAP_NULL
== map
)
1891 return KERN_INVALID_ARGUMENT
;
1893 return (vm_map_remove_upl(map
, upl
));
1896 /* Retrieve a upl for an object underlying an address range in a map */
1901 vm_map_offset_t map_offset
,
1902 upl_size_t
*upl_size
,
1904 upl_page_info_array_t page_list
,
1905 unsigned int *count
,
1907 int force_data_sync
)
1912 if (VM_MAP_NULL
== map
)
1913 return KERN_INVALID_ARGUMENT
;
1915 map_flags
= *flags
& ~UPL_NOZEROFILL
;
1916 if (force_data_sync
)
1917 map_flags
|= UPL_FORCE_DATA_SYNC
;
1919 kr
= vm_map_create_upl(map
,
1927 *flags
= (map_flags
& ~UPL_FORCE_DATA_SYNC
);
1932 __private_extern__ kern_return_t
1933 mach_memory_entry_allocate(
1934 vm_named_entry_t
*user_entry_p
,
1935 ipc_port_t
*user_handle_p
); /* forward */
1938 * mach_make_memory_entry_64
1940 * Think of it as a two-stage vm_remap() operation. First
1941 * you get a handle. Second, you get map that handle in
1942 * somewhere else. Rather than doing it all at once (and
1943 * without needing access to the other whole map).
1947 mach_make_memory_entry_64(
1948 vm_map_t target_map
,
1949 memory_object_size_t
*size
,
1950 memory_object_offset_t offset
,
1951 vm_prot_t permission
,
1952 ipc_port_t
*object_handle
,
1953 ipc_port_t parent_handle
)
1955 vm_map_version_t version
;
1956 vm_named_entry_t parent_entry
;
1957 vm_named_entry_t user_entry
;
1958 ipc_port_t user_handle
;
1962 /* needed for call to vm_map_lookup_locked */
1964 vm_object_offset_t obj_off
;
1966 vm_map_offset_t lo_offset
, hi_offset
;
1967 vm_behavior_t behavior
;
1969 vm_object_t shadow_object
;
1971 /* needed for direct map entry manipulation */
1972 vm_map_entry_t map_entry
;
1973 vm_map_entry_t next_entry
;
1975 vm_map_t original_map
= target_map
;
1976 vm_map_size_t total_size
;
1977 vm_map_size_t map_size
;
1978 vm_map_offset_t map_offset
;
1979 vm_map_offset_t local_offset
;
1980 vm_object_size_t mappable_size
;
1982 unsigned int access
;
1983 vm_prot_t protections
;
1984 unsigned int wimg_mode
;
1985 boolean_t cache_attr
= FALSE
;
1987 if (((permission
& 0x00FF0000) &
1989 MAP_MEM_NAMED_CREATE
|
1991 MAP_MEM_NAMED_REUSE
))) {
1993 * Unknown flag: reject for forward compatibility.
1995 return KERN_INVALID_VALUE
;
1998 if (parent_handle
!= IP_NULL
&&
1999 ip_kotype(parent_handle
) == IKOT_NAMED_ENTRY
) {
2000 parent_entry
= (vm_named_entry_t
) parent_handle
->ip_kobject
;
2002 parent_entry
= NULL
;
2005 protections
= permission
& VM_PROT_ALL
;
2006 access
= GET_MAP_MEM(permission
);
2008 user_handle
= IP_NULL
;
2011 map_offset
= vm_map_trunc_page(offset
);
2012 map_size
= vm_map_round_page(*size
);
2014 if (permission
& MAP_MEM_ONLY
) {
2015 boolean_t parent_is_object
;
2017 if (parent_entry
== NULL
) {
2018 return KERN_INVALID_ARGUMENT
;
2021 parent_is_object
= !(parent_entry
->is_sub_map
|| parent_entry
->is_pager
);
2022 object
= parent_entry
->backing
.object
;
2023 if(parent_is_object
&& object
!= VM_OBJECT_NULL
)
2024 wimg_mode
= object
->wimg_bits
;
2026 wimg_mode
= VM_WIMG_DEFAULT
;
2027 if((access
!= GET_MAP_MEM(parent_entry
->protection
)) &&
2028 !(parent_entry
->protection
& VM_PROT_WRITE
)) {
2029 return KERN_INVALID_RIGHT
;
2031 if(access
== MAP_MEM_IO
) {
2032 SET_MAP_MEM(access
, parent_entry
->protection
);
2033 wimg_mode
= VM_WIMG_IO
;
2034 } else if (access
== MAP_MEM_COPYBACK
) {
2035 SET_MAP_MEM(access
, parent_entry
->protection
);
2036 wimg_mode
= VM_WIMG_DEFAULT
;
2037 } else if (access
== MAP_MEM_WTHRU
) {
2038 SET_MAP_MEM(access
, parent_entry
->protection
);
2039 wimg_mode
= VM_WIMG_WTHRU
;
2040 } else if (access
== MAP_MEM_WCOMB
) {
2041 SET_MAP_MEM(access
, parent_entry
->protection
);
2042 wimg_mode
= VM_WIMG_WCOMB
;
2044 if(parent_is_object
&& object
&&
2045 (access
!= MAP_MEM_NOOP
) &&
2046 (!(object
->nophyscache
))) {
2047 if(object
->wimg_bits
!= wimg_mode
) {
2049 if ((wimg_mode
== VM_WIMG_IO
)
2050 || (wimg_mode
== VM_WIMG_WCOMB
))
2054 vm_object_lock(object
);
2055 vm_object_paging_wait(object
, THREAD_UNINT
);
2056 object
->wimg_bits
= wimg_mode
;
2057 queue_iterate(&object
->memq
,
2058 p
, vm_page_t
, listq
) {
2059 if (!p
->fictitious
) {
2060 pmap_disconnect(p
->phys_page
);
2062 pmap_sync_page_attributes_phys(p
->phys_page
);
2065 vm_object_unlock(object
);
2069 *object_handle
= IP_NULL
;
2070 return KERN_SUCCESS
;
2073 if(permission
& MAP_MEM_NAMED_CREATE
) {
2074 kr
= mach_memory_entry_allocate(&user_entry
, &user_handle
);
2075 if (kr
!= KERN_SUCCESS
) {
2076 return KERN_FAILURE
;
2080 * Force the creation of the VM object now.
2082 if (map_size
> (vm_map_size_t
) VM_MAX_ADDRESS
) {
2084 * LP64todo - for now, we can only allocate 4GB
2085 * internal objects because the default pager can't
2086 * page bigger ones. Remove this when it can.
2092 object
= vm_object_allocate(map_size
);
2093 assert(object
!= VM_OBJECT_NULL
);
2095 if (permission
& MAP_MEM_PURGABLE
) {
2096 if (! (permission
& VM_PROT_WRITE
)) {
2097 /* if we can't write, we can't purge */
2098 vm_object_deallocate(object
);
2099 kr
= KERN_INVALID_ARGUMENT
;
2102 object
->purgable
= VM_OBJECT_PURGABLE_NONVOLATILE
;
2106 * The VM object is brand new and nobody else knows about it,
2107 * so we don't need to lock it.
2110 wimg_mode
= object
->wimg_bits
;
2111 if (access
== MAP_MEM_IO
) {
2112 wimg_mode
= VM_WIMG_IO
;
2113 } else if (access
== MAP_MEM_COPYBACK
) {
2114 wimg_mode
= VM_WIMG_DEFAULT
;
2115 } else if (access
== MAP_MEM_WTHRU
) {
2116 wimg_mode
= VM_WIMG_WTHRU
;
2117 } else if (access
== MAP_MEM_WCOMB
) {
2118 wimg_mode
= VM_WIMG_WCOMB
;
2120 if (access
!= MAP_MEM_NOOP
) {
2121 object
->wimg_bits
= wimg_mode
;
2123 /* the object has no pages, so no WIMG bits to update here */
2127 * We use this path when we want to make sure that
2128 * nobody messes with the object (coalesce, for
2129 * example) before we map it.
2130 * We might want to use these objects for transposition via
2131 * vm_object_transpose() too, so we don't want any copy or
2132 * shadow objects either...
2134 object
->copy_strategy
= MEMORY_OBJECT_COPY_NONE
;
2136 user_entry
->backing
.object
= object
;
2137 user_entry
->internal
= TRUE
;
2138 user_entry
->is_sub_map
= FALSE
;
2139 user_entry
->is_pager
= FALSE
;
2140 user_entry
->offset
= 0;
2141 user_entry
->protection
= protections
;
2142 SET_MAP_MEM(access
, user_entry
->protection
);
2143 user_entry
->size
= map_size
;
2145 /* user_object pager and internal fields are not used */
2146 /* when the object field is filled in. */
2148 *size
= CAST_DOWN(vm_size_t
, map_size
);
2149 *object_handle
= user_handle
;
2150 return KERN_SUCCESS
;
2153 if (parent_entry
== NULL
||
2154 (permission
& MAP_MEM_NAMED_REUSE
)) {
2156 /* Create a named object based on address range within the task map */
2157 /* Go find the object at given address */
2160 vm_map_lock_read(target_map
);
2162 /* get the object associated with the target address */
2163 /* note we check the permission of the range against */
2164 /* that requested by the caller */
2166 kr
= vm_map_lookup_locked(&target_map
, map_offset
,
2167 protections
, &version
,
2168 &object
, &obj_off
, &prot
, &wired
, &behavior
,
2169 &lo_offset
, &hi_offset
, &real_map
);
2170 if (kr
!= KERN_SUCCESS
) {
2171 vm_map_unlock_read(target_map
);
2174 if (((prot
& protections
) != protections
)
2175 || (object
== kernel_object
)) {
2176 kr
= KERN_INVALID_RIGHT
;
2177 vm_object_unlock(object
);
2178 vm_map_unlock_read(target_map
);
2179 if(real_map
!= target_map
)
2180 vm_map_unlock_read(real_map
);
2181 if(object
== kernel_object
) {
2182 printf("Warning: Attempt to create a named"
2183 " entry from the kernel_object\n");
2188 /* We have an object, now check to see if this object */
2189 /* is suitable. If not, create a shadow and share that */
2192 * We have to unlock the VM object to avoid deadlocking with
2193 * a VM map lock (the lock ordering is map, the object), if we
2194 * need to modify the VM map to create a shadow object. Since
2195 * we might release the VM map lock below anyway, we have
2196 * to release the VM map lock now.
2197 * XXX FBDP There must be a way to avoid this double lookup...
2199 * Take an extra reference on the VM object to make sure it's
2200 * not going to disappear.
2202 vm_object_reference_locked(object
); /* extra ref to hold obj */
2203 vm_object_unlock(object
);
2205 local_map
= original_map
;
2206 local_offset
= map_offset
;
2207 if(target_map
!= local_map
) {
2208 vm_map_unlock_read(target_map
);
2209 if(real_map
!= target_map
)
2210 vm_map_unlock_read(real_map
);
2211 vm_map_lock_read(local_map
);
2212 target_map
= local_map
;
2213 real_map
= local_map
;
2216 if(!vm_map_lookup_entry(local_map
,
2217 local_offset
, &map_entry
)) {
2218 kr
= KERN_INVALID_ARGUMENT
;
2219 vm_map_unlock_read(target_map
);
2220 if(real_map
!= target_map
)
2221 vm_map_unlock_read(real_map
);
2222 vm_object_deallocate(object
); /* release extra ref */
2223 object
= VM_OBJECT_NULL
;
2226 if(!(map_entry
->is_sub_map
)) {
2227 if(map_entry
->object
.vm_object
!= object
) {
2228 kr
= KERN_INVALID_ARGUMENT
;
2229 vm_map_unlock_read(target_map
);
2230 if(real_map
!= target_map
)
2231 vm_map_unlock_read(real_map
);
2232 vm_object_deallocate(object
); /* release extra ref */
2233 object
= VM_OBJECT_NULL
;
2240 local_map
= map_entry
->object
.sub_map
;
2242 vm_map_lock_read(local_map
);
2243 vm_map_unlock_read(tmap
);
2244 target_map
= local_map
;
2245 real_map
= local_map
;
2246 local_offset
= local_offset
- map_entry
->vme_start
;
2247 local_offset
+= map_entry
->offset
;
2252 * We found the VM map entry, lock the VM object again.
2254 vm_object_lock(object
);
2255 if(map_entry
->wired_count
) {
2256 /* JMM - The check below should be reworked instead. */
2257 object
->true_share
= TRUE
;
2259 if(((map_entry
->max_protection
) & protections
) != protections
) {
2260 kr
= KERN_INVALID_RIGHT
;
2261 vm_object_unlock(object
);
2262 vm_map_unlock_read(target_map
);
2263 if(real_map
!= target_map
)
2264 vm_map_unlock_read(real_map
);
2265 vm_object_deallocate(object
);
2266 object
= VM_OBJECT_NULL
;
2270 mappable_size
= hi_offset
- obj_off
;
2271 total_size
= map_entry
->vme_end
- map_entry
->vme_start
;
2272 if(map_size
> mappable_size
) {
2273 /* try to extend mappable size if the entries */
2274 /* following are from the same object and are */
2276 next_entry
= map_entry
->vme_next
;
2277 /* lets see if the next map entry is still */
2278 /* pointing at this object and is contiguous */
2279 while(map_size
> mappable_size
) {
2280 if((next_entry
->object
.vm_object
== object
) &&
2281 (next_entry
->vme_start
==
2282 next_entry
->vme_prev
->vme_end
) &&
2283 (next_entry
->offset
==
2284 next_entry
->vme_prev
->offset
+
2285 (next_entry
->vme_prev
->vme_end
-
2286 next_entry
->vme_prev
->vme_start
))) {
2287 if(((next_entry
->max_protection
)
2288 & protections
) != protections
) {
2291 if (next_entry
->needs_copy
!=
2292 map_entry
->needs_copy
)
2294 mappable_size
+= next_entry
->vme_end
2295 - next_entry
->vme_start
;
2296 total_size
+= next_entry
->vme_end
2297 - next_entry
->vme_start
;
2298 next_entry
= next_entry
->vme_next
;
2306 if(object
->internal
) {
2307 /* vm_map_lookup_locked will create a shadow if */
2308 /* needs_copy is set but does not check for the */
2309 /* other two conditions shown. It is important to */
2310 /* set up an object which will not be pulled from */
2313 if ((map_entry
->needs_copy
|| object
->shadowed
||
2314 (object
->size
> total_size
))
2315 && !object
->true_share
) {
2317 * We have to unlock the VM object before
2318 * trying to upgrade the VM map lock, to
2319 * honor lock ordering (map then object).
2320 * Otherwise, we would deadlock if another
2321 * thread holds a read lock on the VM map and
2322 * is trying to acquire the VM object's lock.
2323 * We still hold an extra reference on the
2324 * VM object, guaranteeing that it won't
2327 vm_object_unlock(object
);
2329 if (vm_map_lock_read_to_write(target_map
)) {
2331 * We couldn't upgrade our VM map lock
2332 * from "read" to "write" and we lost
2334 * Start all over again...
2336 vm_object_deallocate(object
); /* extra ref */
2337 target_map
= original_map
;
2340 vm_object_lock(object
);
2343 * JMM - We need to avoid coming here when the object
2344 * is wired by anybody, not just the current map. Why
2345 * couldn't we use the standard vm_object_copy_quickly()
2349 /* create a shadow object */
2350 vm_object_shadow(&map_entry
->object
.vm_object
,
2351 &map_entry
->offset
, total_size
);
2352 shadow_object
= map_entry
->object
.vm_object
;
2353 vm_object_unlock(object
);
2355 vm_object_pmap_protect(
2356 object
, map_entry
->offset
,
2358 ((map_entry
->is_shared
2359 || target_map
->mapped
)
2362 map_entry
->vme_start
,
2363 map_entry
->protection
& ~VM_PROT_WRITE
);
2364 total_size
-= (map_entry
->vme_end
2365 - map_entry
->vme_start
);
2366 next_entry
= map_entry
->vme_next
;
2367 map_entry
->needs_copy
= FALSE
;
2368 while (total_size
) {
2369 if(next_entry
->object
.vm_object
== object
) {
2370 shadow_object
->ref_count
++;
2371 vm_object_res_reference(shadow_object
);
2372 next_entry
->object
.vm_object
2374 vm_object_deallocate(object
);
2376 = next_entry
->vme_prev
->offset
+
2377 (next_entry
->vme_prev
->vme_end
2378 - next_entry
->vme_prev
->vme_start
);
2379 next_entry
->needs_copy
= FALSE
;
2381 panic("mach_make_memory_entry_64:"
2382 " map entries out of sync\n");
2386 - next_entry
->vme_start
;
2387 next_entry
= next_entry
->vme_next
;
2391 * Transfer our extra reference to the
2394 vm_object_reference_locked(shadow_object
);
2395 vm_object_deallocate(object
); /* extra ref */
2396 object
= shadow_object
;
2398 obj_off
= (local_offset
- map_entry
->vme_start
)
2399 + map_entry
->offset
;
2401 vm_map_lock_write_to_read(target_map
);
2402 vm_object_lock(object
);
2407 /* note: in the future we can (if necessary) allow for */
2408 /* memory object lists, this will better support */
2409 /* fragmentation, but is it necessary? The user should */
2410 /* be encouraged to create address space oriented */
2411 /* shared objects from CLEAN memory regions which have */
2412 /* a known and defined history. i.e. no inheritence */
2413 /* share, make this call before making the region the */
2414 /* target of ipc's, etc. The code above, protecting */
2415 /* against delayed copy, etc. is mostly defensive. */
2417 wimg_mode
= object
->wimg_bits
;
2418 if(!(object
->nophyscache
)) {
2419 if(access
== MAP_MEM_IO
) {
2420 wimg_mode
= VM_WIMG_IO
;
2421 } else if (access
== MAP_MEM_COPYBACK
) {
2422 wimg_mode
= VM_WIMG_USE_DEFAULT
;
2423 } else if (access
== MAP_MEM_WTHRU
) {
2424 wimg_mode
= VM_WIMG_WTHRU
;
2425 } else if (access
== MAP_MEM_WCOMB
) {
2426 wimg_mode
= VM_WIMG_WCOMB
;
2430 object
->true_share
= TRUE
;
2431 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
2432 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
2435 * The memory entry now points to this VM object and we
2436 * need to hold a reference on the VM object. Use the extra
2437 * reference we took earlier to keep the object alive when we
2441 vm_map_unlock_read(target_map
);
2442 if(real_map
!= target_map
)
2443 vm_map_unlock_read(real_map
);
2445 if(object
->wimg_bits
!= wimg_mode
) {
2448 vm_object_paging_wait(object
, THREAD_UNINT
);
2450 if ((wimg_mode
== VM_WIMG_IO
)
2451 || (wimg_mode
== VM_WIMG_WCOMB
))
2456 queue_iterate(&object
->memq
,
2457 p
, vm_page_t
, listq
) {
2458 if (!p
->fictitious
) {
2459 pmap_disconnect(p
->phys_page
);
2461 pmap_sync_page_attributes_phys(p
->phys_page
);
2464 object
->wimg_bits
= wimg_mode
;
2467 /* the size of mapped entry that overlaps with our region */
2468 /* which is targeted for share. */
2469 /* (entry_end - entry_start) - */
2470 /* offset of our beg addr within entry */
2471 /* it corresponds to this: */
2473 if(map_size
> mappable_size
)
2474 map_size
= mappable_size
;
2476 if (permission
& MAP_MEM_NAMED_REUSE
) {
2478 * Compare what we got with the "parent_entry".
2479 * If they match, re-use the "parent_entry" instead
2480 * of creating a new one.
2482 if (parent_entry
!= NULL
&&
2483 parent_entry
->backing
.object
== object
&&
2484 parent_entry
->internal
== object
->internal
&&
2485 parent_entry
->is_sub_map
== FALSE
&&
2486 parent_entry
->is_pager
== FALSE
&&
2487 parent_entry
->offset
== obj_off
&&
2488 parent_entry
->protection
== protections
&&
2489 parent_entry
->size
== map_size
) {
2491 * We have a match: re-use "parent_entry".
2493 /* release our extra reference on object */
2494 vm_object_unlock(object
);
2495 vm_object_deallocate(object
);
2496 /* parent_entry->ref_count++; XXX ? */
2497 /* Get an extra send-right on handle */
2498 ipc_port_copy_send(parent_handle
);
2499 *object_handle
= parent_handle
;
2500 return KERN_SUCCESS
;
2503 * No match: we need to create a new entry.
2509 vm_object_unlock(object
);
2510 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2512 /* release our unused reference on the object */
2513 vm_object_deallocate(object
);
2514 return KERN_FAILURE
;
2517 user_entry
->backing
.object
= object
;
2518 user_entry
->internal
= object
->internal
;
2519 user_entry
->is_sub_map
= FALSE
;
2520 user_entry
->is_pager
= FALSE
;
2521 user_entry
->offset
= obj_off
;
2522 user_entry
->protection
= permission
;
2523 user_entry
->size
= map_size
;
2525 /* user_object pager and internal fields are not used */
2526 /* when the object field is filled in. */
2528 *size
= CAST_DOWN(vm_size_t
, map_size
);
2529 *object_handle
= user_handle
;
2530 return KERN_SUCCESS
;
2533 /* The new object will be base on an existing named object */
2535 if (parent_entry
== NULL
) {
2536 kr
= KERN_INVALID_ARGUMENT
;
2539 if((offset
+ map_size
) > parent_entry
->size
) {
2540 kr
= KERN_INVALID_ARGUMENT
;
2544 if((protections
& parent_entry
->protection
) != protections
) {
2545 kr
= KERN_PROTECTION_FAILURE
;
2549 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2555 user_entry
->size
= map_size
;
2556 user_entry
->offset
= parent_entry
->offset
+ map_offset
;
2557 user_entry
->is_sub_map
= parent_entry
->is_sub_map
;
2558 user_entry
->is_pager
= parent_entry
->is_pager
;
2559 user_entry
->internal
= parent_entry
->internal
;
2560 user_entry
->protection
= protections
;
2562 if(access
!= MAP_MEM_NOOP
) {
2563 SET_MAP_MEM(access
, user_entry
->protection
);
2566 if(parent_entry
->is_sub_map
) {
2567 user_entry
->backing
.map
= parent_entry
->backing
.map
;
2568 vm_map_lock(user_entry
->backing
.map
);
2569 user_entry
->backing
.map
->ref_count
++;
2570 vm_map_unlock(user_entry
->backing
.map
);
2572 else if (parent_entry
->is_pager
) {
2573 user_entry
->backing
.pager
= parent_entry
->backing
.pager
;
2574 /* JMM - don't we need a reference here? */
2576 object
= parent_entry
->backing
.object
;
2577 assert(object
!= VM_OBJECT_NULL
);
2578 user_entry
->backing
.object
= object
;
2579 /* we now point to this object, hold on */
2580 vm_object_reference(object
);
2581 vm_object_lock(object
);
2582 object
->true_share
= TRUE
;
2583 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
2584 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
2585 vm_object_unlock(object
);
2587 *size
= CAST_DOWN(vm_size_t
, map_size
);
2588 *object_handle
= user_handle
;
2589 return KERN_SUCCESS
;
2593 if (user_handle
!= IP_NULL
) {
2594 ipc_port_dealloc_kernel(user_handle
);
2596 if (user_entry
!= NULL
) {
2597 kfree(user_entry
, sizeof *user_entry
);
2603 _mach_make_memory_entry(
2604 vm_map_t target_map
,
2605 memory_object_size_t
*size
,
2606 memory_object_offset_t offset
,
2607 vm_prot_t permission
,
2608 ipc_port_t
*object_handle
,
2609 ipc_port_t parent_entry
)
2611 memory_object_offset_t mo_size
;
2614 mo_size
= (memory_object_offset_t
)*size
;
2615 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
2616 (memory_object_offset_t
)offset
, permission
, object_handle
,
2623 mach_make_memory_entry(
2624 vm_map_t target_map
,
2627 vm_prot_t permission
,
2628 ipc_port_t
*object_handle
,
2629 ipc_port_t parent_entry
)
2631 memory_object_offset_t mo_size
;
2634 mo_size
= (memory_object_offset_t
)*size
;
2635 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
2636 (memory_object_offset_t
)offset
, permission
, object_handle
,
2638 *size
= CAST_DOWN(vm_size_t
, mo_size
);
2645 * Set or clear the map's wiring_required flag. This flag, if set,
2646 * will cause all future virtual memory allocation to allocate
2647 * user wired memory. Unwiring pages wired down as a result of
2648 * this routine is done with the vm_wire interface.
2653 boolean_t must_wire
)
2655 if (map
== VM_MAP_NULL
)
2656 return(KERN_INVALID_ARGUMENT
);
2659 map
->wiring_required
= TRUE
;
2661 map
->wiring_required
= FALSE
;
2663 return(KERN_SUCCESS
);
2666 __private_extern__ kern_return_t
2667 mach_memory_entry_allocate(
2668 vm_named_entry_t
*user_entry_p
,
2669 ipc_port_t
*user_handle_p
)
2671 vm_named_entry_t user_entry
;
2672 ipc_port_t user_handle
;
2673 ipc_port_t previous
;
2675 user_entry
= (vm_named_entry_t
) kalloc(sizeof *user_entry
);
2676 if (user_entry
== NULL
)
2677 return KERN_FAILURE
;
2679 named_entry_lock_init(user_entry
);
2681 user_handle
= ipc_port_alloc_kernel();
2682 if (user_handle
== IP_NULL
) {
2683 kfree(user_entry
, sizeof *user_entry
);
2684 return KERN_FAILURE
;
2686 ip_lock(user_handle
);
2688 /* make a sonce right */
2689 user_handle
->ip_sorights
++;
2690 ip_reference(user_handle
);
2692 user_handle
->ip_destination
= IP_NULL
;
2693 user_handle
->ip_receiver_name
= MACH_PORT_NULL
;
2694 user_handle
->ip_receiver
= ipc_space_kernel
;
2696 /* make a send right */
2697 user_handle
->ip_mscount
++;
2698 user_handle
->ip_srights
++;
2699 ip_reference(user_handle
);
2701 ipc_port_nsrequest(user_handle
, 1, user_handle
, &previous
);
2702 /* nsrequest unlocks user_handle */
2704 user_entry
->backing
.pager
= NULL
;
2705 user_entry
->is_sub_map
= FALSE
;
2706 user_entry
->is_pager
= FALSE
;
2707 user_entry
->size
= 0;
2708 user_entry
->internal
= FALSE
;
2709 user_entry
->ref_count
= 1;
2711 ipc_kobject_set(user_handle
, (ipc_kobject_t
) user_entry
,
2714 *user_entry_p
= user_entry
;
2715 *user_handle_p
= user_handle
;
2717 return KERN_SUCCESS
;
2721 * mach_memory_object_memory_entry_64
2723 * Create a named entry backed by the provided pager.
2725 * JMM - we need to hold a reference on the pager -
2726 * and release it when the named entry is destroyed.
2729 mach_memory_object_memory_entry_64(
2732 vm_object_offset_t size
,
2733 vm_prot_t permission
,
2734 memory_object_t pager
,
2735 ipc_port_t
*entry_handle
)
2737 unsigned int access
;
2738 vm_named_entry_t user_entry
;
2739 ipc_port_t user_handle
;
2741 if (host
== HOST_NULL
)
2742 return(KERN_INVALID_HOST
);
2744 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2746 return KERN_FAILURE
;
2749 user_entry
->backing
.pager
= pager
;
2750 user_entry
->size
= size
;
2751 user_entry
->offset
= 0;
2752 user_entry
->protection
= permission
& VM_PROT_ALL
;
2753 access
= GET_MAP_MEM(permission
);
2754 SET_MAP_MEM(access
, user_entry
->protection
);
2755 user_entry
->internal
= internal
;
2756 user_entry
->is_sub_map
= FALSE
;
2757 user_entry
->is_pager
= TRUE
;
2758 assert(user_entry
->ref_count
== 1);
2760 *entry_handle
= user_handle
;
2761 return KERN_SUCCESS
;
2765 mach_memory_object_memory_entry(
2769 vm_prot_t permission
,
2770 memory_object_t pager
,
2771 ipc_port_t
*entry_handle
)
2773 return mach_memory_object_memory_entry_64( host
, internal
,
2774 (vm_object_offset_t
)size
, permission
, pager
, entry_handle
);
2779 mach_memory_entry_purgable_control(
2780 ipc_port_t entry_port
,
2781 vm_purgable_t control
,
2785 vm_named_entry_t mem_entry
;
2788 if (entry_port
== IP_NULL
||
2789 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
2790 return KERN_INVALID_ARGUMENT
;
2793 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
2795 named_entry_lock(mem_entry
);
2797 if (mem_entry
->is_sub_map
|| mem_entry
->is_pager
) {
2798 named_entry_unlock(mem_entry
);
2799 return KERN_INVALID_ARGUMENT
;
2802 object
= mem_entry
->backing
.object
;
2803 if (object
== VM_OBJECT_NULL
) {
2804 named_entry_unlock(mem_entry
);
2805 return KERN_INVALID_ARGUMENT
;
2808 vm_object_lock(object
);
2810 /* check that named entry covers entire object ? */
2811 if (mem_entry
->offset
!= 0 || object
->size
!= mem_entry
->size
) {
2812 vm_object_unlock(object
);
2813 named_entry_unlock(mem_entry
);
2814 return KERN_INVALID_ARGUMENT
;
2817 named_entry_unlock(mem_entry
);
2819 kr
= vm_object_purgable_control(object
, control
, state
);
2821 vm_object_unlock(object
);
2827 * mach_memory_entry_port_release:
2829 * Release a send right on a named entry port. This is the correct
2830 * way to destroy a named entry. When the last right on the port is
2831 * released, ipc_kobject_destroy() will call mach_destroy_memory_entry().
2834 mach_memory_entry_port_release(
2837 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
2838 ipc_port_release_send(port
);
2842 * mach_destroy_memory_entry:
2844 * Drops a reference on a memory entry and destroys the memory entry if
2845 * there are no more references on it.
2846 * NOTE: This routine should not be called to destroy a memory entry from the
2847 * kernel, as it will not release the Mach port associated with the memory
2848 * entry. The proper way to destroy a memory entry in the kernel is to
2849 * call mach_memort_entry_port_release() to release the kernel's send-right on
2850 * the memory entry's port. When the last send right is released, the memory
2851 * entry will be destroyed via ipc_kobject_destroy().
2854 mach_destroy_memory_entry(
2857 vm_named_entry_t named_entry
;
2859 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
2860 #endif /* MACH_ASSERT */
2861 named_entry
= (vm_named_entry_t
)port
->ip_kobject
;
2862 mutex_lock(&(named_entry
)->Lock
);
2863 named_entry
->ref_count
-= 1;
2864 if(named_entry
->ref_count
== 0) {
2865 if (named_entry
->is_sub_map
) {
2866 vm_map_deallocate(named_entry
->backing
.map
);
2867 } else if (!named_entry
->is_pager
) {
2868 /* release the memory object we've been pointing to */
2869 vm_object_deallocate(named_entry
->backing
.object
);
2870 } /* else JMM - need to drop reference on pager in that case */
2872 mutex_unlock(&(named_entry
)->Lock
);
2874 kfree((void *) port
->ip_kobject
,
2875 sizeof (struct vm_named_entry
));
2877 mutex_unlock(&(named_entry
)->Lock
);
2883 set_dp_control_port(
2884 host_priv_t host_priv
,
2885 ipc_port_t control_port
)
2887 if (host_priv
== HOST_PRIV_NULL
)
2888 return (KERN_INVALID_HOST
);
2890 if (IP_VALID(dynamic_pager_control_port
))
2891 ipc_port_release_send(dynamic_pager_control_port
);
2893 dynamic_pager_control_port
= control_port
;
2894 return KERN_SUCCESS
;
2898 get_dp_control_port(
2899 host_priv_t host_priv
,
2900 ipc_port_t
*control_port
)
2902 if (host_priv
== HOST_PRIV_NULL
)
2903 return (KERN_INVALID_HOST
);
2905 *control_port
= ipc_port_copy_send(dynamic_pager_control_port
);
2906 return KERN_SUCCESS
;
2910 /* ******* Temporary Internal calls to UPL for BSD ***** */
2912 extern int kernel_upl_map(
2915 vm_offset_t
*dst_addr
);
2917 extern int kernel_upl_unmap(
2921 extern int kernel_upl_commit(
2923 upl_page_info_t
*pl
,
2924 mach_msg_type_number_t count
);
2926 extern int kernel_upl_commit_range(
2928 upl_offset_t offset
,
2931 upl_page_info_array_t pl
,
2932 mach_msg_type_number_t count
);
2934 extern int kernel_upl_abort(
2938 extern int kernel_upl_abort_range(
2940 upl_offset_t offset
,
2949 vm_offset_t
*dst_addr
)
2951 return vm_upl_map(map
, upl
, dst_addr
);
2960 return vm_upl_unmap(map
, upl
);
2966 upl_page_info_t
*pl
,
2967 mach_msg_type_number_t count
)
2971 kr
= upl_commit(upl
, pl
, count
);
2972 upl_deallocate(upl
);
2978 kernel_upl_commit_range(
2980 upl_offset_t offset
,
2983 upl_page_info_array_t pl
,
2984 mach_msg_type_number_t count
)
2986 boolean_t finished
= FALSE
;
2989 if (flags
& UPL_COMMIT_FREE_ON_EMPTY
)
2990 flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
2992 kr
= upl_commit_range(upl
, offset
, size
, flags
, pl
, count
, &finished
);
2994 if ((flags
& UPL_COMMIT_NOTIFY_EMPTY
) && finished
)
2995 upl_deallocate(upl
);
3001 kernel_upl_abort_range(
3003 upl_offset_t offset
,
3008 boolean_t finished
= FALSE
;
3010 if (abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
)
3011 abort_flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
3013 kr
= upl_abort_range(upl
, offset
, size
, abort_flags
, &finished
);
3015 if ((abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
) && finished
)
3016 upl_deallocate(upl
);
3028 kr
= upl_abort(upl
, abort_type
);
3029 upl_deallocate(upl
);
3034 * Now a kernel-private interface (for BootCache
3035 * use only). Need a cleaner way to create an
3036 * empty vm_map() and return a handle to it.
3040 vm_region_object_create(
3041 __unused vm_map_t target_map
,
3043 ipc_port_t
*object_handle
)
3045 vm_named_entry_t user_entry
;
3046 ipc_port_t user_handle
;
3050 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
3052 return KERN_FAILURE
;
3055 /* Create a named object based on a submap of specified size */
3057 new_map
= vm_map_create(PMAP_NULL
, VM_MAP_MIN_ADDRESS
,
3058 vm_map_round_page(size
), TRUE
);
3060 user_entry
->backing
.map
= new_map
;
3061 user_entry
->internal
= TRUE
;
3062 user_entry
->is_sub_map
= TRUE
;
3063 user_entry
->offset
= 0;
3064 user_entry
->protection
= VM_PROT_ALL
;
3065 user_entry
->size
= size
;
3066 assert(user_entry
->ref_count
== 1);
3068 *object_handle
= user_handle
;
3069 return KERN_SUCCESS
;
3073 ppnum_t
vm_map_get_phys_page( /* forward */
3075 vm_offset_t offset
);
3078 vm_map_get_phys_page(
3082 vm_object_offset_t offset
;
3084 vm_map_offset_t map_offset
;
3085 vm_map_entry_t entry
;
3086 ppnum_t phys_page
= 0;
3088 map_offset
= vm_map_trunc_page(addr
);
3091 while (vm_map_lookup_entry(map
, map_offset
, &entry
)) {
3093 if (entry
->object
.vm_object
== VM_OBJECT_NULL
) {
3097 if (entry
->is_sub_map
) {
3099 vm_map_lock(entry
->object
.sub_map
);
3101 map
= entry
->object
.sub_map
;
3102 map_offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3103 vm_map_unlock(old_map
);
3106 if (entry
->object
.vm_object
->phys_contiguous
) {
3107 /* These are not standard pageable memory mappings */
3108 /* If they are not present in the object they will */
3109 /* have to be picked up from the pager through the */
3110 /* fault mechanism. */
3111 if(entry
->object
.vm_object
->shadow_offset
== 0) {
3112 /* need to call vm_fault */
3114 vm_fault(map
, map_offset
, VM_PROT_NONE
,
3115 FALSE
, THREAD_UNINT
, NULL
, 0);
3119 offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3120 phys_page
= (ppnum_t
)
3121 ((entry
->object
.vm_object
->shadow_offset
3126 offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3127 object
= entry
->object
.vm_object
;
3128 vm_object_lock(object
);
3130 vm_page_t dst_page
= vm_page_lookup(object
,offset
);
3131 if(dst_page
== VM_PAGE_NULL
) {
3132 if(object
->shadow
) {
3133 vm_object_t old_object
;
3134 vm_object_lock(object
->shadow
);
3135 old_object
= object
;
3136 offset
= offset
+ object
->shadow_offset
;
3137 object
= object
->shadow
;
3138 vm_object_unlock(old_object
);
3140 vm_object_unlock(object
);
3144 phys_page
= (ppnum_t
)(dst_page
->phys_page
);
3145 vm_object_unlock(object
);
3159 kern_return_t
kernel_object_iopl_request( /* forward */
3160 vm_named_entry_t named_entry
,
3161 memory_object_offset_t offset
,
3162 vm_size_t
*upl_size
,
3164 upl_page_info_array_t user_page_list
,
3165 unsigned int *page_list_count
,
3169 kernel_object_iopl_request(
3170 vm_named_entry_t named_entry
,
3171 memory_object_offset_t offset
,
3172 vm_size_t
*upl_size
,
3174 upl_page_info_array_t user_page_list
,
3175 unsigned int *page_list_count
,
3183 caller_flags
= *flags
;
3185 if (caller_flags
& ~UPL_VALID_FLAGS
) {
3187 * For forward compatibility's sake,
3188 * reject any unknown flag.
3190 return KERN_INVALID_VALUE
;
3193 /* a few checks to make sure user is obeying rules */
3194 if(*upl_size
== 0) {
3195 if(offset
>= named_entry
->size
)
3196 return(KERN_INVALID_RIGHT
);
3197 *upl_size
= named_entry
->size
- offset
;
3199 if(caller_flags
& UPL_COPYOUT_FROM
) {
3200 if((named_entry
->protection
& VM_PROT_READ
)
3202 return(KERN_INVALID_RIGHT
);
3205 if((named_entry
->protection
&
3206 (VM_PROT_READ
| VM_PROT_WRITE
))
3207 != (VM_PROT_READ
| VM_PROT_WRITE
)) {
3208 return(KERN_INVALID_RIGHT
);
3211 if(named_entry
->size
< (offset
+ *upl_size
))
3212 return(KERN_INVALID_ARGUMENT
);
3214 /* the callers parameter offset is defined to be the */
3215 /* offset from beginning of named entry offset in object */
3216 offset
= offset
+ named_entry
->offset
;
3218 if(named_entry
->is_sub_map
)
3219 return (KERN_INVALID_ARGUMENT
);
3221 named_entry_lock(named_entry
);
3223 if (named_entry
->is_pager
) {
3224 object
= vm_object_enter(named_entry
->backing
.pager
,
3225 named_entry
->offset
+ named_entry
->size
,
3226 named_entry
->internal
,
3229 if (object
== VM_OBJECT_NULL
) {
3230 named_entry_unlock(named_entry
);
3231 return(KERN_INVALID_OBJECT
);
3234 /* JMM - drop reference on the pager here? */
3236 /* create an extra reference for the object */
3237 vm_object_lock(object
);
3238 vm_object_reference_locked(object
);
3239 named_entry
->backing
.object
= object
;
3240 named_entry
->is_pager
= FALSE
;
3241 named_entry_unlock(named_entry
);
3243 /* wait for object (if any) to be ready */
3244 if (!named_entry
->internal
) {
3245 while (!object
->pager_ready
) {
3246 vm_object_wait(object
,
3247 VM_OBJECT_EVENT_PAGER_READY
,
3249 vm_object_lock(object
);
3252 vm_object_unlock(object
);
3255 /* This is the case where we are going to operate */
3256 /* an an already known object. If the object is */
3257 /* not ready it is internal. An external */
3258 /* object cannot be mapped until it is ready */
3259 /* we can therefore avoid the ready check */
3261 object
= named_entry
->backing
.object
;
3262 vm_object_reference(object
);
3263 named_entry_unlock(named_entry
);
3266 if (!object
->private) {
3267 if (*upl_size
> (MAX_UPL_TRANSFER
*PAGE_SIZE
))
3268 *upl_size
= (MAX_UPL_TRANSFER
*PAGE_SIZE
);
3269 if (object
->phys_contiguous
) {
3270 *flags
= UPL_PHYS_CONTIG
;
3275 *flags
= UPL_DEV_MEMORY
| UPL_PHYS_CONTIG
;
3278 ret
= vm_object_iopl_request(object
,
3285 vm_object_deallocate(object
);