2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
54 * Author: Avadis Tevanian, Jr., Michael Wayne Young
56 * User-exported virtual memory functions.
62 #include <mach/boolean.h>
63 #include <mach/kern_return.h>
64 #include <mach/mach_types.h> /* to get vm_address_t */
65 #include <mach/memory_object.h>
66 #include <mach/std_types.h> /* to get pointer_t */
68 #include <mach/vm_attributes.h>
69 #include <mach/vm_param.h>
70 #include <mach/vm_statistics.h>
71 #include <mach/mach_syscalls.h>
73 #include <mach/host_priv_server.h>
74 #include <mach/mach_vm_server.h>
75 #include <mach/shared_memory_server.h>
76 #include <mach/vm_map_server.h>
77 #include <vm/vm_shared_memory_server.h>
79 #include <kern/host.h>
80 #include <kern/kalloc.h>
81 #include <kern/task.h>
82 #include <kern/misc_protos.h>
83 #include <vm/vm_fault.h>
84 #include <vm/vm_map.h>
85 #include <vm/vm_object.h>
86 #include <vm/vm_page.h>
87 #include <vm/memory_object.h>
88 #include <vm/vm_pageout.h>
89 #include <vm/vm_protos.h>
91 vm_size_t upl_offset_to_pagelist
= 0;
97 ipc_port_t dynamic_pager_control_port
=NULL
;
100 * mach_vm_allocate allocates "zero fill" memory in the specfied
106 mach_vm_offset_t
*addr
,
110 vm_map_offset_t map_addr
;
111 vm_map_size_t map_size
;
112 kern_return_t result
;
113 boolean_t anywhere
= ((VM_FLAGS_ANYWHERE
& flags
) != 0);
115 if (map
== VM_MAP_NULL
)
116 return(KERN_INVALID_ARGUMENT
);
119 return(KERN_SUCCESS
);
124 * No specific address requested, so start candidate address
125 * search at the minimum address in the map. However, if that
126 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
127 * allocations of PAGEZERO to explicit requests since its
128 * normal use is to catch dereferences of NULL and many
129 * applications also treat pointers with a value of 0 as
130 * special and suddenly having address 0 contain useable
131 * memory would tend to confuse those applications.
133 map_addr
= vm_map_min(map
);
135 map_addr
+= PAGE_SIZE
;
137 map_addr
= vm_map_trunc_page(*addr
);
138 map_size
= vm_map_round_page(size
);
140 return(KERN_INVALID_ARGUMENT
);
143 result
= vm_map_enter(
150 (vm_object_offset_t
)0,
162 * Legacy routine that allocates "zero fill" memory in the specfied
163 * map (which is limited to the same size as the kernel).
172 vm_map_offset_t map_addr
;
173 vm_map_size_t map_size
;
174 kern_return_t result
;
175 boolean_t anywhere
= ((VM_FLAGS_ANYWHERE
& flags
) != 0);
177 if (map
== VM_MAP_NULL
)
178 return(KERN_INVALID_ARGUMENT
);
181 return(KERN_SUCCESS
);
186 * No specific address requested, so start candidate address
187 * search at the minimum address in the map. However, if that
188 * minimum is 0, bump it up by PAGE_SIZE. We want to limit
189 * allocations of PAGEZERO to explicit requests since its
190 * normal use is to catch dereferences of NULL and many
191 * applications also treat pointers with a value of 0 as
192 * special and suddenly having address 0 contain useable
193 * memory would tend to confuse those applications.
195 map_addr
= vm_map_min(map
);
197 map_addr
+= PAGE_SIZE
;
199 map_addr
= vm_map_trunc_page(*addr
);
200 map_size
= vm_map_round_page(size
);
202 return(KERN_INVALID_ARGUMENT
);
205 result
= vm_map_enter(
212 (vm_object_offset_t
)0,
218 *addr
= CAST_DOWN(vm_offset_t
, map_addr
);
223 * mach_vm_deallocate -
224 * deallocates the specified range of addresses in the
225 * specified address map.
230 mach_vm_offset_t start
,
233 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
234 return(KERN_INVALID_ARGUMENT
);
236 if (size
== (mach_vm_offset_t
) 0)
237 return(KERN_SUCCESS
);
239 return(vm_map_remove(map
, vm_map_trunc_page(start
),
240 vm_map_round_page(start
+size
), VM_MAP_NO_FLAGS
));
245 * deallocates the specified range of addresses in the
246 * specified address map (limited to addresses the same
247 * size as the kernel).
251 register vm_map_t map
,
255 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
256 return(KERN_INVALID_ARGUMENT
);
258 if (size
== (vm_offset_t
) 0)
259 return(KERN_SUCCESS
);
261 return(vm_map_remove(map
, vm_map_trunc_page(start
),
262 vm_map_round_page(start
+size
), VM_MAP_NO_FLAGS
));
267 * Sets the inheritance of the specified range in the
273 mach_vm_offset_t start
,
275 vm_inherit_t new_inheritance
)
277 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
278 (new_inheritance
> VM_INHERIT_LAST_VALID
))
279 return(KERN_INVALID_ARGUMENT
);
284 return(vm_map_inherit(map
,
285 vm_map_trunc_page(start
),
286 vm_map_round_page(start
+size
),
292 * Sets the inheritance of the specified range in the
293 * specified map (range limited to addresses
297 register vm_map_t map
,
300 vm_inherit_t new_inheritance
)
302 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
303 (new_inheritance
> VM_INHERIT_LAST_VALID
))
304 return(KERN_INVALID_ARGUMENT
);
309 return(vm_map_inherit(map
,
310 vm_map_trunc_page(start
),
311 vm_map_round_page(start
+size
),
317 * Sets the protection of the specified range in the
324 mach_vm_offset_t start
,
326 boolean_t set_maximum
,
327 vm_prot_t new_protection
)
329 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
330 (new_protection
& ~(VM_PROT_ALL
| VM_PROT_COPY
)))
331 return(KERN_INVALID_ARGUMENT
);
336 return(vm_map_protect(map
,
337 vm_map_trunc_page(start
),
338 vm_map_round_page(start
+size
),
345 * Sets the protection of the specified range in the
346 * specified map. Addressability of the range limited
347 * to the same size as the kernel.
355 boolean_t set_maximum
,
356 vm_prot_t new_protection
)
358 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
) ||
359 (new_protection
& ~(VM_PROT_ALL
| VM_PROT_COPY
)))
360 return(KERN_INVALID_ARGUMENT
);
365 return(vm_map_protect(map
,
366 vm_map_trunc_page(start
),
367 vm_map_round_page(start
+size
),
373 * mach_vm_machine_attributes -
374 * Handle machine-specific attributes for a mapping, such
375 * as cachability, migrability, etc.
378 mach_vm_machine_attribute(
380 mach_vm_address_t addr
,
382 vm_machine_attribute_t attribute
,
383 vm_machine_attribute_val_t
* value
) /* IN/OUT */
385 if ((map
== VM_MAP_NULL
) || (addr
+ size
< addr
))
386 return(KERN_INVALID_ARGUMENT
);
391 return vm_map_machine_attribute(map
,
392 vm_map_trunc_page(addr
),
393 vm_map_round_page(addr
+size
),
399 * vm_machine_attribute -
400 * Handle machine-specific attributes for a mapping, such
401 * as cachability, migrability, etc. Limited addressability
402 * (same range limits as for the native kernel map).
405 vm_machine_attribute(
409 vm_machine_attribute_t attribute
,
410 vm_machine_attribute_val_t
* value
) /* IN/OUT */
412 if ((map
== VM_MAP_NULL
) || (addr
+ size
< addr
))
413 return(KERN_INVALID_ARGUMENT
);
418 return vm_map_machine_attribute(map
,
419 vm_map_trunc_page(addr
),
420 vm_map_round_page(addr
+size
),
427 * Read/copy a range from one address space and return it to the caller.
429 * It is assumed that the address for the returned memory is selected by
430 * the IPC implementation as part of receiving the reply to this call.
431 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
432 * that gets returned.
434 * JMM - because of mach_msg_type_number_t, this call is limited to a
435 * single 4GB region at this time.
441 mach_vm_address_t addr
,
444 mach_msg_type_number_t
*data_size
)
447 vm_map_copy_t ipc_address
;
449 if (map
== VM_MAP_NULL
)
450 return(KERN_INVALID_ARGUMENT
);
453 error
= vm_map_copyin(map
,
454 (vm_map_address_t
)addr
,
456 FALSE
, /* src_destroy */
459 if (KERN_SUCCESS
== error
) {
460 *data
= (pointer_t
) ipc_address
;
468 * Read/copy a range from one address space and return it to the caller.
469 * Limited addressability (same range limits as for the native kernel map).
471 * It is assumed that the address for the returned memory is selected by
472 * the IPC implementation as part of receiving the reply to this call.
473 * If IPC isn't used, the caller must deal with the vm_map_copy_t object
474 * that gets returned.
482 mach_msg_type_number_t
*data_size
)
485 vm_map_copy_t ipc_address
;
487 if (map
== VM_MAP_NULL
)
488 return(KERN_INVALID_ARGUMENT
);
490 error
= vm_map_copyin(map
,
491 (vm_map_address_t
)addr
,
493 FALSE
, /* src_destroy */
496 if (KERN_SUCCESS
== error
) {
497 *data
= (pointer_t
) ipc_address
;
504 * mach_vm_read_list -
505 * Read/copy a list of address ranges from specified map.
507 * MIG does not know how to deal with a returned array of
508 * vm_map_copy_t structures, so we have to do the copyout
514 mach_vm_read_entry_t data_list
,
517 mach_msg_type_number_t i
;
521 if (map
== VM_MAP_NULL
)
522 return(KERN_INVALID_ARGUMENT
);
524 error
= KERN_SUCCESS
;
525 for(i
=0; i
<count
; i
++) {
526 vm_map_address_t map_addr
;
527 vm_map_size_t map_size
;
529 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
530 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
533 error
= vm_map_copyin(map
,
536 FALSE
, /* src_destroy */
538 if (KERN_SUCCESS
== error
) {
539 error
= vm_map_copyout(
543 if (KERN_SUCCESS
== error
) {
544 data_list
[i
].address
= map_addr
;
547 vm_map_copy_discard(copy
);
550 data_list
[i
].address
= (mach_vm_address_t
)0;
551 data_list
[i
].size
= (mach_vm_size_t
)0;
558 * Read/copy a list of address ranges from specified map.
560 * MIG does not know how to deal with a returned array of
561 * vm_map_copy_t structures, so we have to do the copyout
564 * The source and destination ranges are limited to those
565 * that can be described with a vm_address_t (i.e. same
566 * size map as the kernel).
568 * JMM - If the result of the copyout is an address range
569 * that cannot be described with a vm_address_t (i.e. the
570 * caller had a larger address space but used this call
571 * anyway), it will result in a truncated address being
572 * returned (and a likely confused caller).
578 vm_read_entry_t data_list
,
581 mach_msg_type_number_t i
;
585 if (map
== VM_MAP_NULL
)
586 return(KERN_INVALID_ARGUMENT
);
588 error
= KERN_SUCCESS
;
589 for(i
=0; i
<count
; i
++) {
590 vm_map_address_t map_addr
;
591 vm_map_size_t map_size
;
593 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
594 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
597 error
= vm_map_copyin(map
,
600 FALSE
, /* src_destroy */
602 if (KERN_SUCCESS
== error
) {
603 error
= vm_map_copyout(current_task()->map
,
606 if (KERN_SUCCESS
== error
) {
607 data_list
[i
].address
=
608 CAST_DOWN(vm_offset_t
, map_addr
);
611 vm_map_copy_discard(copy
);
614 data_list
[i
].address
= (mach_vm_address_t
)0;
615 data_list
[i
].size
= (mach_vm_size_t
)0;
621 * mach_vm_read_overwrite -
622 * Overwrite a range of the current map with data from the specified
625 * In making an assumption that the current thread is local, it is
626 * no longer cluster-safe without a fully supportive local proxy
627 * thread/task (but we don't support cluster's anymore so this is moot).
631 mach_vm_read_overwrite(
633 mach_vm_address_t address
,
635 mach_vm_address_t data
,
636 mach_vm_size_t
*data_size
)
641 if (map
== VM_MAP_NULL
)
642 return(KERN_INVALID_ARGUMENT
);
644 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
645 (vm_map_size_t
)size
, FALSE
, ©
);
647 if (KERN_SUCCESS
== error
) {
648 error
= vm_map_copy_overwrite(current_thread()->map
,
649 (vm_map_address_t
)data
,
651 if (KERN_SUCCESS
== error
) {
655 vm_map_copy_discard(copy
);
661 * vm_read_overwrite -
662 * Overwrite a range of the current map with data from the specified
665 * This routine adds the additional limitation that the source and
666 * destination ranges must be describable with vm_address_t values
667 * (i.e. the same size address spaces as the kernel, or at least the
668 * the ranges are in that first portion of the respective address
675 vm_address_t address
,
678 vm_size_t
*data_size
)
683 if (map
== VM_MAP_NULL
)
684 return(KERN_INVALID_ARGUMENT
);
686 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
687 (vm_map_size_t
)size
, FALSE
, ©
);
689 if (KERN_SUCCESS
== error
) {
690 error
= vm_map_copy_overwrite(current_thread()->map
,
691 (vm_map_address_t
)data
,
693 if (KERN_SUCCESS
== error
) {
697 vm_map_copy_discard(copy
);
705 * Overwrite the specified address range with the data provided
706 * (from the current map).
711 mach_vm_address_t address
,
713 __unused mach_msg_type_number_t size
)
715 if (map
== VM_MAP_NULL
)
716 return KERN_INVALID_ARGUMENT
;
718 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
719 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
724 * Overwrite the specified address range with the data provided
725 * (from the current map).
727 * The addressability of the range of addresses to overwrite is
728 * limited bu the use of a vm_address_t (same size as kernel map).
729 * Either the target map is also small, or the range is in the
730 * low addresses within it.
735 vm_address_t address
,
737 __unused mach_msg_type_number_t size
)
739 if (map
== VM_MAP_NULL
)
740 return KERN_INVALID_ARGUMENT
;
742 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
743 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
748 * Overwrite one range of the specified map with the contents of
749 * another range within that same map (i.e. both address ranges
755 mach_vm_address_t source_address
,
757 mach_vm_address_t dest_address
)
762 if (map
== VM_MAP_NULL
)
763 return KERN_INVALID_ARGUMENT
;
765 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
766 (vm_map_size_t
)size
, FALSE
, ©
);
768 if (KERN_SUCCESS
== kr
) {
769 kr
= vm_map_copy_overwrite(map
,
770 (vm_map_address_t
)dest_address
,
771 copy
, FALSE
/* interruptible XXX */);
773 if (KERN_SUCCESS
!= kr
)
774 vm_map_copy_discard(copy
);
782 vm_address_t source_address
,
784 vm_address_t dest_address
)
789 if (map
== VM_MAP_NULL
)
790 return KERN_INVALID_ARGUMENT
;
792 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
793 (vm_map_size_t
)size
, FALSE
, ©
);
795 if (KERN_SUCCESS
== kr
) {
796 kr
= vm_map_copy_overwrite(map
,
797 (vm_map_address_t
)dest_address
,
798 copy
, FALSE
/* interruptible XXX */);
800 if (KERN_SUCCESS
!= kr
)
801 vm_map_copy_discard(copy
);
808 * Map some range of an object into an address space.
810 * The object can be one of several types of objects:
811 * NULL - anonymous memory
812 * a named entry - a range within another address space
813 * or a range within a memory object
814 * a whole memory object
820 mach_vm_offset_t
*address
,
821 mach_vm_size_t initial_size
,
822 mach_vm_offset_t mask
,
825 vm_object_offset_t offset
,
827 vm_prot_t cur_protection
,
828 vm_prot_t max_protection
,
829 vm_inherit_t inheritance
)
831 vm_map_address_t map_addr
;
832 vm_map_size_t map_size
;
834 vm_object_size_t size
;
835 kern_return_t result
;
838 * Check arguments for validity
840 if ((target_map
== VM_MAP_NULL
) ||
841 (cur_protection
& ~VM_PROT_ALL
) ||
842 (max_protection
& ~VM_PROT_ALL
) ||
843 (inheritance
> VM_INHERIT_LAST_VALID
) ||
845 return(KERN_INVALID_ARGUMENT
);
847 map_addr
= vm_map_trunc_page(*address
);
848 map_size
= vm_map_round_page(initial_size
);
849 size
= vm_object_round_page(initial_size
);
852 * Find the vm object (if any) corresponding to this port.
854 if (!IP_VALID(port
)) {
855 object
= VM_OBJECT_NULL
;
858 } else if (ip_kotype(port
) == IKOT_NAMED_ENTRY
) {
859 vm_named_entry_t named_entry
;
861 named_entry
= (vm_named_entry_t
)port
->ip_kobject
;
862 /* a few checks to make sure user is obeying rules */
864 if(offset
>= named_entry
->size
)
865 return(KERN_INVALID_RIGHT
);
866 size
= named_entry
->size
- offset
;
868 if((named_entry
->protection
& max_protection
) != max_protection
)
869 return(KERN_INVALID_RIGHT
);
870 if((named_entry
->protection
& cur_protection
) != cur_protection
)
871 return(KERN_INVALID_RIGHT
);
872 if(named_entry
->size
< (offset
+ size
))
873 return(KERN_INVALID_ARGUMENT
);
875 /* the callers parameter offset is defined to be the */
876 /* offset from beginning of named entry offset in object */
877 offset
= offset
+ named_entry
->offset
;
879 named_entry_lock(named_entry
);
880 if(named_entry
->is_sub_map
) {
881 vm_map_entry_t map_entry
;
883 named_entry_unlock(named_entry
);
884 vm_object_reference(vm_submap_object
);
885 if ((result
= vm_map_enter(target_map
,
887 (vm_map_offset_t
)mask
, flags
,
890 cur_protection
, max_protection
, inheritance
891 )) != KERN_SUCCESS
) {
892 vm_object_deallocate(vm_submap_object
);
896 VM_GET_FLAGS_ALIAS(flags
, alias
);
897 if ((alias
== VM_MEMORY_SHARED_PMAP
) &&
899 vm_map_submap(target_map
, map_addr
,
901 named_entry
->backing
.map
,
902 (vm_map_offset_t
)offset
, TRUE
);
904 vm_map_submap(target_map
, map_addr
,
906 named_entry
->backing
.map
,
907 (vm_map_offset_t
)offset
, FALSE
);
910 if(vm_map_lookup_entry(
911 target_map
, map_addr
, &map_entry
)) {
912 map_entry
->needs_copy
= TRUE
;
919 } else if (named_entry
->is_pager
) {
921 vm_prot_t protections
;
922 unsigned int wimg_mode
;
923 boolean_t cache_attr
;
925 protections
= named_entry
->protection
927 access
= GET_MAP_MEM(named_entry
->protection
);
929 object
= vm_object_enter(
930 named_entry
->backing
.pager
,
932 named_entry
->internal
,
935 if (object
== VM_OBJECT_NULL
) {
936 named_entry_unlock(named_entry
);
937 return(KERN_INVALID_OBJECT
);
940 /* JMM - drop reference on pager here */
942 /* create an extra ref for the named entry */
943 vm_object_lock(object
);
944 vm_object_reference_locked(object
);
945 named_entry
->backing
.object
= object
;
946 named_entry
->is_pager
= FALSE
;
947 named_entry_unlock(named_entry
);
949 wimg_mode
= object
->wimg_bits
;
950 if(access
== MAP_MEM_IO
) {
951 wimg_mode
= VM_WIMG_IO
;
952 } else if (access
== MAP_MEM_COPYBACK
) {
953 wimg_mode
= VM_WIMG_USE_DEFAULT
;
954 } else if (access
== MAP_MEM_WTHRU
) {
955 wimg_mode
= VM_WIMG_WTHRU
;
956 } else if (access
== MAP_MEM_WCOMB
) {
957 wimg_mode
= VM_WIMG_WCOMB
;
959 if ((wimg_mode
== VM_WIMG_IO
)
960 || (wimg_mode
== VM_WIMG_WCOMB
))
965 /* wait for object (if any) to be ready */
966 if (!named_entry
->internal
) {
967 while (!object
->pager_ready
) {
968 vm_object_wait(object
,
969 VM_OBJECT_EVENT_PAGER_READY
,
971 vm_object_lock(object
);
975 if(object
->wimg_bits
!= wimg_mode
) {
978 vm_object_paging_wait(object
, THREAD_UNINT
);
980 object
->wimg_bits
= wimg_mode
;
981 queue_iterate(&object
->memq
, p
, vm_page_t
, listq
) {
982 if (!p
->fictitious
) {
983 pmap_disconnect(p
->phys_page
);
985 pmap_sync_page_attributes_phys(p
->phys_page
);
989 object
->true_share
= TRUE
;
990 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
991 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
992 vm_object_unlock(object
);
994 /* This is the case where we are going to map */
995 /* an already mapped object. If the object is */
996 /* not ready it is internal. An external */
997 /* object cannot be mapped until it is ready */
998 /* we can therefore avoid the ready check */
1000 object
= named_entry
->backing
.object
;
1001 assert(object
!= VM_OBJECT_NULL
);
1002 named_entry_unlock(named_entry
);
1003 vm_object_reference(object
);
1005 } else if (ip_kotype(port
) == IKOT_MEMORY_OBJECT
) {
1007 * JMM - This is temporary until we unify named entries
1008 * and raw memory objects.
1010 * Detected fake ip_kotype for a memory object. In
1011 * this case, the port isn't really a port at all, but
1012 * instead is just a raw memory object.
1015 if ((object
= vm_object_enter((memory_object_t
)port
,
1016 size
, FALSE
, FALSE
, FALSE
))
1018 return(KERN_INVALID_OBJECT
);
1020 /* wait for object (if any) to be ready */
1021 if (object
!= VM_OBJECT_NULL
) {
1022 if(object
== kernel_object
) {
1023 printf("Warning: Attempt to map kernel object"
1024 " by a non-private kernel entity\n");
1025 return(KERN_INVALID_OBJECT
);
1027 vm_object_lock(object
);
1028 while (!object
->pager_ready
) {
1029 vm_object_wait(object
,
1030 VM_OBJECT_EVENT_PAGER_READY
,
1032 vm_object_lock(object
);
1034 vm_object_unlock(object
);
1037 return (KERN_INVALID_OBJECT
);
1041 * Perform the copy if requested
1045 vm_object_t new_object
;
1046 vm_object_offset_t new_offset
;
1048 result
= vm_object_copy_strategically(object
, offset
, size
,
1049 &new_object
, &new_offset
,
1053 if (result
== KERN_MEMORY_RESTART_COPY
) {
1055 boolean_t src_needs_copy
;
1059 * We currently ignore src_needs_copy.
1060 * This really is the issue of how to make
1061 * MEMORY_OBJECT_COPY_SYMMETRIC safe for
1062 * non-kernel users to use. Solution forthcoming.
1063 * In the meantime, since we don't allow non-kernel
1064 * memory managers to specify symmetric copy,
1065 * we won't run into problems here.
1067 new_object
= object
;
1068 new_offset
= offset
;
1069 success
= vm_object_copy_quickly(&new_object
,
1074 result
= KERN_SUCCESS
;
1077 * Throw away the reference to the
1078 * original object, as it won't be mapped.
1081 vm_object_deallocate(object
);
1083 if (result
!= KERN_SUCCESS
)
1086 object
= new_object
;
1087 offset
= new_offset
;
1090 if ((result
= vm_map_enter(target_map
,
1091 &map_addr
, map_size
,
1092 (vm_map_offset_t
)mask
,
1096 cur_protection
, max_protection
, inheritance
1098 vm_object_deallocate(object
);
1099 *address
= map_addr
;
1104 /* legacy interface */
1107 vm_map_t target_map
,
1108 vm_offset_t
*address
,
1113 vm_object_offset_t offset
,
1115 vm_prot_t cur_protection
,
1116 vm_prot_t max_protection
,
1117 vm_inherit_t inheritance
)
1119 mach_vm_address_t map_addr
;
1120 mach_vm_size_t map_size
;
1121 mach_vm_offset_t map_mask
;
1124 map_addr
= (mach_vm_address_t
)*address
;
1125 map_size
= (mach_vm_size_t
)size
;
1126 map_mask
= (mach_vm_offset_t
)mask
;
1128 kr
= mach_vm_map(target_map
, &map_addr
, map_size
, map_mask
, flags
,
1130 cur_protection
, max_protection
, inheritance
);
1131 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1135 /* temporary, until world build */
1138 vm_map_t target_map
,
1139 vm_offset_t
*address
,
1146 vm_prot_t cur_protection
,
1147 vm_prot_t max_protection
,
1148 vm_inherit_t inheritance
)
1150 mach_vm_address_t map_addr
;
1151 mach_vm_size_t map_size
;
1152 mach_vm_offset_t map_mask
;
1153 vm_object_offset_t obj_offset
;
1156 map_addr
= (mach_vm_address_t
)*address
;
1157 map_size
= (mach_vm_size_t
)size
;
1158 map_mask
= (mach_vm_offset_t
)mask
;
1159 obj_offset
= (vm_object_offset_t
)offset
;
1161 kr
= mach_vm_map(target_map
, &map_addr
, map_size
, map_mask
, flags
,
1162 port
, obj_offset
, copy
,
1163 cur_protection
, max_protection
, inheritance
);
1164 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1170 * Remap a range of memory from one task into another,
1171 * to another address range within the same task, or
1172 * over top of itself (with altered permissions and/or
1173 * as an in-place copy of itself).
1178 vm_map_t target_map
,
1179 mach_vm_offset_t
*address
,
1180 mach_vm_size_t size
,
1181 mach_vm_offset_t mask
,
1184 mach_vm_offset_t memory_address
,
1186 vm_prot_t
*cur_protection
,
1187 vm_prot_t
*max_protection
,
1188 vm_inherit_t inheritance
)
1190 vm_map_offset_t map_addr
;
1193 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
)
1194 return KERN_INVALID_ARGUMENT
;
1196 map_addr
= (vm_map_offset_t
)*address
;
1198 kr
= vm_map_remap(target_map
,
1209 *address
= map_addr
;
1215 * Remap a range of memory from one task into another,
1216 * to another address range within the same task, or
1217 * over top of itself (with altered permissions and/or
1218 * as an in-place copy of itself).
1220 * The addressability of the source and target address
1221 * range is limited by the size of vm_address_t (in the
1226 vm_map_t target_map
,
1227 vm_offset_t
*address
,
1232 vm_offset_t memory_address
,
1234 vm_prot_t
*cur_protection
,
1235 vm_prot_t
*max_protection
,
1236 vm_inherit_t inheritance
)
1238 vm_map_offset_t map_addr
;
1241 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
)
1242 return KERN_INVALID_ARGUMENT
;
1244 map_addr
= (vm_map_offset_t
)*address
;
1246 kr
= vm_map_remap(target_map
,
1257 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1262 * NOTE: these routine (and this file) will no longer require mach_host_server.h
1263 * when mach_vm_wire and vm_wire are changed to use ledgers.
1265 #include <mach/mach_host_server.h>
1268 * Specify that the range of the virtual address space
1269 * of the target task must not cause page faults for
1270 * the indicated accesses.
1272 * [ To unwire the pages, specify VM_PROT_NONE. ]
1276 host_priv_t host_priv
,
1278 mach_vm_offset_t start
,
1279 mach_vm_size_t size
,
1284 if (host_priv
== HOST_PRIV_NULL
)
1285 return KERN_INVALID_HOST
;
1287 assert(host_priv
== &realhost
);
1289 if (map
== VM_MAP_NULL
)
1290 return KERN_INVALID_TASK
;
1292 if (access
& ~VM_PROT_ALL
)
1293 return KERN_INVALID_ARGUMENT
;
1295 if (access
!= VM_PROT_NONE
) {
1296 rc
= vm_map_wire(map
, vm_map_trunc_page(start
),
1297 vm_map_round_page(start
+size
), access
, TRUE
);
1299 rc
= vm_map_unwire(map
, vm_map_trunc_page(start
),
1300 vm_map_round_page(start
+size
), TRUE
);
1307 * Specify that the range of the virtual address space
1308 * of the target task must not cause page faults for
1309 * the indicated accesses.
1311 * [ To unwire the pages, specify VM_PROT_NONE. ]
1315 host_priv_t host_priv
,
1316 register vm_map_t map
,
1323 if (host_priv
== HOST_PRIV_NULL
)
1324 return KERN_INVALID_HOST
;
1326 assert(host_priv
== &realhost
);
1328 if (map
== VM_MAP_NULL
)
1329 return KERN_INVALID_TASK
;
1331 if ((access
& ~VM_PROT_ALL
) || (start
+ size
< start
))
1332 return KERN_INVALID_ARGUMENT
;
1336 } else if (access
!= VM_PROT_NONE
) {
1337 rc
= vm_map_wire(map
, vm_map_trunc_page(start
),
1338 vm_map_round_page(start
+size
), access
, TRUE
);
1340 rc
= vm_map_unwire(map
, vm_map_trunc_page(start
),
1341 vm_map_round_page(start
+size
), TRUE
);
1349 * Synchronises the memory range specified with its backing store
1350 * image by either flushing or cleaning the contents to the appropriate
1353 * interpretation of sync_flags
1354 * VM_SYNC_INVALIDATE - discard pages, only return precious
1357 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1358 * - discard pages, write dirty or precious
1359 * pages back to memory manager.
1361 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1362 * - write dirty or precious pages back to
1363 * the memory manager.
1365 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1366 * is a hole in the region, and we would
1367 * have returned KERN_SUCCESS, return
1368 * KERN_INVALID_ADDRESS instead.
1371 * KERN_INVALID_TASK Bad task parameter
1372 * KERN_INVALID_ARGUMENT both sync and async were specified.
1373 * KERN_SUCCESS The usual.
1374 * KERN_INVALID_ADDRESS There was a hole in the region.
1380 mach_vm_address_t address
,
1381 mach_vm_size_t size
,
1382 vm_sync_t sync_flags
)
1385 if (map
== VM_MAP_NULL
)
1386 return(KERN_INVALID_TASK
);
1388 return vm_map_msync(map
, (vm_map_address_t
)address
,
1389 (vm_map_size_t
)size
, sync_flags
);
1395 * Synchronises the memory range specified with its backing store
1396 * image by either flushing or cleaning the contents to the appropriate
1399 * interpretation of sync_flags
1400 * VM_SYNC_INVALIDATE - discard pages, only return precious
1403 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1404 * - discard pages, write dirty or precious
1405 * pages back to memory manager.
1407 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1408 * - write dirty or precious pages back to
1409 * the memory manager.
1411 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1412 * is a hole in the region, and we would
1413 * have returned KERN_SUCCESS, return
1414 * KERN_INVALID_ADDRESS instead.
1416 * The addressability of the range is limited to that which can
1417 * be described by a vm_address_t.
1420 * KERN_INVALID_TASK Bad task parameter
1421 * KERN_INVALID_ARGUMENT both sync and async were specified.
1422 * KERN_SUCCESS The usual.
1423 * KERN_INVALID_ADDRESS There was a hole in the region.
1429 vm_address_t address
,
1431 vm_sync_t sync_flags
)
1434 if (map
== VM_MAP_NULL
)
1435 return(KERN_INVALID_TASK
);
1437 return vm_map_msync(map
, (vm_map_address_t
)address
,
1438 (vm_map_size_t
)size
, sync_flags
);
1443 * mach_vm_behavior_set
1445 * Sets the paging behavior attribute for the specified range
1446 * in the specified map.
1448 * This routine will fail with KERN_INVALID_ADDRESS if any address
1449 * in [start,start+size) is not a valid allocated memory region.
1452 mach_vm_behavior_set(
1454 mach_vm_offset_t start
,
1455 mach_vm_size_t size
,
1456 vm_behavior_t new_behavior
)
1458 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
1459 return(KERN_INVALID_ARGUMENT
);
1462 return KERN_SUCCESS
;
1464 return(vm_map_behavior_set(map
, vm_map_trunc_page(start
),
1465 vm_map_round_page(start
+size
), new_behavior
));
1471 * Sets the paging behavior attribute for the specified range
1472 * in the specified map.
1474 * This routine will fail with KERN_INVALID_ADDRESS if any address
1475 * in [start,start+size) is not a valid allocated memory region.
1477 * This routine is potentially limited in addressibility by the
1478 * use of vm_offset_t (if the map provided is larger than the
1486 vm_behavior_t new_behavior
)
1488 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
1489 return(KERN_INVALID_ARGUMENT
);
1492 return KERN_SUCCESS
;
1494 return(vm_map_behavior_set(map
, vm_map_trunc_page(start
),
1495 vm_map_round_page(start
+size
), new_behavior
));
1501 * User call to obtain information about a region in
1502 * a task's address map. Currently, only one flavor is
1505 * XXX The reserved and behavior fields cannot be filled
1506 * in until the vm merge from the IK is completed, and
1507 * vm_reserve is implemented.
1509 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1515 mach_vm_offset_t
*address
, /* IN/OUT */
1516 mach_vm_size_t
*size
, /* OUT */
1517 vm_region_flavor_t flavor
, /* IN */
1518 vm_region_info_t info
, /* OUT */
1519 mach_msg_type_number_t
*count
, /* IN/OUT */
1520 mach_port_t
*object_name
) /* OUT */
1522 vm_map_offset_t map_addr
;
1523 vm_map_size_t map_size
;
1526 if (VM_MAP_NULL
== map
)
1527 return KERN_INVALID_ARGUMENT
;
1529 map_addr
= (vm_map_offset_t
)*address
;
1530 map_size
= (vm_map_size_t
)*size
;
1532 /* legacy conversion */
1533 if (VM_REGION_BASIC_INFO
== flavor
)
1534 flavor
= VM_REGION_BASIC_INFO_64
;
1536 kr
= vm_map_region(map
,
1537 &map_addr
, &map_size
,
1538 flavor
, info
, count
,
1541 *address
= map_addr
;
1547 * vm_region_64 and vm_region:
1549 * User call to obtain information about a region in
1550 * a task's address map. Currently, only one flavor is
1553 * XXX The reserved and behavior fields cannot be filled
1554 * in until the vm merge from the IK is completed, and
1555 * vm_reserve is implemented.
1557 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1563 vm_offset_t
*address
, /* IN/OUT */
1564 vm_size_t
*size
, /* OUT */
1565 vm_region_flavor_t flavor
, /* IN */
1566 vm_region_info_t info
, /* OUT */
1567 mach_msg_type_number_t
*count
, /* IN/OUT */
1568 mach_port_t
*object_name
) /* OUT */
1570 vm_map_offset_t map_addr
;
1571 vm_map_size_t map_size
;
1574 if (VM_MAP_NULL
== map
)
1575 return KERN_INVALID_ARGUMENT
;
1577 map_addr
= (vm_map_offset_t
)*address
;
1578 map_size
= (vm_map_size_t
)*size
;
1580 /* legacy conversion */
1581 if (VM_REGION_BASIC_INFO
== flavor
)
1582 flavor
= VM_REGION_BASIC_INFO_64
;
1584 kr
= vm_map_region(map
,
1585 &map_addr
, &map_size
,
1586 flavor
, info
, count
,
1589 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1590 *size
= CAST_DOWN(vm_size_t
, map_size
);
1592 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1593 return KERN_INVALID_ADDRESS
;
1600 vm_address_t
*address
, /* IN/OUT */
1601 vm_size_t
*size
, /* OUT */
1602 vm_region_flavor_t flavor
, /* IN */
1603 vm_region_info_t info
, /* OUT */
1604 mach_msg_type_number_t
*count
, /* IN/OUT */
1605 mach_port_t
*object_name
) /* OUT */
1607 vm_map_address_t map_addr
;
1608 vm_map_size_t map_size
;
1611 if (VM_MAP_NULL
== map
)
1612 return KERN_INVALID_ARGUMENT
;
1614 map_addr
= (vm_map_address_t
)*address
;
1615 map_size
= (vm_map_size_t
)*size
;
1617 kr
= vm_map_region(map
,
1618 &map_addr
, &map_size
,
1619 flavor
, info
, count
,
1622 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1623 *size
= CAST_DOWN(vm_size_t
, map_size
);
1625 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1626 return KERN_INVALID_ADDRESS
;
1631 * vm_region_recurse: A form of vm_region which follows the
1632 * submaps in a target map
1636 mach_vm_region_recurse(
1638 mach_vm_address_t
*address
,
1639 mach_vm_size_t
*size
,
1641 vm_region_recurse_info_t info
,
1642 mach_msg_type_number_t
*infoCnt
)
1644 vm_map_address_t map_addr
;
1645 vm_map_size_t map_size
;
1648 if (VM_MAP_NULL
== map
)
1649 return KERN_INVALID_ARGUMENT
;
1651 map_addr
= (vm_map_address_t
)*address
;
1652 map_size
= (vm_map_size_t
)*size
;
1654 kr
= vm_map_region_recurse_64(
1659 (vm_region_submap_info_64_t
)info
,
1662 *address
= map_addr
;
1668 * vm_region_recurse: A form of vm_region which follows the
1669 * submaps in a target map
1673 vm_region_recurse_64(
1675 vm_address_t
*address
,
1678 vm_region_recurse_info_64_t info
,
1679 mach_msg_type_number_t
*infoCnt
)
1681 vm_map_address_t map_addr
;
1682 vm_map_size_t map_size
;
1685 if (VM_MAP_NULL
== map
)
1686 return KERN_INVALID_ARGUMENT
;
1688 map_addr
= (vm_map_address_t
)*address
;
1689 map_size
= (vm_map_size_t
)*size
;
1691 kr
= vm_map_region_recurse_64(
1696 (vm_region_submap_info_64_t
)info
,
1699 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1700 *size
= CAST_DOWN(vm_size_t
, map_size
);
1702 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1703 return KERN_INVALID_ADDRESS
;
1710 vm_offset_t
*address
, /* IN/OUT */
1711 vm_size_t
*size
, /* OUT */
1712 natural_t
*depth
, /* IN/OUT */
1713 vm_region_recurse_info_t info32
, /* IN/OUT */
1714 mach_msg_type_number_t
*infoCnt
) /* IN/OUT */
1716 vm_region_submap_info_data_64_t info64
;
1717 vm_region_submap_info_t info
;
1718 vm_map_address_t map_addr
;
1719 vm_map_size_t map_size
;
1722 if (VM_MAP_NULL
== map
|| *infoCnt
< VM_REGION_SUBMAP_INFO_COUNT
)
1723 return KERN_INVALID_ARGUMENT
;
1726 map_addr
= (vm_map_address_t
)*address
;
1727 map_size
= (vm_map_size_t
)*size
;
1728 info
= (vm_region_submap_info_t
)info32
;
1729 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT_64
;
1731 kr
= vm_map_region_recurse_64(map
, &map_addr
,&map_size
,
1732 depth
, &info64
, infoCnt
);
1734 info
->protection
= info64
.protection
;
1735 info
->max_protection
= info64
.max_protection
;
1736 info
->inheritance
= info64
.inheritance
;
1737 info
->offset
= (uint32_t)info64
.offset
; /* trouble-maker */
1738 info
->user_tag
= info64
.user_tag
;
1739 info
->pages_resident
= info64
.pages_resident
;
1740 info
->pages_shared_now_private
= info64
.pages_shared_now_private
;
1741 info
->pages_swapped_out
= info64
.pages_swapped_out
;
1742 info
->pages_dirtied
= info64
.pages_dirtied
;
1743 info
->ref_count
= info64
.ref_count
;
1744 info
->shadow_depth
= info64
.shadow_depth
;
1745 info
->external_pager
= info64
.external_pager
;
1746 info
->share_mode
= info64
.share_mode
;
1747 info
->is_submap
= info64
.is_submap
;
1748 info
->behavior
= info64
.behavior
;
1749 info
->object_id
= info64
.object_id
;
1750 info
->user_wired_count
= info64
.user_wired_count
;
1752 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1753 *size
= CAST_DOWN(vm_size_t
, map_size
);
1754 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT
;
1756 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1757 return KERN_INVALID_ADDRESS
;
1762 vm_purgable_control(
1764 vm_offset_t address
,
1765 vm_purgable_t control
,
1768 if (VM_MAP_NULL
== map
)
1769 return KERN_INVALID_ARGUMENT
;
1771 return vm_map_purgable_control(map
,
1772 vm_map_trunc_page(address
),
1779 * Ordinarily, the right to allocate CPM is restricted
1780 * to privileged applications (those that can gain access
1781 * to the host priv port). Set this variable to zero if
1782 * you want to let any application allocate CPM.
1784 unsigned int vm_allocate_cpm_privileged
= 0;
1787 * Allocate memory in the specified map, with the caveat that
1788 * the memory is physically contiguous. This call may fail
1789 * if the system can't find sufficient contiguous memory.
1790 * This call may cause or lead to heart-stopping amounts of
1793 * Memory obtained from this call should be freed in the
1794 * normal way, viz., via vm_deallocate.
1798 host_priv_t host_priv
,
1804 vm_map_address_t map_addr
;
1805 vm_map_size_t map_size
;
1808 if (vm_allocate_cpm_privileged
&& HOST_PRIV_NULL
== host_priv
)
1809 return KERN_INVALID_HOST
;
1811 if (VM_MAP_NULL
== map
)
1812 return KERN_INVALID_ARGUMENT
;
1814 map_addr
= (vm_map_address_t
)*addr
;
1815 map_size
= (vm_map_size_t
)size
;
1817 kr
= vm_map_enter_cpm(map
,
1822 *addr
= CAST_DOWN(vm_address_t
, map_addr
);
1830 mach_vm_offset_t offset
,
1834 if (VM_MAP_NULL
== map
)
1835 return KERN_INVALID_ARGUMENT
;
1837 return vm_map_page_info(map
,
1838 vm_map_trunc_page(offset
),
1839 disposition
, ref_count
);
1849 if (VM_MAP_NULL
== map
)
1850 return KERN_INVALID_ARGUMENT
;
1852 return vm_map_page_info(map
,
1853 vm_map_trunc_page(offset
),
1854 disposition
, ref_count
);
1857 /* map a (whole) upl into an address space */
1862 vm_offset_t
*dst_addr
)
1864 vm_map_offset_t map_addr
;
1867 if (VM_MAP_NULL
== map
)
1868 return KERN_INVALID_ARGUMENT
;
1870 kr
= vm_map_enter_upl(map
, upl
, &map_addr
);
1871 *dst_addr
= CAST_DOWN(vm_offset_t
, map_addr
);
1880 if (VM_MAP_NULL
== map
)
1881 return KERN_INVALID_ARGUMENT
;
1883 return (vm_map_remove_upl(map
, upl
));
1886 /* Retrieve a upl for an object underlying an address range in a map */
1891 vm_map_offset_t map_offset
,
1892 upl_size_t
*upl_size
,
1894 upl_page_info_array_t page_list
,
1895 unsigned int *count
,
1897 int force_data_sync
)
1902 if (VM_MAP_NULL
== map
)
1903 return KERN_INVALID_ARGUMENT
;
1905 map_flags
= *flags
& ~UPL_NOZEROFILL
;
1906 if (force_data_sync
)
1907 map_flags
|= UPL_FORCE_DATA_SYNC
;
1909 kr
= vm_map_create_upl(map
,
1917 *flags
= (map_flags
& ~UPL_FORCE_DATA_SYNC
);
1922 __private_extern__ kern_return_t
1923 mach_memory_entry_allocate(
1924 vm_named_entry_t
*user_entry_p
,
1925 ipc_port_t
*user_handle_p
); /* forward */
1928 * mach_make_memory_entry_64
1930 * Think of it as a two-stage vm_remap() operation. First
1931 * you get a handle. Second, you get map that handle in
1932 * somewhere else. Rather than doing it all at once (and
1933 * without needing access to the other whole map).
1937 mach_make_memory_entry_64(
1938 vm_map_t target_map
,
1939 memory_object_size_t
*size
,
1940 memory_object_offset_t offset
,
1941 vm_prot_t permission
,
1942 ipc_port_t
*object_handle
,
1943 ipc_port_t parent_handle
)
1945 vm_map_version_t version
;
1946 vm_named_entry_t parent_entry
;
1947 vm_named_entry_t user_entry
;
1948 ipc_port_t user_handle
;
1952 /* needed for call to vm_map_lookup_locked */
1954 vm_object_offset_t obj_off
;
1956 vm_map_offset_t lo_offset
, hi_offset
;
1957 vm_behavior_t behavior
;
1959 vm_object_t shadow_object
;
1961 /* needed for direct map entry manipulation */
1962 vm_map_entry_t map_entry
;
1963 vm_map_entry_t next_entry
;
1965 vm_map_t original_map
= target_map
;
1966 vm_map_size_t total_size
;
1967 vm_map_size_t map_size
;
1968 vm_map_offset_t map_offset
;
1969 vm_map_offset_t local_offset
;
1970 vm_object_size_t mappable_size
;
1972 unsigned int access
;
1973 vm_prot_t protections
;
1974 unsigned int wimg_mode
;
1975 boolean_t cache_attr
= FALSE
;
1977 if (((permission
& 0x00FF0000) &
1979 MAP_MEM_NAMED_CREATE
|
1981 MAP_MEM_NAMED_REUSE
))) {
1983 * Unknown flag: reject for forward compatibility.
1985 return KERN_INVALID_VALUE
;
1988 if (parent_handle
!= IP_NULL
&&
1989 ip_kotype(parent_handle
) == IKOT_NAMED_ENTRY
) {
1990 parent_entry
= (vm_named_entry_t
) parent_handle
->ip_kobject
;
1992 parent_entry
= NULL
;
1995 protections
= permission
& VM_PROT_ALL
;
1996 access
= GET_MAP_MEM(permission
);
1998 user_handle
= IP_NULL
;
2001 map_offset
= vm_map_trunc_page(offset
);
2002 map_size
= vm_map_round_page(*size
);
2004 if (permission
& MAP_MEM_ONLY
) {
2005 boolean_t parent_is_object
;
2007 if (parent_entry
== NULL
) {
2008 return KERN_INVALID_ARGUMENT
;
2011 parent_is_object
= !(parent_entry
->is_sub_map
|| parent_entry
->is_pager
);
2012 object
= parent_entry
->backing
.object
;
2013 if(parent_is_object
&& object
!= VM_OBJECT_NULL
)
2014 wimg_mode
= object
->wimg_bits
;
2016 wimg_mode
= VM_WIMG_DEFAULT
;
2017 if((access
!= GET_MAP_MEM(parent_entry
->protection
)) &&
2018 !(parent_entry
->protection
& VM_PROT_WRITE
)) {
2019 return KERN_INVALID_RIGHT
;
2021 if(access
== MAP_MEM_IO
) {
2022 SET_MAP_MEM(access
, parent_entry
->protection
);
2023 wimg_mode
= VM_WIMG_IO
;
2024 } else if (access
== MAP_MEM_COPYBACK
) {
2025 SET_MAP_MEM(access
, parent_entry
->protection
);
2026 wimg_mode
= VM_WIMG_DEFAULT
;
2027 } else if (access
== MAP_MEM_WTHRU
) {
2028 SET_MAP_MEM(access
, parent_entry
->protection
);
2029 wimg_mode
= VM_WIMG_WTHRU
;
2030 } else if (access
== MAP_MEM_WCOMB
) {
2031 SET_MAP_MEM(access
, parent_entry
->protection
);
2032 wimg_mode
= VM_WIMG_WCOMB
;
2034 if(parent_is_object
&& object
&&
2035 (access
!= MAP_MEM_NOOP
) &&
2036 (!(object
->nophyscache
))) {
2037 if(object
->wimg_bits
!= wimg_mode
) {
2039 if ((wimg_mode
== VM_WIMG_IO
)
2040 || (wimg_mode
== VM_WIMG_WCOMB
))
2044 vm_object_lock(object
);
2045 vm_object_paging_wait(object
, THREAD_UNINT
);
2046 object
->wimg_bits
= wimg_mode
;
2047 queue_iterate(&object
->memq
,
2048 p
, vm_page_t
, listq
) {
2049 if (!p
->fictitious
) {
2050 pmap_disconnect(p
->phys_page
);
2052 pmap_sync_page_attributes_phys(p
->phys_page
);
2055 vm_object_unlock(object
);
2059 *object_handle
= IP_NULL
;
2060 return KERN_SUCCESS
;
2063 if(permission
& MAP_MEM_NAMED_CREATE
) {
2064 kr
= mach_memory_entry_allocate(&user_entry
, &user_handle
);
2065 if (kr
!= KERN_SUCCESS
) {
2066 return KERN_FAILURE
;
2070 * Force the creation of the VM object now.
2072 if (map_size
> (vm_map_size_t
) VM_MAX_ADDRESS
) {
2074 * LP64todo - for now, we can only allocate 4GB
2075 * internal objects because the default pager can't
2076 * page bigger ones. Remove this when it can.
2082 object
= vm_object_allocate(map_size
);
2083 assert(object
!= VM_OBJECT_NULL
);
2085 if (permission
& MAP_MEM_PURGABLE
) {
2086 if (! (permission
& VM_PROT_WRITE
)) {
2087 /* if we can't write, we can't purge */
2088 vm_object_deallocate(object
);
2089 kr
= KERN_INVALID_ARGUMENT
;
2092 object
->purgable
= VM_OBJECT_PURGABLE_NONVOLATILE
;
2096 * The VM object is brand new and nobody else knows about it,
2097 * so we don't need to lock it.
2100 wimg_mode
= object
->wimg_bits
;
2101 if (access
== MAP_MEM_IO
) {
2102 wimg_mode
= VM_WIMG_IO
;
2103 } else if (access
== MAP_MEM_COPYBACK
) {
2104 wimg_mode
= VM_WIMG_DEFAULT
;
2105 } else if (access
== MAP_MEM_WTHRU
) {
2106 wimg_mode
= VM_WIMG_WTHRU
;
2107 } else if (access
== MAP_MEM_WCOMB
) {
2108 wimg_mode
= VM_WIMG_WCOMB
;
2110 if (access
!= MAP_MEM_NOOP
) {
2111 object
->wimg_bits
= wimg_mode
;
2113 /* the object has no pages, so no WIMG bits to update here */
2117 * We use this path when we want to make sure that
2118 * nobody messes with the object (coalesce, for
2119 * example) before we map it.
2120 * We might want to use these objects for transposition via
2121 * vm_object_transpose() too, so we don't want any copy or
2122 * shadow objects either...
2124 object
->copy_strategy
= MEMORY_OBJECT_COPY_NONE
;
2126 user_entry
->backing
.object
= object
;
2127 user_entry
->internal
= TRUE
;
2128 user_entry
->is_sub_map
= FALSE
;
2129 user_entry
->is_pager
= FALSE
;
2130 user_entry
->offset
= 0;
2131 user_entry
->protection
= protections
;
2132 SET_MAP_MEM(access
, user_entry
->protection
);
2133 user_entry
->size
= map_size
;
2135 /* user_object pager and internal fields are not used */
2136 /* when the object field is filled in. */
2138 *size
= CAST_DOWN(vm_size_t
, map_size
);
2139 *object_handle
= user_handle
;
2140 return KERN_SUCCESS
;
2143 if (parent_entry
== NULL
||
2144 (permission
& MAP_MEM_NAMED_REUSE
)) {
2146 /* Create a named object based on address range within the task map */
2147 /* Go find the object at given address */
2150 vm_map_lock_read(target_map
);
2152 /* get the object associated with the target address */
2153 /* note we check the permission of the range against */
2154 /* that requested by the caller */
2156 kr
= vm_map_lookup_locked(&target_map
, map_offset
,
2157 protections
, &version
,
2158 &object
, &obj_off
, &prot
, &wired
, &behavior
,
2159 &lo_offset
, &hi_offset
, &real_map
);
2160 if (kr
!= KERN_SUCCESS
) {
2161 vm_map_unlock_read(target_map
);
2164 if (((prot
& protections
) != protections
)
2165 || (object
== kernel_object
)) {
2166 kr
= KERN_INVALID_RIGHT
;
2167 vm_object_unlock(object
);
2168 vm_map_unlock_read(target_map
);
2169 if(real_map
!= target_map
)
2170 vm_map_unlock_read(real_map
);
2171 if(object
== kernel_object
) {
2172 printf("Warning: Attempt to create a named"
2173 " entry from the kernel_object\n");
2178 /* We have an object, now check to see if this object */
2179 /* is suitable. If not, create a shadow and share that */
2182 * We have to unlock the VM object to avoid deadlocking with
2183 * a VM map lock (the lock ordering is map, the object), if we
2184 * need to modify the VM map to create a shadow object. Since
2185 * we might release the VM map lock below anyway, we have
2186 * to release the VM map lock now.
2187 * XXX FBDP There must be a way to avoid this double lookup...
2189 * Take an extra reference on the VM object to make sure it's
2190 * not going to disappear.
2192 vm_object_reference_locked(object
); /* extra ref to hold obj */
2193 vm_object_unlock(object
);
2195 local_map
= original_map
;
2196 local_offset
= map_offset
;
2197 if(target_map
!= local_map
) {
2198 vm_map_unlock_read(target_map
);
2199 if(real_map
!= target_map
)
2200 vm_map_unlock_read(real_map
);
2201 vm_map_lock_read(local_map
);
2202 target_map
= local_map
;
2203 real_map
= local_map
;
2206 if(!vm_map_lookup_entry(local_map
,
2207 local_offset
, &map_entry
)) {
2208 kr
= KERN_INVALID_ARGUMENT
;
2209 vm_map_unlock_read(target_map
);
2210 if(real_map
!= target_map
)
2211 vm_map_unlock_read(real_map
);
2212 vm_object_deallocate(object
); /* release extra ref */
2213 object
= VM_OBJECT_NULL
;
2216 if(!(map_entry
->is_sub_map
)) {
2217 if(map_entry
->object
.vm_object
!= object
) {
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
;
2230 local_map
= map_entry
->object
.sub_map
;
2232 vm_map_lock_read(local_map
);
2233 vm_map_unlock_read(tmap
);
2234 target_map
= local_map
;
2235 real_map
= local_map
;
2236 local_offset
= local_offset
- map_entry
->vme_start
;
2237 local_offset
+= map_entry
->offset
;
2242 * We found the VM map entry, lock the VM object again.
2244 vm_object_lock(object
);
2245 if(map_entry
->wired_count
) {
2246 /* JMM - The check below should be reworked instead. */
2247 object
->true_share
= TRUE
;
2249 if(((map_entry
->max_protection
) & protections
) != protections
) {
2250 kr
= KERN_INVALID_RIGHT
;
2251 vm_object_unlock(object
);
2252 vm_map_unlock_read(target_map
);
2253 if(real_map
!= target_map
)
2254 vm_map_unlock_read(real_map
);
2255 vm_object_deallocate(object
);
2256 object
= VM_OBJECT_NULL
;
2260 mappable_size
= hi_offset
- obj_off
;
2261 total_size
= map_entry
->vme_end
- map_entry
->vme_start
;
2262 if(map_size
> mappable_size
) {
2263 /* try to extend mappable size if the entries */
2264 /* following are from the same object and are */
2266 next_entry
= map_entry
->vme_next
;
2267 /* lets see if the next map entry is still */
2268 /* pointing at this object and is contiguous */
2269 while(map_size
> mappable_size
) {
2270 if((next_entry
->object
.vm_object
== object
) &&
2271 (next_entry
->vme_start
==
2272 next_entry
->vme_prev
->vme_end
) &&
2273 (next_entry
->offset
==
2274 next_entry
->vme_prev
->offset
+
2275 (next_entry
->vme_prev
->vme_end
-
2276 next_entry
->vme_prev
->vme_start
))) {
2277 if(((next_entry
->max_protection
)
2278 & protections
) != protections
) {
2281 if (next_entry
->needs_copy
!=
2282 map_entry
->needs_copy
)
2284 mappable_size
+= next_entry
->vme_end
2285 - next_entry
->vme_start
;
2286 total_size
+= next_entry
->vme_end
2287 - next_entry
->vme_start
;
2288 next_entry
= next_entry
->vme_next
;
2296 if(object
->internal
) {
2297 /* vm_map_lookup_locked will create a shadow if */
2298 /* needs_copy is set but does not check for the */
2299 /* other two conditions shown. It is important to */
2300 /* set up an object which will not be pulled from */
2303 if ((map_entry
->needs_copy
|| object
->shadowed
||
2304 (object
->size
> total_size
))
2305 && !object
->true_share
) {
2307 * We have to unlock the VM object before
2308 * trying to upgrade the VM map lock, to
2309 * honor lock ordering (map then object).
2310 * Otherwise, we would deadlock if another
2311 * thread holds a read lock on the VM map and
2312 * is trying to acquire the VM object's lock.
2313 * We still hold an extra reference on the
2314 * VM object, guaranteeing that it won't
2317 vm_object_unlock(object
);
2319 if (vm_map_lock_read_to_write(target_map
)) {
2321 * We couldn't upgrade our VM map lock
2322 * from "read" to "write" and we lost
2324 * Start all over again...
2326 vm_object_deallocate(object
); /* extra ref */
2327 target_map
= original_map
;
2330 vm_object_lock(object
);
2333 * JMM - We need to avoid coming here when the object
2334 * is wired by anybody, not just the current map. Why
2335 * couldn't we use the standard vm_object_copy_quickly()
2339 /* create a shadow object */
2340 vm_object_shadow(&map_entry
->object
.vm_object
,
2341 &map_entry
->offset
, total_size
);
2342 shadow_object
= map_entry
->object
.vm_object
;
2343 vm_object_unlock(object
);
2345 vm_object_pmap_protect(
2346 object
, map_entry
->offset
,
2348 ((map_entry
->is_shared
2349 || target_map
->mapped
)
2352 map_entry
->vme_start
,
2353 map_entry
->protection
& ~VM_PROT_WRITE
);
2354 total_size
-= (map_entry
->vme_end
2355 - map_entry
->vme_start
);
2356 next_entry
= map_entry
->vme_next
;
2357 map_entry
->needs_copy
= FALSE
;
2358 while (total_size
) {
2359 if(next_entry
->object
.vm_object
== object
) {
2360 shadow_object
->ref_count
++;
2361 vm_object_res_reference(shadow_object
);
2362 next_entry
->object
.vm_object
2364 vm_object_deallocate(object
);
2366 = next_entry
->vme_prev
->offset
+
2367 (next_entry
->vme_prev
->vme_end
2368 - next_entry
->vme_prev
->vme_start
);
2369 next_entry
->needs_copy
= FALSE
;
2371 panic("mach_make_memory_entry_64:"
2372 " map entries out of sync\n");
2376 - next_entry
->vme_start
;
2377 next_entry
= next_entry
->vme_next
;
2381 * Transfer our extra reference to the
2384 vm_object_reference_locked(shadow_object
);
2385 vm_object_deallocate(object
); /* extra ref */
2386 object
= shadow_object
;
2388 obj_off
= (local_offset
- map_entry
->vme_start
)
2389 + map_entry
->offset
;
2391 vm_map_lock_write_to_read(target_map
);
2392 vm_object_lock(object
);
2397 /* note: in the future we can (if necessary) allow for */
2398 /* memory object lists, this will better support */
2399 /* fragmentation, but is it necessary? The user should */
2400 /* be encouraged to create address space oriented */
2401 /* shared objects from CLEAN memory regions which have */
2402 /* a known and defined history. i.e. no inheritence */
2403 /* share, make this call before making the region the */
2404 /* target of ipc's, etc. The code above, protecting */
2405 /* against delayed copy, etc. is mostly defensive. */
2407 wimg_mode
= object
->wimg_bits
;
2408 if(!(object
->nophyscache
)) {
2409 if(access
== MAP_MEM_IO
) {
2410 wimg_mode
= VM_WIMG_IO
;
2411 } else if (access
== MAP_MEM_COPYBACK
) {
2412 wimg_mode
= VM_WIMG_USE_DEFAULT
;
2413 } else if (access
== MAP_MEM_WTHRU
) {
2414 wimg_mode
= VM_WIMG_WTHRU
;
2415 } else if (access
== MAP_MEM_WCOMB
) {
2416 wimg_mode
= VM_WIMG_WCOMB
;
2420 object
->true_share
= TRUE
;
2421 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
2422 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
2425 * The memory entry now points to this VM object and we
2426 * need to hold a reference on the VM object. Use the extra
2427 * reference we took earlier to keep the object alive when we
2431 vm_map_unlock_read(target_map
);
2432 if(real_map
!= target_map
)
2433 vm_map_unlock_read(real_map
);
2435 if(object
->wimg_bits
!= wimg_mode
) {
2438 vm_object_paging_wait(object
, THREAD_UNINT
);
2440 if ((wimg_mode
== VM_WIMG_IO
)
2441 || (wimg_mode
== VM_WIMG_WCOMB
))
2446 queue_iterate(&object
->memq
,
2447 p
, vm_page_t
, listq
) {
2448 if (!p
->fictitious
) {
2449 pmap_disconnect(p
->phys_page
);
2451 pmap_sync_page_attributes_phys(p
->phys_page
);
2454 object
->wimg_bits
= wimg_mode
;
2457 /* the size of mapped entry that overlaps with our region */
2458 /* which is targeted for share. */
2459 /* (entry_end - entry_start) - */
2460 /* offset of our beg addr within entry */
2461 /* it corresponds to this: */
2463 if(map_size
> mappable_size
)
2464 map_size
= mappable_size
;
2466 if (permission
& MAP_MEM_NAMED_REUSE
) {
2468 * Compare what we got with the "parent_entry".
2469 * If they match, re-use the "parent_entry" instead
2470 * of creating a new one.
2472 if (parent_entry
!= NULL
&&
2473 parent_entry
->backing
.object
== object
&&
2474 parent_entry
->internal
== object
->internal
&&
2475 parent_entry
->is_sub_map
== FALSE
&&
2476 parent_entry
->is_pager
== FALSE
&&
2477 parent_entry
->offset
== obj_off
&&
2478 parent_entry
->protection
== protections
&&
2479 parent_entry
->size
== map_size
) {
2481 * We have a match: re-use "parent_entry".
2483 /* release our extra reference on object */
2484 vm_object_unlock(object
);
2485 vm_object_deallocate(object
);
2486 /* parent_entry->ref_count++; XXX ? */
2487 /* Get an extra send-right on handle */
2488 ipc_port_copy_send(parent_handle
);
2489 *object_handle
= parent_handle
;
2490 return KERN_SUCCESS
;
2493 * No match: we need to create a new entry.
2499 vm_object_unlock(object
);
2500 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2502 /* release our unused reference on the object */
2503 vm_object_deallocate(object
);
2504 return KERN_FAILURE
;
2507 user_entry
->backing
.object
= object
;
2508 user_entry
->internal
= object
->internal
;
2509 user_entry
->is_sub_map
= FALSE
;
2510 user_entry
->is_pager
= FALSE
;
2511 user_entry
->offset
= obj_off
;
2512 user_entry
->protection
= permission
;
2513 user_entry
->size
= map_size
;
2515 /* user_object pager and internal fields are not used */
2516 /* when the object field is filled in. */
2518 *size
= CAST_DOWN(vm_size_t
, map_size
);
2519 *object_handle
= user_handle
;
2520 return KERN_SUCCESS
;
2523 /* The new object will be base on an existing named object */
2525 if (parent_entry
== NULL
) {
2526 kr
= KERN_INVALID_ARGUMENT
;
2529 if((offset
+ map_size
) > parent_entry
->size
) {
2530 kr
= KERN_INVALID_ARGUMENT
;
2534 if((protections
& parent_entry
->protection
) != protections
) {
2535 kr
= KERN_PROTECTION_FAILURE
;
2539 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2545 user_entry
->size
= map_size
;
2546 user_entry
->offset
= parent_entry
->offset
+ map_offset
;
2547 user_entry
->is_sub_map
= parent_entry
->is_sub_map
;
2548 user_entry
->is_pager
= parent_entry
->is_pager
;
2549 user_entry
->internal
= parent_entry
->internal
;
2550 user_entry
->protection
= protections
;
2552 if(access
!= MAP_MEM_NOOP
) {
2553 SET_MAP_MEM(access
, user_entry
->protection
);
2556 if(parent_entry
->is_sub_map
) {
2557 user_entry
->backing
.map
= parent_entry
->backing
.map
;
2558 vm_map_lock(user_entry
->backing
.map
);
2559 user_entry
->backing
.map
->ref_count
++;
2560 vm_map_unlock(user_entry
->backing
.map
);
2562 else if (parent_entry
->is_pager
) {
2563 user_entry
->backing
.pager
= parent_entry
->backing
.pager
;
2564 /* JMM - don't we need a reference here? */
2566 object
= parent_entry
->backing
.object
;
2567 assert(object
!= VM_OBJECT_NULL
);
2568 user_entry
->backing
.object
= object
;
2569 /* we now point to this object, hold on */
2570 vm_object_reference(object
);
2571 vm_object_lock(object
);
2572 object
->true_share
= TRUE
;
2573 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
2574 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
2575 vm_object_unlock(object
);
2577 *size
= CAST_DOWN(vm_size_t
, map_size
);
2578 *object_handle
= user_handle
;
2579 return KERN_SUCCESS
;
2583 if (user_handle
!= IP_NULL
) {
2584 ipc_port_dealloc_kernel(user_handle
);
2586 if (user_entry
!= NULL
) {
2587 kfree(user_entry
, sizeof *user_entry
);
2593 _mach_make_memory_entry(
2594 vm_map_t target_map
,
2595 memory_object_size_t
*size
,
2596 memory_object_offset_t offset
,
2597 vm_prot_t permission
,
2598 ipc_port_t
*object_handle
,
2599 ipc_port_t parent_entry
)
2601 memory_object_offset_t mo_size
;
2604 mo_size
= (memory_object_offset_t
)*size
;
2605 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
2606 (memory_object_offset_t
)offset
, permission
, object_handle
,
2613 mach_make_memory_entry(
2614 vm_map_t target_map
,
2617 vm_prot_t permission
,
2618 ipc_port_t
*object_handle
,
2619 ipc_port_t parent_entry
)
2621 memory_object_offset_t mo_size
;
2624 mo_size
= (memory_object_offset_t
)*size
;
2625 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
2626 (memory_object_offset_t
)offset
, permission
, object_handle
,
2628 *size
= CAST_DOWN(vm_size_t
, mo_size
);
2635 * Set or clear the map's wiring_required flag. This flag, if set,
2636 * will cause all future virtual memory allocation to allocate
2637 * user wired memory. Unwiring pages wired down as a result of
2638 * this routine is done with the vm_wire interface.
2643 boolean_t must_wire
)
2645 if (map
== VM_MAP_NULL
)
2646 return(KERN_INVALID_ARGUMENT
);
2649 map
->wiring_required
= TRUE
;
2651 map
->wiring_required
= FALSE
;
2653 return(KERN_SUCCESS
);
2656 __private_extern__ kern_return_t
2657 mach_memory_entry_allocate(
2658 vm_named_entry_t
*user_entry_p
,
2659 ipc_port_t
*user_handle_p
)
2661 vm_named_entry_t user_entry
;
2662 ipc_port_t user_handle
;
2663 ipc_port_t previous
;
2665 user_entry
= (vm_named_entry_t
) kalloc(sizeof *user_entry
);
2666 if (user_entry
== NULL
)
2667 return KERN_FAILURE
;
2669 named_entry_lock_init(user_entry
);
2671 user_handle
= ipc_port_alloc_kernel();
2672 if (user_handle
== IP_NULL
) {
2673 kfree(user_entry
, sizeof *user_entry
);
2674 return KERN_FAILURE
;
2676 ip_lock(user_handle
);
2678 /* make a sonce right */
2679 user_handle
->ip_sorights
++;
2680 ip_reference(user_handle
);
2682 user_handle
->ip_destination
= IP_NULL
;
2683 user_handle
->ip_receiver_name
= MACH_PORT_NULL
;
2684 user_handle
->ip_receiver
= ipc_space_kernel
;
2686 /* make a send right */
2687 user_handle
->ip_mscount
++;
2688 user_handle
->ip_srights
++;
2689 ip_reference(user_handle
);
2691 ipc_port_nsrequest(user_handle
, 1, user_handle
, &previous
);
2692 /* nsrequest unlocks user_handle */
2694 user_entry
->backing
.pager
= NULL
;
2695 user_entry
->is_sub_map
= FALSE
;
2696 user_entry
->is_pager
= FALSE
;
2697 user_entry
->size
= 0;
2698 user_entry
->internal
= FALSE
;
2699 user_entry
->ref_count
= 1;
2701 ipc_kobject_set(user_handle
, (ipc_kobject_t
) user_entry
,
2704 *user_entry_p
= user_entry
;
2705 *user_handle_p
= user_handle
;
2707 return KERN_SUCCESS
;
2711 * mach_memory_object_memory_entry_64
2713 * Create a named entry backed by the provided pager.
2715 * JMM - we need to hold a reference on the pager -
2716 * and release it when the named entry is destroyed.
2719 mach_memory_object_memory_entry_64(
2722 vm_object_offset_t size
,
2723 vm_prot_t permission
,
2724 memory_object_t pager
,
2725 ipc_port_t
*entry_handle
)
2727 unsigned int access
;
2728 vm_named_entry_t user_entry
;
2729 ipc_port_t user_handle
;
2731 if (host
== HOST_NULL
)
2732 return(KERN_INVALID_HOST
);
2734 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2736 return KERN_FAILURE
;
2739 user_entry
->backing
.pager
= pager
;
2740 user_entry
->size
= size
;
2741 user_entry
->offset
= 0;
2742 user_entry
->protection
= permission
& VM_PROT_ALL
;
2743 access
= GET_MAP_MEM(permission
);
2744 SET_MAP_MEM(access
, user_entry
->protection
);
2745 user_entry
->internal
= internal
;
2746 user_entry
->is_sub_map
= FALSE
;
2747 user_entry
->is_pager
= TRUE
;
2748 assert(user_entry
->ref_count
== 1);
2750 *entry_handle
= user_handle
;
2751 return KERN_SUCCESS
;
2755 mach_memory_object_memory_entry(
2759 vm_prot_t permission
,
2760 memory_object_t pager
,
2761 ipc_port_t
*entry_handle
)
2763 return mach_memory_object_memory_entry_64( host
, internal
,
2764 (vm_object_offset_t
)size
, permission
, pager
, entry_handle
);
2769 mach_memory_entry_purgable_control(
2770 ipc_port_t entry_port
,
2771 vm_purgable_t control
,
2775 vm_named_entry_t mem_entry
;
2778 if (entry_port
== IP_NULL
||
2779 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
2780 return KERN_INVALID_ARGUMENT
;
2783 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
2785 named_entry_lock(mem_entry
);
2787 if (mem_entry
->is_sub_map
|| mem_entry
->is_pager
) {
2788 named_entry_unlock(mem_entry
);
2789 return KERN_INVALID_ARGUMENT
;
2792 object
= mem_entry
->backing
.object
;
2793 if (object
== VM_OBJECT_NULL
) {
2794 named_entry_unlock(mem_entry
);
2795 return KERN_INVALID_ARGUMENT
;
2798 vm_object_lock(object
);
2800 /* check that named entry covers entire object ? */
2801 if (mem_entry
->offset
!= 0 || object
->size
!= mem_entry
->size
) {
2802 vm_object_unlock(object
);
2803 named_entry_unlock(mem_entry
);
2804 return KERN_INVALID_ARGUMENT
;
2807 named_entry_unlock(mem_entry
);
2809 kr
= vm_object_purgable_control(object
, control
, state
);
2811 vm_object_unlock(object
);
2817 * mach_memory_entry_port_release:
2819 * Release a send right on a named entry port. This is the correct
2820 * way to destroy a named entry. When the last right on the port is
2821 * released, ipc_kobject_destroy() will call mach_destroy_memory_entry().
2824 mach_memory_entry_port_release(
2827 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
2828 ipc_port_release_send(port
);
2832 * mach_destroy_memory_entry:
2834 * Drops a reference on a memory entry and destroys the memory entry if
2835 * there are no more references on it.
2836 * NOTE: This routine should not be called to destroy a memory entry from the
2837 * kernel, as it will not release the Mach port associated with the memory
2838 * entry. The proper way to destroy a memory entry in the kernel is to
2839 * call mach_memort_entry_port_release() to release the kernel's send-right on
2840 * the memory entry's port. When the last send right is released, the memory
2841 * entry will be destroyed via ipc_kobject_destroy().
2844 mach_destroy_memory_entry(
2847 vm_named_entry_t named_entry
;
2849 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
2850 #endif /* MACH_ASSERT */
2851 named_entry
= (vm_named_entry_t
)port
->ip_kobject
;
2852 mutex_lock(&(named_entry
)->Lock
);
2853 named_entry
->ref_count
-= 1;
2854 if(named_entry
->ref_count
== 0) {
2855 if (named_entry
->is_sub_map
) {
2856 vm_map_deallocate(named_entry
->backing
.map
);
2857 } else if (!named_entry
->is_pager
) {
2858 /* release the memory object we've been pointing to */
2859 vm_object_deallocate(named_entry
->backing
.object
);
2860 } /* else JMM - need to drop reference on pager in that case */
2862 mutex_unlock(&(named_entry
)->Lock
);
2864 kfree((void *) port
->ip_kobject
,
2865 sizeof (struct vm_named_entry
));
2867 mutex_unlock(&(named_entry
)->Lock
);
2873 set_dp_control_port(
2874 host_priv_t host_priv
,
2875 ipc_port_t control_port
)
2877 if (host_priv
== HOST_PRIV_NULL
)
2878 return (KERN_INVALID_HOST
);
2880 if (IP_VALID(dynamic_pager_control_port
))
2881 ipc_port_release_send(dynamic_pager_control_port
);
2883 dynamic_pager_control_port
= control_port
;
2884 return KERN_SUCCESS
;
2888 get_dp_control_port(
2889 host_priv_t host_priv
,
2890 ipc_port_t
*control_port
)
2892 if (host_priv
== HOST_PRIV_NULL
)
2893 return (KERN_INVALID_HOST
);
2895 *control_port
= ipc_port_copy_send(dynamic_pager_control_port
);
2896 return KERN_SUCCESS
;
2900 /* ******* Temporary Internal calls to UPL for BSD ***** */
2902 extern int kernel_upl_map(
2905 vm_offset_t
*dst_addr
);
2907 extern int kernel_upl_unmap(
2911 extern int kernel_upl_commit(
2913 upl_page_info_t
*pl
,
2914 mach_msg_type_number_t count
);
2916 extern int kernel_upl_commit_range(
2918 upl_offset_t offset
,
2921 upl_page_info_array_t pl
,
2922 mach_msg_type_number_t count
);
2924 extern int kernel_upl_abort(
2928 extern int kernel_upl_abort_range(
2930 upl_offset_t offset
,
2939 vm_offset_t
*dst_addr
)
2941 return vm_upl_map(map
, upl
, dst_addr
);
2950 return vm_upl_unmap(map
, upl
);
2956 upl_page_info_t
*pl
,
2957 mach_msg_type_number_t count
)
2961 kr
= upl_commit(upl
, pl
, count
);
2962 upl_deallocate(upl
);
2968 kernel_upl_commit_range(
2970 upl_offset_t offset
,
2973 upl_page_info_array_t pl
,
2974 mach_msg_type_number_t count
)
2976 boolean_t finished
= FALSE
;
2979 if (flags
& UPL_COMMIT_FREE_ON_EMPTY
)
2980 flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
2982 kr
= upl_commit_range(upl
, offset
, size
, flags
, pl
, count
, &finished
);
2984 if ((flags
& UPL_COMMIT_NOTIFY_EMPTY
) && finished
)
2985 upl_deallocate(upl
);
2991 kernel_upl_abort_range(
2993 upl_offset_t offset
,
2998 boolean_t finished
= FALSE
;
3000 if (abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
)
3001 abort_flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
3003 kr
= upl_abort_range(upl
, offset
, size
, abort_flags
, &finished
);
3005 if ((abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
) && finished
)
3006 upl_deallocate(upl
);
3018 kr
= upl_abort(upl
, abort_type
);
3019 upl_deallocate(upl
);
3024 * Now a kernel-private interface (for BootCache
3025 * use only). Need a cleaner way to create an
3026 * empty vm_map() and return a handle to it.
3030 vm_region_object_create(
3031 __unused vm_map_t target_map
,
3033 ipc_port_t
*object_handle
)
3035 vm_named_entry_t user_entry
;
3036 ipc_port_t user_handle
;
3040 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
3042 return KERN_FAILURE
;
3045 /* Create a named object based on a submap of specified size */
3047 new_map
= vm_map_create(PMAP_NULL
, VM_MAP_MIN_ADDRESS
,
3048 vm_map_round_page(size
), TRUE
);
3050 user_entry
->backing
.map
= new_map
;
3051 user_entry
->internal
= TRUE
;
3052 user_entry
->is_sub_map
= TRUE
;
3053 user_entry
->offset
= 0;
3054 user_entry
->protection
= VM_PROT_ALL
;
3055 user_entry
->size
= size
;
3056 assert(user_entry
->ref_count
== 1);
3058 *object_handle
= user_handle
;
3059 return KERN_SUCCESS
;
3063 ppnum_t
vm_map_get_phys_page( /* forward */
3065 vm_offset_t offset
);
3068 vm_map_get_phys_page(
3072 vm_object_offset_t offset
;
3074 vm_map_offset_t map_offset
;
3075 vm_map_entry_t entry
;
3076 ppnum_t phys_page
= 0;
3078 map_offset
= vm_map_trunc_page(addr
);
3081 while (vm_map_lookup_entry(map
, map_offset
, &entry
)) {
3083 if (entry
->object
.vm_object
== VM_OBJECT_NULL
) {
3087 if (entry
->is_sub_map
) {
3089 vm_map_lock(entry
->object
.sub_map
);
3091 map
= entry
->object
.sub_map
;
3092 map_offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3093 vm_map_unlock(old_map
);
3096 if (entry
->object
.vm_object
->phys_contiguous
) {
3097 /* These are not standard pageable memory mappings */
3098 /* If they are not present in the object they will */
3099 /* have to be picked up from the pager through the */
3100 /* fault mechanism. */
3101 if(entry
->object
.vm_object
->shadow_offset
== 0) {
3102 /* need to call vm_fault */
3104 vm_fault(map
, map_offset
, VM_PROT_NONE
,
3105 FALSE
, THREAD_UNINT
, NULL
, 0);
3109 offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3110 phys_page
= (ppnum_t
)
3111 ((entry
->object
.vm_object
->shadow_offset
3116 offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3117 object
= entry
->object
.vm_object
;
3118 vm_object_lock(object
);
3120 vm_page_t dst_page
= vm_page_lookup(object
,offset
);
3121 if(dst_page
== VM_PAGE_NULL
) {
3122 if(object
->shadow
) {
3123 vm_object_t old_object
;
3124 vm_object_lock(object
->shadow
);
3125 old_object
= object
;
3126 offset
= offset
+ object
->shadow_offset
;
3127 object
= object
->shadow
;
3128 vm_object_unlock(old_object
);
3130 vm_object_unlock(object
);
3134 phys_page
= (ppnum_t
)(dst_page
->phys_page
);
3135 vm_object_unlock(object
);
3149 kern_return_t
kernel_object_iopl_request( /* forward */
3150 vm_named_entry_t named_entry
,
3151 memory_object_offset_t offset
,
3152 vm_size_t
*upl_size
,
3154 upl_page_info_array_t user_page_list
,
3155 unsigned int *page_list_count
,
3159 kernel_object_iopl_request(
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
,
3173 caller_flags
= *flags
;
3175 if (caller_flags
& ~UPL_VALID_FLAGS
) {
3177 * For forward compatibility's sake,
3178 * reject any unknown flag.
3180 return KERN_INVALID_VALUE
;
3183 /* a few checks to make sure user is obeying rules */
3184 if(*upl_size
== 0) {
3185 if(offset
>= named_entry
->size
)
3186 return(KERN_INVALID_RIGHT
);
3187 *upl_size
= named_entry
->size
- offset
;
3189 if(caller_flags
& UPL_COPYOUT_FROM
) {
3190 if((named_entry
->protection
& VM_PROT_READ
)
3192 return(KERN_INVALID_RIGHT
);
3195 if((named_entry
->protection
&
3196 (VM_PROT_READ
| VM_PROT_WRITE
))
3197 != (VM_PROT_READ
| VM_PROT_WRITE
)) {
3198 return(KERN_INVALID_RIGHT
);
3201 if(named_entry
->size
< (offset
+ *upl_size
))
3202 return(KERN_INVALID_ARGUMENT
);
3204 /* the callers parameter offset is defined to be the */
3205 /* offset from beginning of named entry offset in object */
3206 offset
= offset
+ named_entry
->offset
;
3208 if(named_entry
->is_sub_map
)
3209 return (KERN_INVALID_ARGUMENT
);
3211 named_entry_lock(named_entry
);
3213 if (named_entry
->is_pager
) {
3214 object
= vm_object_enter(named_entry
->backing
.pager
,
3215 named_entry
->offset
+ named_entry
->size
,
3216 named_entry
->internal
,
3219 if (object
== VM_OBJECT_NULL
) {
3220 named_entry_unlock(named_entry
);
3221 return(KERN_INVALID_OBJECT
);
3224 /* JMM - drop reference on the pager here? */
3226 /* create an extra reference for the object */
3227 vm_object_lock(object
);
3228 vm_object_reference_locked(object
);
3229 named_entry
->backing
.object
= object
;
3230 named_entry
->is_pager
= FALSE
;
3231 named_entry_unlock(named_entry
);
3233 /* wait for object (if any) to be ready */
3234 if (!named_entry
->internal
) {
3235 while (!object
->pager_ready
) {
3236 vm_object_wait(object
,
3237 VM_OBJECT_EVENT_PAGER_READY
,
3239 vm_object_lock(object
);
3242 vm_object_unlock(object
);
3245 /* This is the case where we are going to operate */
3246 /* an an already known object. If the object is */
3247 /* not ready it is internal. An external */
3248 /* object cannot be mapped until it is ready */
3249 /* we can therefore avoid the ready check */
3251 object
= named_entry
->backing
.object
;
3252 vm_object_reference(object
);
3253 named_entry_unlock(named_entry
);
3256 if (!object
->private) {
3257 if (*upl_size
> (MAX_UPL_TRANSFER
*PAGE_SIZE
))
3258 *upl_size
= (MAX_UPL_TRANSFER
*PAGE_SIZE
);
3259 if (object
->phys_contiguous
) {
3260 *flags
= UPL_PHYS_CONTIG
;
3265 *flags
= UPL_DEV_MEMORY
| UPL_PHYS_CONTIG
;
3268 ret
= vm_object_iopl_request(object
,
3275 vm_object_deallocate(object
);