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 count
> VM_MAP_ENTRY_MAX
)
523 return(KERN_INVALID_ARGUMENT
);
525 error
= KERN_SUCCESS
;
526 for(i
=0; i
<count
; i
++) {
527 vm_map_address_t map_addr
;
528 vm_map_size_t map_size
;
530 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
531 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
534 error
= vm_map_copyin(map
,
537 FALSE
, /* src_destroy */
539 if (KERN_SUCCESS
== error
) {
540 error
= vm_map_copyout(
544 if (KERN_SUCCESS
== error
) {
545 data_list
[i
].address
= map_addr
;
548 vm_map_copy_discard(copy
);
551 data_list
[i
].address
= (mach_vm_address_t
)0;
552 data_list
[i
].size
= (mach_vm_size_t
)0;
559 * Read/copy a list of address ranges from specified map.
561 * MIG does not know how to deal with a returned array of
562 * vm_map_copy_t structures, so we have to do the copyout
565 * The source and destination ranges are limited to those
566 * that can be described with a vm_address_t (i.e. same
567 * size map as the kernel).
569 * JMM - If the result of the copyout is an address range
570 * that cannot be described with a vm_address_t (i.e. the
571 * caller had a larger address space but used this call
572 * anyway), it will result in a truncated address being
573 * returned (and a likely confused caller).
579 vm_read_entry_t data_list
,
582 mach_msg_type_number_t i
;
586 if (map
== VM_MAP_NULL
||
587 count
> VM_MAP_ENTRY_MAX
)
588 return(KERN_INVALID_ARGUMENT
);
590 error
= KERN_SUCCESS
;
591 for(i
=0; i
<count
; i
++) {
592 vm_map_address_t map_addr
;
593 vm_map_size_t map_size
;
595 map_addr
= (vm_map_address_t
)(data_list
[i
].address
);
596 map_size
= (vm_map_size_t
)(data_list
[i
].size
);
599 error
= vm_map_copyin(map
,
602 FALSE
, /* src_destroy */
604 if (KERN_SUCCESS
== error
) {
605 error
= vm_map_copyout(current_task()->map
,
608 if (KERN_SUCCESS
== error
) {
609 data_list
[i
].address
=
610 CAST_DOWN(vm_offset_t
, map_addr
);
613 vm_map_copy_discard(copy
);
616 data_list
[i
].address
= (mach_vm_address_t
)0;
617 data_list
[i
].size
= (mach_vm_size_t
)0;
623 * mach_vm_read_overwrite -
624 * Overwrite a range of the current map with data from the specified
627 * In making an assumption that the current thread is local, it is
628 * no longer cluster-safe without a fully supportive local proxy
629 * thread/task (but we don't support cluster's anymore so this is moot).
633 mach_vm_read_overwrite(
635 mach_vm_address_t address
,
637 mach_vm_address_t data
,
638 mach_vm_size_t
*data_size
)
643 if (map
== VM_MAP_NULL
)
644 return(KERN_INVALID_ARGUMENT
);
646 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
647 (vm_map_size_t
)size
, FALSE
, ©
);
649 if (KERN_SUCCESS
== error
) {
650 error
= vm_map_copy_overwrite(current_thread()->map
,
651 (vm_map_address_t
)data
,
653 if (KERN_SUCCESS
== error
) {
657 vm_map_copy_discard(copy
);
663 * vm_read_overwrite -
664 * Overwrite a range of the current map with data from the specified
667 * This routine adds the additional limitation that the source and
668 * destination ranges must be describable with vm_address_t values
669 * (i.e. the same size address spaces as the kernel, or at least the
670 * the ranges are in that first portion of the respective address
677 vm_address_t address
,
680 vm_size_t
*data_size
)
685 if (map
== VM_MAP_NULL
)
686 return(KERN_INVALID_ARGUMENT
);
688 error
= vm_map_copyin(map
, (vm_map_address_t
)address
,
689 (vm_map_size_t
)size
, FALSE
, ©
);
691 if (KERN_SUCCESS
== error
) {
692 error
= vm_map_copy_overwrite(current_thread()->map
,
693 (vm_map_address_t
)data
,
695 if (KERN_SUCCESS
== error
) {
699 vm_map_copy_discard(copy
);
707 * Overwrite the specified address range with the data provided
708 * (from the current map).
713 mach_vm_address_t address
,
715 __unused mach_msg_type_number_t size
)
717 if (map
== VM_MAP_NULL
)
718 return KERN_INVALID_ARGUMENT
;
720 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
721 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
726 * Overwrite the specified address range with the data provided
727 * (from the current map).
729 * The addressability of the range of addresses to overwrite is
730 * limited bu the use of a vm_address_t (same size as kernel map).
731 * Either the target map is also small, or the range is in the
732 * low addresses within it.
737 vm_address_t address
,
739 __unused mach_msg_type_number_t size
)
741 if (map
== VM_MAP_NULL
)
742 return KERN_INVALID_ARGUMENT
;
744 return vm_map_copy_overwrite(map
, (vm_map_address_t
)address
,
745 (vm_map_copy_t
) data
, FALSE
/* interruptible XXX */);
750 * Overwrite one range of the specified map with the contents of
751 * another range within that same map (i.e. both address ranges
757 mach_vm_address_t source_address
,
759 mach_vm_address_t dest_address
)
764 if (map
== VM_MAP_NULL
)
765 return KERN_INVALID_ARGUMENT
;
767 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
768 (vm_map_size_t
)size
, FALSE
, ©
);
770 if (KERN_SUCCESS
== kr
) {
771 kr
= vm_map_copy_overwrite(map
,
772 (vm_map_address_t
)dest_address
,
773 copy
, FALSE
/* interruptible XXX */);
775 if (KERN_SUCCESS
!= kr
)
776 vm_map_copy_discard(copy
);
784 vm_address_t source_address
,
786 vm_address_t dest_address
)
791 if (map
== VM_MAP_NULL
)
792 return KERN_INVALID_ARGUMENT
;
794 kr
= vm_map_copyin(map
, (vm_map_address_t
)source_address
,
795 (vm_map_size_t
)size
, FALSE
, ©
);
797 if (KERN_SUCCESS
== kr
) {
798 kr
= vm_map_copy_overwrite(map
,
799 (vm_map_address_t
)dest_address
,
800 copy
, FALSE
/* interruptible XXX */);
802 if (KERN_SUCCESS
!= kr
)
803 vm_map_copy_discard(copy
);
810 * Map some range of an object into an address space.
812 * The object can be one of several types of objects:
813 * NULL - anonymous memory
814 * a named entry - a range within another address space
815 * or a range within a memory object
816 * a whole memory object
822 mach_vm_offset_t
*address
,
823 mach_vm_size_t initial_size
,
824 mach_vm_offset_t mask
,
827 vm_object_offset_t offset
,
829 vm_prot_t cur_protection
,
830 vm_prot_t max_protection
,
831 vm_inherit_t inheritance
)
833 vm_map_address_t map_addr
;
834 vm_map_size_t map_size
;
836 vm_object_size_t size
;
837 kern_return_t result
;
840 * Check arguments for validity
842 if ((target_map
== VM_MAP_NULL
) ||
843 (cur_protection
& ~VM_PROT_ALL
) ||
844 (max_protection
& ~VM_PROT_ALL
) ||
845 (inheritance
> VM_INHERIT_LAST_VALID
) ||
847 return(KERN_INVALID_ARGUMENT
);
849 map_addr
= vm_map_trunc_page(*address
);
850 map_size
= vm_map_round_page(initial_size
);
851 size
= vm_object_round_page(initial_size
);
854 * Find the vm object (if any) corresponding to this port.
856 if (!IP_VALID(port
)) {
857 object
= VM_OBJECT_NULL
;
860 } else if (ip_kotype(port
) == IKOT_NAMED_ENTRY
) {
861 vm_named_entry_t named_entry
;
863 named_entry
= (vm_named_entry_t
)port
->ip_kobject
;
864 /* a few checks to make sure user is obeying rules */
866 if(offset
>= named_entry
->size
)
867 return(KERN_INVALID_RIGHT
);
868 size
= named_entry
->size
- offset
;
870 if((named_entry
->protection
& max_protection
) != max_protection
)
871 return(KERN_INVALID_RIGHT
);
872 if((named_entry
->protection
& cur_protection
) != cur_protection
)
873 return(KERN_INVALID_RIGHT
);
874 if(named_entry
->size
< (offset
+ size
))
875 return(KERN_INVALID_ARGUMENT
);
877 /* the callers parameter offset is defined to be the */
878 /* offset from beginning of named entry offset in object */
879 offset
= offset
+ named_entry
->offset
;
881 named_entry_lock(named_entry
);
882 if(named_entry
->is_sub_map
) {
883 vm_map_entry_t map_entry
;
885 named_entry_unlock(named_entry
);
886 vm_object_reference(vm_submap_object
);
887 if ((result
= vm_map_enter(target_map
,
889 (vm_map_offset_t
)mask
, flags
,
892 cur_protection
, max_protection
, inheritance
893 )) != KERN_SUCCESS
) {
894 vm_object_deallocate(vm_submap_object
);
898 VM_GET_FLAGS_ALIAS(flags
, alias
);
899 if ((alias
== VM_MEMORY_SHARED_PMAP
) &&
901 vm_map_submap(target_map
, map_addr
,
903 named_entry
->backing
.map
,
904 (vm_map_offset_t
)offset
, TRUE
);
906 vm_map_submap(target_map
, map_addr
,
908 named_entry
->backing
.map
,
909 (vm_map_offset_t
)offset
, FALSE
);
912 if(vm_map_lookup_entry(
913 target_map
, map_addr
, &map_entry
)) {
914 map_entry
->needs_copy
= TRUE
;
921 } else if (named_entry
->is_pager
) {
923 vm_prot_t protections
;
924 unsigned int wimg_mode
;
925 boolean_t cache_attr
;
927 protections
= named_entry
->protection
929 access
= GET_MAP_MEM(named_entry
->protection
);
931 object
= vm_object_enter(
932 named_entry
->backing
.pager
,
934 named_entry
->internal
,
937 if (object
== VM_OBJECT_NULL
) {
938 named_entry_unlock(named_entry
);
939 return(KERN_INVALID_OBJECT
);
942 /* JMM - drop reference on pager here */
944 /* create an extra ref for the named entry */
945 vm_object_lock(object
);
946 vm_object_reference_locked(object
);
947 named_entry
->backing
.object
= object
;
948 named_entry
->is_pager
= FALSE
;
949 named_entry_unlock(named_entry
);
951 wimg_mode
= object
->wimg_bits
;
952 if(access
== MAP_MEM_IO
) {
953 wimg_mode
= VM_WIMG_IO
;
954 } else if (access
== MAP_MEM_COPYBACK
) {
955 wimg_mode
= VM_WIMG_USE_DEFAULT
;
956 } else if (access
== MAP_MEM_WTHRU
) {
957 wimg_mode
= VM_WIMG_WTHRU
;
958 } else if (access
== MAP_MEM_WCOMB
) {
959 wimg_mode
= VM_WIMG_WCOMB
;
961 if ((wimg_mode
== VM_WIMG_IO
)
962 || (wimg_mode
== VM_WIMG_WCOMB
))
967 /* wait for object (if any) to be ready */
968 if (!named_entry
->internal
) {
969 while (!object
->pager_ready
) {
970 vm_object_wait(object
,
971 VM_OBJECT_EVENT_PAGER_READY
,
973 vm_object_lock(object
);
977 if(object
->wimg_bits
!= wimg_mode
) {
980 vm_object_paging_wait(object
, THREAD_UNINT
);
982 object
->wimg_bits
= wimg_mode
;
983 queue_iterate(&object
->memq
, p
, vm_page_t
, listq
) {
984 if (!p
->fictitious
) {
985 pmap_disconnect(p
->phys_page
);
987 pmap_sync_page_attributes_phys(p
->phys_page
);
991 object
->true_share
= TRUE
;
992 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
993 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
994 vm_object_unlock(object
);
996 /* This is the case where we are going to map */
997 /* an already mapped object. If the object is */
998 /* not ready it is internal. An external */
999 /* object cannot be mapped until it is ready */
1000 /* we can therefore avoid the ready check */
1002 object
= named_entry
->backing
.object
;
1003 assert(object
!= VM_OBJECT_NULL
);
1004 named_entry_unlock(named_entry
);
1005 vm_object_reference(object
);
1007 } else if (ip_kotype(port
) == IKOT_MEMORY_OBJECT
) {
1009 * JMM - This is temporary until we unify named entries
1010 * and raw memory objects.
1012 * Detected fake ip_kotype for a memory object. In
1013 * this case, the port isn't really a port at all, but
1014 * instead is just a raw memory object.
1017 if ((object
= vm_object_enter((memory_object_t
)port
,
1018 size
, FALSE
, FALSE
, FALSE
))
1020 return(KERN_INVALID_OBJECT
);
1022 /* wait for object (if any) to be ready */
1023 if (object
!= VM_OBJECT_NULL
) {
1024 if(object
== kernel_object
) {
1025 printf("Warning: Attempt to map kernel object"
1026 " by a non-private kernel entity\n");
1027 return(KERN_INVALID_OBJECT
);
1029 vm_object_lock(object
);
1030 while (!object
->pager_ready
) {
1031 vm_object_wait(object
,
1032 VM_OBJECT_EVENT_PAGER_READY
,
1034 vm_object_lock(object
);
1036 vm_object_unlock(object
);
1039 return (KERN_INVALID_OBJECT
);
1043 * Perform the copy if requested
1047 vm_object_t new_object
;
1048 vm_object_offset_t new_offset
;
1050 result
= vm_object_copy_strategically(object
, offset
, size
,
1051 &new_object
, &new_offset
,
1055 if (result
== KERN_MEMORY_RESTART_COPY
) {
1057 boolean_t src_needs_copy
;
1061 * We currently ignore src_needs_copy.
1062 * This really is the issue of how to make
1063 * MEMORY_OBJECT_COPY_SYMMETRIC safe for
1064 * non-kernel users to use. Solution forthcoming.
1065 * In the meantime, since we don't allow non-kernel
1066 * memory managers to specify symmetric copy,
1067 * we won't run into problems here.
1069 new_object
= object
;
1070 new_offset
= offset
;
1071 success
= vm_object_copy_quickly(&new_object
,
1076 result
= KERN_SUCCESS
;
1079 * Throw away the reference to the
1080 * original object, as it won't be mapped.
1083 vm_object_deallocate(object
);
1085 if (result
!= KERN_SUCCESS
)
1088 object
= new_object
;
1089 offset
= new_offset
;
1092 if ((result
= vm_map_enter(target_map
,
1093 &map_addr
, map_size
,
1094 (vm_map_offset_t
)mask
,
1098 cur_protection
, max_protection
, inheritance
1100 vm_object_deallocate(object
);
1101 *address
= map_addr
;
1106 /* legacy interface */
1109 vm_map_t target_map
,
1110 vm_offset_t
*address
,
1115 vm_object_offset_t offset
,
1117 vm_prot_t cur_protection
,
1118 vm_prot_t max_protection
,
1119 vm_inherit_t inheritance
)
1121 mach_vm_address_t map_addr
;
1122 mach_vm_size_t map_size
;
1123 mach_vm_offset_t map_mask
;
1126 map_addr
= (mach_vm_address_t
)*address
;
1127 map_size
= (mach_vm_size_t
)size
;
1128 map_mask
= (mach_vm_offset_t
)mask
;
1130 kr
= mach_vm_map(target_map
, &map_addr
, map_size
, map_mask
, flags
,
1132 cur_protection
, max_protection
, inheritance
);
1133 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1137 /* temporary, until world build */
1140 vm_map_t target_map
,
1141 vm_offset_t
*address
,
1148 vm_prot_t cur_protection
,
1149 vm_prot_t max_protection
,
1150 vm_inherit_t inheritance
)
1152 mach_vm_address_t map_addr
;
1153 mach_vm_size_t map_size
;
1154 mach_vm_offset_t map_mask
;
1155 vm_object_offset_t obj_offset
;
1158 map_addr
= (mach_vm_address_t
)*address
;
1159 map_size
= (mach_vm_size_t
)size
;
1160 map_mask
= (mach_vm_offset_t
)mask
;
1161 obj_offset
= (vm_object_offset_t
)offset
;
1163 kr
= mach_vm_map(target_map
, &map_addr
, map_size
, map_mask
, flags
,
1164 port
, obj_offset
, copy
,
1165 cur_protection
, max_protection
, inheritance
);
1166 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1172 * Remap a range of memory from one task into another,
1173 * to another address range within the same task, or
1174 * over top of itself (with altered permissions and/or
1175 * as an in-place copy of itself).
1180 vm_map_t target_map
,
1181 mach_vm_offset_t
*address
,
1182 mach_vm_size_t size
,
1183 mach_vm_offset_t mask
,
1186 mach_vm_offset_t memory_address
,
1188 vm_prot_t
*cur_protection
,
1189 vm_prot_t
*max_protection
,
1190 vm_inherit_t inheritance
)
1192 vm_map_offset_t map_addr
;
1195 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
)
1196 return KERN_INVALID_ARGUMENT
;
1198 map_addr
= (vm_map_offset_t
)*address
;
1200 kr
= vm_map_remap(target_map
,
1211 *address
= map_addr
;
1217 * Remap a range of memory from one task into another,
1218 * to another address range within the same task, or
1219 * over top of itself (with altered permissions and/or
1220 * as an in-place copy of itself).
1222 * The addressability of the source and target address
1223 * range is limited by the size of vm_address_t (in the
1228 vm_map_t target_map
,
1229 vm_offset_t
*address
,
1234 vm_offset_t memory_address
,
1236 vm_prot_t
*cur_protection
,
1237 vm_prot_t
*max_protection
,
1238 vm_inherit_t inheritance
)
1240 vm_map_offset_t map_addr
;
1243 if (VM_MAP_NULL
== target_map
|| VM_MAP_NULL
== src_map
)
1244 return KERN_INVALID_ARGUMENT
;
1246 map_addr
= (vm_map_offset_t
)*address
;
1248 kr
= vm_map_remap(target_map
,
1259 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1264 * NOTE: these routine (and this file) will no longer require mach_host_server.h
1265 * when mach_vm_wire and vm_wire are changed to use ledgers.
1267 #include <mach/mach_host_server.h>
1270 * Specify that the range of the virtual address space
1271 * of the target task must not cause page faults for
1272 * the indicated accesses.
1274 * [ To unwire the pages, specify VM_PROT_NONE. ]
1278 host_priv_t host_priv
,
1280 mach_vm_offset_t start
,
1281 mach_vm_size_t size
,
1286 if (host_priv
== HOST_PRIV_NULL
)
1287 return KERN_INVALID_HOST
;
1289 assert(host_priv
== &realhost
);
1291 if (map
== VM_MAP_NULL
)
1292 return KERN_INVALID_TASK
;
1294 if (access
& ~VM_PROT_ALL
)
1295 return KERN_INVALID_ARGUMENT
;
1297 if (access
!= VM_PROT_NONE
) {
1298 rc
= vm_map_wire(map
, vm_map_trunc_page(start
),
1299 vm_map_round_page(start
+size
), access
, TRUE
);
1301 rc
= vm_map_unwire(map
, vm_map_trunc_page(start
),
1302 vm_map_round_page(start
+size
), TRUE
);
1309 * Specify that the range of the virtual address space
1310 * of the target task must not cause page faults for
1311 * the indicated accesses.
1313 * [ To unwire the pages, specify VM_PROT_NONE. ]
1317 host_priv_t host_priv
,
1318 register vm_map_t map
,
1325 if (host_priv
== HOST_PRIV_NULL
)
1326 return KERN_INVALID_HOST
;
1328 assert(host_priv
== &realhost
);
1330 if (map
== VM_MAP_NULL
)
1331 return KERN_INVALID_TASK
;
1333 if ((access
& ~VM_PROT_ALL
) || (start
+ size
< start
))
1334 return KERN_INVALID_ARGUMENT
;
1338 } else if (access
!= VM_PROT_NONE
) {
1339 rc
= vm_map_wire(map
, vm_map_trunc_page(start
),
1340 vm_map_round_page(start
+size
), access
, TRUE
);
1342 rc
= vm_map_unwire(map
, vm_map_trunc_page(start
),
1343 vm_map_round_page(start
+size
), TRUE
);
1351 * Synchronises the memory range specified with its backing store
1352 * image by either flushing or cleaning the contents to the appropriate
1355 * interpretation of sync_flags
1356 * VM_SYNC_INVALIDATE - discard pages, only return precious
1359 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1360 * - discard pages, write dirty or precious
1361 * pages back to memory manager.
1363 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1364 * - write dirty or precious pages back to
1365 * the memory manager.
1367 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1368 * is a hole in the region, and we would
1369 * have returned KERN_SUCCESS, return
1370 * KERN_INVALID_ADDRESS instead.
1373 * KERN_INVALID_TASK Bad task parameter
1374 * KERN_INVALID_ARGUMENT both sync and async were specified.
1375 * KERN_SUCCESS The usual.
1376 * KERN_INVALID_ADDRESS There was a hole in the region.
1382 mach_vm_address_t address
,
1383 mach_vm_size_t size
,
1384 vm_sync_t sync_flags
)
1387 if (map
== VM_MAP_NULL
)
1388 return(KERN_INVALID_TASK
);
1390 return vm_map_msync(map
, (vm_map_address_t
)address
,
1391 (vm_map_size_t
)size
, sync_flags
);
1397 * Synchronises the memory range specified with its backing store
1398 * image by either flushing or cleaning the contents to the appropriate
1401 * interpretation of sync_flags
1402 * VM_SYNC_INVALIDATE - discard pages, only return precious
1405 * VM_SYNC_INVALIDATE & (VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS)
1406 * - discard pages, write dirty or precious
1407 * pages back to memory manager.
1409 * VM_SYNC_SYNCHRONOUS | VM_SYNC_ASYNCHRONOUS
1410 * - write dirty or precious pages back to
1411 * the memory manager.
1413 * VM_SYNC_CONTIGUOUS - does everything normally, but if there
1414 * is a hole in the region, and we would
1415 * have returned KERN_SUCCESS, return
1416 * KERN_INVALID_ADDRESS instead.
1418 * The addressability of the range is limited to that which can
1419 * be described by a vm_address_t.
1422 * KERN_INVALID_TASK Bad task parameter
1423 * KERN_INVALID_ARGUMENT both sync and async were specified.
1424 * KERN_SUCCESS The usual.
1425 * KERN_INVALID_ADDRESS There was a hole in the region.
1431 vm_address_t address
,
1433 vm_sync_t sync_flags
)
1436 if (map
== VM_MAP_NULL
)
1437 return(KERN_INVALID_TASK
);
1439 return vm_map_msync(map
, (vm_map_address_t
)address
,
1440 (vm_map_size_t
)size
, sync_flags
);
1445 * mach_vm_behavior_set
1447 * Sets the paging behavior attribute for the specified range
1448 * in the specified map.
1450 * This routine will fail with KERN_INVALID_ADDRESS if any address
1451 * in [start,start+size) is not a valid allocated memory region.
1454 mach_vm_behavior_set(
1456 mach_vm_offset_t start
,
1457 mach_vm_size_t size
,
1458 vm_behavior_t new_behavior
)
1460 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
1461 return(KERN_INVALID_ARGUMENT
);
1464 return KERN_SUCCESS
;
1466 return(vm_map_behavior_set(map
, vm_map_trunc_page(start
),
1467 vm_map_round_page(start
+size
), new_behavior
));
1473 * Sets the paging behavior attribute for the specified range
1474 * in the specified map.
1476 * This routine will fail with KERN_INVALID_ADDRESS if any address
1477 * in [start,start+size) is not a valid allocated memory region.
1479 * This routine is potentially limited in addressibility by the
1480 * use of vm_offset_t (if the map provided is larger than the
1488 vm_behavior_t new_behavior
)
1490 if ((map
== VM_MAP_NULL
) || (start
+ size
< start
))
1491 return(KERN_INVALID_ARGUMENT
);
1494 return KERN_SUCCESS
;
1496 return(vm_map_behavior_set(map
, vm_map_trunc_page(start
),
1497 vm_map_round_page(start
+size
), new_behavior
));
1503 * User call to obtain information about a region in
1504 * a task's address map. Currently, only one flavor is
1507 * XXX The reserved and behavior fields cannot be filled
1508 * in until the vm merge from the IK is completed, and
1509 * vm_reserve is implemented.
1511 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1517 mach_vm_offset_t
*address
, /* IN/OUT */
1518 mach_vm_size_t
*size
, /* OUT */
1519 vm_region_flavor_t flavor
, /* IN */
1520 vm_region_info_t info
, /* OUT */
1521 mach_msg_type_number_t
*count
, /* IN/OUT */
1522 mach_port_t
*object_name
) /* OUT */
1524 vm_map_offset_t map_addr
;
1525 vm_map_size_t map_size
;
1528 if (VM_MAP_NULL
== map
)
1529 return KERN_INVALID_ARGUMENT
;
1531 map_addr
= (vm_map_offset_t
)*address
;
1532 map_size
= (vm_map_size_t
)*size
;
1534 /* legacy conversion */
1535 if (VM_REGION_BASIC_INFO
== flavor
)
1536 flavor
= VM_REGION_BASIC_INFO_64
;
1538 kr
= vm_map_region(map
,
1539 &map_addr
, &map_size
,
1540 flavor
, info
, count
,
1543 *address
= map_addr
;
1549 * vm_region_64 and vm_region:
1551 * User call to obtain information about a region in
1552 * a task's address map. Currently, only one flavor is
1555 * XXX The reserved and behavior fields cannot be filled
1556 * in until the vm merge from the IK is completed, and
1557 * vm_reserve is implemented.
1559 * XXX Dependency: syscall_vm_region() also supports only one flavor.
1565 vm_offset_t
*address
, /* IN/OUT */
1566 vm_size_t
*size
, /* OUT */
1567 vm_region_flavor_t flavor
, /* IN */
1568 vm_region_info_t info
, /* OUT */
1569 mach_msg_type_number_t
*count
, /* IN/OUT */
1570 mach_port_t
*object_name
) /* OUT */
1572 vm_map_offset_t map_addr
;
1573 vm_map_size_t map_size
;
1576 if (VM_MAP_NULL
== map
)
1577 return KERN_INVALID_ARGUMENT
;
1579 map_addr
= (vm_map_offset_t
)*address
;
1580 map_size
= (vm_map_size_t
)*size
;
1582 /* legacy conversion */
1583 if (VM_REGION_BASIC_INFO
== flavor
)
1584 flavor
= VM_REGION_BASIC_INFO_64
;
1586 kr
= vm_map_region(map
,
1587 &map_addr
, &map_size
,
1588 flavor
, info
, count
,
1591 *address
= CAST_DOWN(vm_offset_t
, map_addr
);
1592 *size
= CAST_DOWN(vm_size_t
, map_size
);
1594 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1595 return KERN_INVALID_ADDRESS
;
1602 vm_address_t
*address
, /* IN/OUT */
1603 vm_size_t
*size
, /* OUT */
1604 vm_region_flavor_t flavor
, /* IN */
1605 vm_region_info_t info
, /* OUT */
1606 mach_msg_type_number_t
*count
, /* IN/OUT */
1607 mach_port_t
*object_name
) /* OUT */
1609 vm_map_address_t map_addr
;
1610 vm_map_size_t map_size
;
1613 if (VM_MAP_NULL
== map
)
1614 return KERN_INVALID_ARGUMENT
;
1616 map_addr
= (vm_map_address_t
)*address
;
1617 map_size
= (vm_map_size_t
)*size
;
1619 kr
= vm_map_region(map
,
1620 &map_addr
, &map_size
,
1621 flavor
, info
, count
,
1624 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1625 *size
= CAST_DOWN(vm_size_t
, map_size
);
1627 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1628 return KERN_INVALID_ADDRESS
;
1633 * vm_region_recurse: A form of vm_region which follows the
1634 * submaps in a target map
1638 mach_vm_region_recurse(
1640 mach_vm_address_t
*address
,
1641 mach_vm_size_t
*size
,
1643 vm_region_recurse_info_t info
,
1644 mach_msg_type_number_t
*infoCnt
)
1646 vm_map_address_t map_addr
;
1647 vm_map_size_t map_size
;
1650 if (VM_MAP_NULL
== map
)
1651 return KERN_INVALID_ARGUMENT
;
1653 map_addr
= (vm_map_address_t
)*address
;
1654 map_size
= (vm_map_size_t
)*size
;
1656 kr
= vm_map_region_recurse_64(
1661 (vm_region_submap_info_64_t
)info
,
1664 *address
= map_addr
;
1670 * vm_region_recurse: A form of vm_region which follows the
1671 * submaps in a target map
1675 vm_region_recurse_64(
1677 vm_address_t
*address
,
1680 vm_region_recurse_info_64_t info
,
1681 mach_msg_type_number_t
*infoCnt
)
1683 vm_map_address_t map_addr
;
1684 vm_map_size_t map_size
;
1687 if (VM_MAP_NULL
== map
)
1688 return KERN_INVALID_ARGUMENT
;
1690 map_addr
= (vm_map_address_t
)*address
;
1691 map_size
= (vm_map_size_t
)*size
;
1693 kr
= vm_map_region_recurse_64(
1698 (vm_region_submap_info_64_t
)info
,
1701 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1702 *size
= CAST_DOWN(vm_size_t
, map_size
);
1704 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1705 return KERN_INVALID_ADDRESS
;
1712 vm_offset_t
*address
, /* IN/OUT */
1713 vm_size_t
*size
, /* OUT */
1714 natural_t
*depth
, /* IN/OUT */
1715 vm_region_recurse_info_t info32
, /* IN/OUT */
1716 mach_msg_type_number_t
*infoCnt
) /* IN/OUT */
1718 vm_region_submap_info_data_64_t info64
;
1719 vm_region_submap_info_t info
;
1720 vm_map_address_t map_addr
;
1721 vm_map_size_t map_size
;
1724 if (VM_MAP_NULL
== map
|| *infoCnt
< VM_REGION_SUBMAP_INFO_COUNT
)
1725 return KERN_INVALID_ARGUMENT
;
1728 map_addr
= (vm_map_address_t
)*address
;
1729 map_size
= (vm_map_size_t
)*size
;
1730 info
= (vm_region_submap_info_t
)info32
;
1731 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT_64
;
1733 kr
= vm_map_region_recurse_64(map
, &map_addr
,&map_size
,
1734 depth
, &info64
, infoCnt
);
1736 info
->protection
= info64
.protection
;
1737 info
->max_protection
= info64
.max_protection
;
1738 info
->inheritance
= info64
.inheritance
;
1739 info
->offset
= (uint32_t)info64
.offset
; /* trouble-maker */
1740 info
->user_tag
= info64
.user_tag
;
1741 info
->pages_resident
= info64
.pages_resident
;
1742 info
->pages_shared_now_private
= info64
.pages_shared_now_private
;
1743 info
->pages_swapped_out
= info64
.pages_swapped_out
;
1744 info
->pages_dirtied
= info64
.pages_dirtied
;
1745 info
->ref_count
= info64
.ref_count
;
1746 info
->shadow_depth
= info64
.shadow_depth
;
1747 info
->external_pager
= info64
.external_pager
;
1748 info
->share_mode
= info64
.share_mode
;
1749 info
->is_submap
= info64
.is_submap
;
1750 info
->behavior
= info64
.behavior
;
1751 info
->object_id
= info64
.object_id
;
1752 info
->user_wired_count
= info64
.user_wired_count
;
1754 *address
= CAST_DOWN(vm_address_t
, map_addr
);
1755 *size
= CAST_DOWN(vm_size_t
, map_size
);
1756 *infoCnt
= VM_REGION_SUBMAP_INFO_COUNT
;
1758 if (KERN_SUCCESS
== kr
&& map_addr
+ map_size
> VM_MAX_ADDRESS
)
1759 return KERN_INVALID_ADDRESS
;
1764 vm_purgable_control(
1766 vm_offset_t address
,
1767 vm_purgable_t control
,
1770 if (VM_MAP_NULL
== map
)
1771 return KERN_INVALID_ARGUMENT
;
1773 return vm_map_purgable_control(map
,
1774 vm_map_trunc_page(address
),
1781 * Ordinarily, the right to allocate CPM is restricted
1782 * to privileged applications (those that can gain access
1783 * to the host priv port). Set this variable to zero if
1784 * you want to let any application allocate CPM.
1786 unsigned int vm_allocate_cpm_privileged
= 0;
1789 * Allocate memory in the specified map, with the caveat that
1790 * the memory is physically contiguous. This call may fail
1791 * if the system can't find sufficient contiguous memory.
1792 * This call may cause or lead to heart-stopping amounts of
1795 * Memory obtained from this call should be freed in the
1796 * normal way, viz., via vm_deallocate.
1800 host_priv_t host_priv
,
1806 vm_map_address_t map_addr
;
1807 vm_map_size_t map_size
;
1810 if (vm_allocate_cpm_privileged
&& HOST_PRIV_NULL
== host_priv
)
1811 return KERN_INVALID_HOST
;
1813 if (VM_MAP_NULL
== map
)
1814 return KERN_INVALID_ARGUMENT
;
1816 map_addr
= (vm_map_address_t
)*addr
;
1817 map_size
= (vm_map_size_t
)size
;
1819 kr
= vm_map_enter_cpm(map
,
1824 *addr
= CAST_DOWN(vm_address_t
, map_addr
);
1832 mach_vm_offset_t offset
,
1836 if (VM_MAP_NULL
== map
)
1837 return KERN_INVALID_ARGUMENT
;
1839 return vm_map_page_info(map
,
1840 vm_map_trunc_page(offset
),
1841 disposition
, ref_count
);
1851 if (VM_MAP_NULL
== map
)
1852 return KERN_INVALID_ARGUMENT
;
1854 return vm_map_page_info(map
,
1855 vm_map_trunc_page(offset
),
1856 disposition
, ref_count
);
1859 /* map a (whole) upl into an address space */
1864 vm_offset_t
*dst_addr
)
1866 vm_map_offset_t map_addr
;
1869 if (VM_MAP_NULL
== map
)
1870 return KERN_INVALID_ARGUMENT
;
1872 kr
= vm_map_enter_upl(map
, upl
, &map_addr
);
1873 *dst_addr
= CAST_DOWN(vm_offset_t
, map_addr
);
1882 if (VM_MAP_NULL
== map
)
1883 return KERN_INVALID_ARGUMENT
;
1885 return (vm_map_remove_upl(map
, upl
));
1888 /* Retrieve a upl for an object underlying an address range in a map */
1893 vm_map_offset_t map_offset
,
1894 upl_size_t
*upl_size
,
1896 upl_page_info_array_t page_list
,
1897 unsigned int *count
,
1899 int force_data_sync
)
1904 if (VM_MAP_NULL
== map
)
1905 return KERN_INVALID_ARGUMENT
;
1907 map_flags
= *flags
& ~UPL_NOZEROFILL
;
1908 if (force_data_sync
)
1909 map_flags
|= UPL_FORCE_DATA_SYNC
;
1911 kr
= vm_map_create_upl(map
,
1919 *flags
= (map_flags
& ~UPL_FORCE_DATA_SYNC
);
1924 __private_extern__ kern_return_t
1925 mach_memory_entry_allocate(
1926 vm_named_entry_t
*user_entry_p
,
1927 ipc_port_t
*user_handle_p
); /* forward */
1930 * mach_make_memory_entry_64
1932 * Think of it as a two-stage vm_remap() operation. First
1933 * you get a handle. Second, you get map that handle in
1934 * somewhere else. Rather than doing it all at once (and
1935 * without needing access to the other whole map).
1939 mach_make_memory_entry_64(
1940 vm_map_t target_map
,
1941 memory_object_size_t
*size
,
1942 memory_object_offset_t offset
,
1943 vm_prot_t permission
,
1944 ipc_port_t
*object_handle
,
1945 ipc_port_t parent_handle
)
1947 vm_map_version_t version
;
1948 vm_named_entry_t parent_entry
;
1949 vm_named_entry_t user_entry
;
1950 ipc_port_t user_handle
;
1954 /* needed for call to vm_map_lookup_locked */
1956 vm_object_offset_t obj_off
;
1958 vm_map_offset_t lo_offset
, hi_offset
;
1959 vm_behavior_t behavior
;
1961 vm_object_t shadow_object
;
1963 /* needed for direct map entry manipulation */
1964 vm_map_entry_t map_entry
;
1965 vm_map_entry_t next_entry
;
1967 vm_map_t original_map
= target_map
;
1968 vm_map_size_t total_size
;
1969 vm_map_size_t map_size
;
1970 vm_map_offset_t map_offset
;
1971 vm_map_offset_t local_offset
;
1972 vm_object_size_t mappable_size
;
1974 unsigned int access
;
1975 vm_prot_t protections
;
1976 unsigned int wimg_mode
;
1977 boolean_t cache_attr
= FALSE
;
1979 if (((permission
& 0x00FF0000) &
1981 MAP_MEM_NAMED_CREATE
|
1983 MAP_MEM_NAMED_REUSE
))) {
1985 * Unknown flag: reject for forward compatibility.
1987 return KERN_INVALID_VALUE
;
1990 if (parent_handle
!= IP_NULL
&&
1991 ip_kotype(parent_handle
) == IKOT_NAMED_ENTRY
) {
1992 parent_entry
= (vm_named_entry_t
) parent_handle
->ip_kobject
;
1994 parent_entry
= NULL
;
1997 protections
= permission
& VM_PROT_ALL
;
1998 access
= GET_MAP_MEM(permission
);
2000 user_handle
= IP_NULL
;
2003 map_offset
= vm_map_trunc_page(offset
);
2004 map_size
= vm_map_round_page(*size
);
2006 if (permission
& MAP_MEM_ONLY
) {
2007 boolean_t parent_is_object
;
2009 if (parent_entry
== NULL
) {
2010 return KERN_INVALID_ARGUMENT
;
2013 parent_is_object
= !(parent_entry
->is_sub_map
|| parent_entry
->is_pager
);
2014 object
= parent_entry
->backing
.object
;
2015 if(parent_is_object
&& object
!= VM_OBJECT_NULL
)
2016 wimg_mode
= object
->wimg_bits
;
2018 wimg_mode
= VM_WIMG_DEFAULT
;
2019 if((access
!= GET_MAP_MEM(parent_entry
->protection
)) &&
2020 !(parent_entry
->protection
& VM_PROT_WRITE
)) {
2021 return KERN_INVALID_RIGHT
;
2023 if(access
== MAP_MEM_IO
) {
2024 SET_MAP_MEM(access
, parent_entry
->protection
);
2025 wimg_mode
= VM_WIMG_IO
;
2026 } else if (access
== MAP_MEM_COPYBACK
) {
2027 SET_MAP_MEM(access
, parent_entry
->protection
);
2028 wimg_mode
= VM_WIMG_DEFAULT
;
2029 } else if (access
== MAP_MEM_WTHRU
) {
2030 SET_MAP_MEM(access
, parent_entry
->protection
);
2031 wimg_mode
= VM_WIMG_WTHRU
;
2032 } else if (access
== MAP_MEM_WCOMB
) {
2033 SET_MAP_MEM(access
, parent_entry
->protection
);
2034 wimg_mode
= VM_WIMG_WCOMB
;
2036 if(parent_is_object
&& object
&&
2037 (access
!= MAP_MEM_NOOP
) &&
2038 (!(object
->nophyscache
))) {
2039 if(object
->wimg_bits
!= wimg_mode
) {
2041 if ((wimg_mode
== VM_WIMG_IO
)
2042 || (wimg_mode
== VM_WIMG_WCOMB
))
2046 vm_object_lock(object
);
2047 vm_object_paging_wait(object
, THREAD_UNINT
);
2048 object
->wimg_bits
= wimg_mode
;
2049 queue_iterate(&object
->memq
,
2050 p
, vm_page_t
, listq
) {
2051 if (!p
->fictitious
) {
2052 pmap_disconnect(p
->phys_page
);
2054 pmap_sync_page_attributes_phys(p
->phys_page
);
2057 vm_object_unlock(object
);
2061 *object_handle
= IP_NULL
;
2062 return KERN_SUCCESS
;
2065 if(permission
& MAP_MEM_NAMED_CREATE
) {
2066 kr
= mach_memory_entry_allocate(&user_entry
, &user_handle
);
2067 if (kr
!= KERN_SUCCESS
) {
2068 return KERN_FAILURE
;
2072 * Force the creation of the VM object now.
2074 if (map_size
> (vm_map_size_t
) VM_MAX_ADDRESS
) {
2076 * LP64todo - for now, we can only allocate 4GB
2077 * internal objects because the default pager can't
2078 * page bigger ones. Remove this when it can.
2084 object
= vm_object_allocate(map_size
);
2085 assert(object
!= VM_OBJECT_NULL
);
2087 if (permission
& MAP_MEM_PURGABLE
) {
2088 if (! (permission
& VM_PROT_WRITE
)) {
2089 /* if we can't write, we can't purge */
2090 vm_object_deallocate(object
);
2091 kr
= KERN_INVALID_ARGUMENT
;
2094 object
->purgable
= VM_OBJECT_PURGABLE_NONVOLATILE
;
2098 * The VM object is brand new and nobody else knows about it,
2099 * so we don't need to lock it.
2102 wimg_mode
= object
->wimg_bits
;
2103 if (access
== MAP_MEM_IO
) {
2104 wimg_mode
= VM_WIMG_IO
;
2105 } else if (access
== MAP_MEM_COPYBACK
) {
2106 wimg_mode
= VM_WIMG_DEFAULT
;
2107 } else if (access
== MAP_MEM_WTHRU
) {
2108 wimg_mode
= VM_WIMG_WTHRU
;
2109 } else if (access
== MAP_MEM_WCOMB
) {
2110 wimg_mode
= VM_WIMG_WCOMB
;
2112 if (access
!= MAP_MEM_NOOP
) {
2113 object
->wimg_bits
= wimg_mode
;
2115 /* the object has no pages, so no WIMG bits to update here */
2119 * We use this path when we want to make sure that
2120 * nobody messes with the object (coalesce, for
2121 * example) before we map it.
2122 * We might want to use these objects for transposition via
2123 * vm_object_transpose() too, so we don't want any copy or
2124 * shadow objects either...
2126 object
->copy_strategy
= MEMORY_OBJECT_COPY_NONE
;
2128 user_entry
->backing
.object
= object
;
2129 user_entry
->internal
= TRUE
;
2130 user_entry
->is_sub_map
= FALSE
;
2131 user_entry
->is_pager
= FALSE
;
2132 user_entry
->offset
= 0;
2133 user_entry
->protection
= protections
;
2134 SET_MAP_MEM(access
, user_entry
->protection
);
2135 user_entry
->size
= map_size
;
2137 /* user_object pager and internal fields are not used */
2138 /* when the object field is filled in. */
2140 *size
= CAST_DOWN(vm_size_t
, map_size
);
2141 *object_handle
= user_handle
;
2142 return KERN_SUCCESS
;
2145 if (parent_entry
== NULL
||
2146 (permission
& MAP_MEM_NAMED_REUSE
)) {
2148 /* Create a named object based on address range within the task map */
2149 /* Go find the object at given address */
2152 vm_map_lock_read(target_map
);
2154 /* get the object associated with the target address */
2155 /* note we check the permission of the range against */
2156 /* that requested by the caller */
2158 kr
= vm_map_lookup_locked(&target_map
, map_offset
,
2159 protections
, &version
,
2160 &object
, &obj_off
, &prot
, &wired
, &behavior
,
2161 &lo_offset
, &hi_offset
, &real_map
);
2162 if (kr
!= KERN_SUCCESS
) {
2163 vm_map_unlock_read(target_map
);
2166 if (((prot
& protections
) != protections
)
2167 || (object
== kernel_object
)) {
2168 kr
= KERN_INVALID_RIGHT
;
2169 vm_object_unlock(object
);
2170 vm_map_unlock_read(target_map
);
2171 if(real_map
!= target_map
)
2172 vm_map_unlock_read(real_map
);
2173 if(object
== kernel_object
) {
2174 printf("Warning: Attempt to create a named"
2175 " entry from the kernel_object\n");
2180 /* We have an object, now check to see if this object */
2181 /* is suitable. If not, create a shadow and share that */
2184 * We have to unlock the VM object to avoid deadlocking with
2185 * a VM map lock (the lock ordering is map, the object), if we
2186 * need to modify the VM map to create a shadow object. Since
2187 * we might release the VM map lock below anyway, we have
2188 * to release the VM map lock now.
2189 * XXX FBDP There must be a way to avoid this double lookup...
2191 * Take an extra reference on the VM object to make sure it's
2192 * not going to disappear.
2194 vm_object_reference_locked(object
); /* extra ref to hold obj */
2195 vm_object_unlock(object
);
2197 local_map
= original_map
;
2198 local_offset
= map_offset
;
2199 if(target_map
!= local_map
) {
2200 vm_map_unlock_read(target_map
);
2201 if(real_map
!= target_map
)
2202 vm_map_unlock_read(real_map
);
2203 vm_map_lock_read(local_map
);
2204 target_map
= local_map
;
2205 real_map
= local_map
;
2208 if(!vm_map_lookup_entry(local_map
,
2209 local_offset
, &map_entry
)) {
2210 kr
= KERN_INVALID_ARGUMENT
;
2211 vm_map_unlock_read(target_map
);
2212 if(real_map
!= target_map
)
2213 vm_map_unlock_read(real_map
);
2214 vm_object_deallocate(object
); /* release extra ref */
2215 object
= VM_OBJECT_NULL
;
2218 if(!(map_entry
->is_sub_map
)) {
2219 if(map_entry
->object
.vm_object
!= object
) {
2220 kr
= KERN_INVALID_ARGUMENT
;
2221 vm_map_unlock_read(target_map
);
2222 if(real_map
!= target_map
)
2223 vm_map_unlock_read(real_map
);
2224 vm_object_deallocate(object
); /* release extra ref */
2225 object
= VM_OBJECT_NULL
;
2232 local_map
= map_entry
->object
.sub_map
;
2234 vm_map_lock_read(local_map
);
2235 vm_map_unlock_read(tmap
);
2236 target_map
= local_map
;
2237 real_map
= local_map
;
2238 local_offset
= local_offset
- map_entry
->vme_start
;
2239 local_offset
+= map_entry
->offset
;
2244 * We found the VM map entry, lock the VM object again.
2246 vm_object_lock(object
);
2247 if(map_entry
->wired_count
) {
2248 /* JMM - The check below should be reworked instead. */
2249 object
->true_share
= TRUE
;
2251 if(((map_entry
->max_protection
) & protections
) != protections
) {
2252 kr
= KERN_INVALID_RIGHT
;
2253 vm_object_unlock(object
);
2254 vm_map_unlock_read(target_map
);
2255 if(real_map
!= target_map
)
2256 vm_map_unlock_read(real_map
);
2257 vm_object_deallocate(object
);
2258 object
= VM_OBJECT_NULL
;
2262 mappable_size
= hi_offset
- obj_off
;
2263 total_size
= map_entry
->vme_end
- map_entry
->vme_start
;
2264 if(map_size
> mappable_size
) {
2265 /* try to extend mappable size if the entries */
2266 /* following are from the same object and are */
2268 next_entry
= map_entry
->vme_next
;
2269 /* lets see if the next map entry is still */
2270 /* pointing at this object and is contiguous */
2271 while(map_size
> mappable_size
) {
2272 if((next_entry
->object
.vm_object
== object
) &&
2273 (next_entry
->vme_start
==
2274 next_entry
->vme_prev
->vme_end
) &&
2275 (next_entry
->offset
==
2276 next_entry
->vme_prev
->offset
+
2277 (next_entry
->vme_prev
->vme_end
-
2278 next_entry
->vme_prev
->vme_start
))) {
2279 if(((next_entry
->max_protection
)
2280 & protections
) != protections
) {
2283 if (next_entry
->needs_copy
!=
2284 map_entry
->needs_copy
)
2286 mappable_size
+= next_entry
->vme_end
2287 - next_entry
->vme_start
;
2288 total_size
+= next_entry
->vme_end
2289 - next_entry
->vme_start
;
2290 next_entry
= next_entry
->vme_next
;
2298 if(object
->internal
) {
2299 /* vm_map_lookup_locked will create a shadow if */
2300 /* needs_copy is set but does not check for the */
2301 /* other two conditions shown. It is important to */
2302 /* set up an object which will not be pulled from */
2305 if ((map_entry
->needs_copy
|| object
->shadowed
||
2306 (object
->size
> total_size
))
2307 && !object
->true_share
) {
2309 * We have to unlock the VM object before
2310 * trying to upgrade the VM map lock, to
2311 * honor lock ordering (map then object).
2312 * Otherwise, we would deadlock if another
2313 * thread holds a read lock on the VM map and
2314 * is trying to acquire the VM object's lock.
2315 * We still hold an extra reference on the
2316 * VM object, guaranteeing that it won't
2319 vm_object_unlock(object
);
2321 if (vm_map_lock_read_to_write(target_map
)) {
2323 * We couldn't upgrade our VM map lock
2324 * from "read" to "write" and we lost
2326 * Start all over again...
2328 vm_object_deallocate(object
); /* extra ref */
2329 target_map
= original_map
;
2332 vm_object_lock(object
);
2335 * JMM - We need to avoid coming here when the object
2336 * is wired by anybody, not just the current map. Why
2337 * couldn't we use the standard vm_object_copy_quickly()
2341 /* create a shadow object */
2342 vm_object_shadow(&map_entry
->object
.vm_object
,
2343 &map_entry
->offset
, total_size
);
2344 shadow_object
= map_entry
->object
.vm_object
;
2345 vm_object_unlock(object
);
2347 vm_object_pmap_protect(
2348 object
, map_entry
->offset
,
2350 ((map_entry
->is_shared
2351 || target_map
->mapped
)
2354 map_entry
->vme_start
,
2355 map_entry
->protection
& ~VM_PROT_WRITE
);
2356 total_size
-= (map_entry
->vme_end
2357 - map_entry
->vme_start
);
2358 next_entry
= map_entry
->vme_next
;
2359 map_entry
->needs_copy
= FALSE
;
2360 while (total_size
) {
2361 if(next_entry
->object
.vm_object
== object
) {
2362 shadow_object
->ref_count
++;
2363 vm_object_res_reference(shadow_object
);
2364 next_entry
->object
.vm_object
2366 vm_object_deallocate(object
);
2368 = next_entry
->vme_prev
->offset
+
2369 (next_entry
->vme_prev
->vme_end
2370 - next_entry
->vme_prev
->vme_start
);
2371 next_entry
->needs_copy
= FALSE
;
2373 panic("mach_make_memory_entry_64:"
2374 " map entries out of sync\n");
2378 - next_entry
->vme_start
;
2379 next_entry
= next_entry
->vme_next
;
2383 * Transfer our extra reference to the
2386 vm_object_reference_locked(shadow_object
);
2387 vm_object_deallocate(object
); /* extra ref */
2388 object
= shadow_object
;
2390 obj_off
= (local_offset
- map_entry
->vme_start
)
2391 + map_entry
->offset
;
2393 vm_map_lock_write_to_read(target_map
);
2394 vm_object_lock(object
);
2399 /* note: in the future we can (if necessary) allow for */
2400 /* memory object lists, this will better support */
2401 /* fragmentation, but is it necessary? The user should */
2402 /* be encouraged to create address space oriented */
2403 /* shared objects from CLEAN memory regions which have */
2404 /* a known and defined history. i.e. no inheritence */
2405 /* share, make this call before making the region the */
2406 /* target of ipc's, etc. The code above, protecting */
2407 /* against delayed copy, etc. is mostly defensive. */
2409 wimg_mode
= object
->wimg_bits
;
2410 if(!(object
->nophyscache
)) {
2411 if(access
== MAP_MEM_IO
) {
2412 wimg_mode
= VM_WIMG_IO
;
2413 } else if (access
== MAP_MEM_COPYBACK
) {
2414 wimg_mode
= VM_WIMG_USE_DEFAULT
;
2415 } else if (access
== MAP_MEM_WTHRU
) {
2416 wimg_mode
= VM_WIMG_WTHRU
;
2417 } else if (access
== MAP_MEM_WCOMB
) {
2418 wimg_mode
= VM_WIMG_WCOMB
;
2422 object
->true_share
= TRUE
;
2423 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
2424 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
2427 * The memory entry now points to this VM object and we
2428 * need to hold a reference on the VM object. Use the extra
2429 * reference we took earlier to keep the object alive when we
2433 vm_map_unlock_read(target_map
);
2434 if(real_map
!= target_map
)
2435 vm_map_unlock_read(real_map
);
2437 if(object
->wimg_bits
!= wimg_mode
) {
2440 vm_object_paging_wait(object
, THREAD_UNINT
);
2442 if ((wimg_mode
== VM_WIMG_IO
)
2443 || (wimg_mode
== VM_WIMG_WCOMB
))
2448 queue_iterate(&object
->memq
,
2449 p
, vm_page_t
, listq
) {
2450 if (!p
->fictitious
) {
2451 pmap_disconnect(p
->phys_page
);
2453 pmap_sync_page_attributes_phys(p
->phys_page
);
2456 object
->wimg_bits
= wimg_mode
;
2459 /* the size of mapped entry that overlaps with our region */
2460 /* which is targeted for share. */
2461 /* (entry_end - entry_start) - */
2462 /* offset of our beg addr within entry */
2463 /* it corresponds to this: */
2465 if(map_size
> mappable_size
)
2466 map_size
= mappable_size
;
2468 if (permission
& MAP_MEM_NAMED_REUSE
) {
2470 * Compare what we got with the "parent_entry".
2471 * If they match, re-use the "parent_entry" instead
2472 * of creating a new one.
2474 if (parent_entry
!= NULL
&&
2475 parent_entry
->backing
.object
== object
&&
2476 parent_entry
->internal
== object
->internal
&&
2477 parent_entry
->is_sub_map
== FALSE
&&
2478 parent_entry
->is_pager
== FALSE
&&
2479 parent_entry
->offset
== obj_off
&&
2480 parent_entry
->protection
== protections
&&
2481 parent_entry
->size
== map_size
) {
2483 * We have a match: re-use "parent_entry".
2485 /* release our extra reference on object */
2486 vm_object_unlock(object
);
2487 vm_object_deallocate(object
);
2488 /* parent_entry->ref_count++; XXX ? */
2489 /* Get an extra send-right on handle */
2490 ipc_port_copy_send(parent_handle
);
2491 *object_handle
= parent_handle
;
2492 return KERN_SUCCESS
;
2495 * No match: we need to create a new entry.
2501 vm_object_unlock(object
);
2502 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2504 /* release our unused reference on the object */
2505 vm_object_deallocate(object
);
2506 return KERN_FAILURE
;
2509 user_entry
->backing
.object
= object
;
2510 user_entry
->internal
= object
->internal
;
2511 user_entry
->is_sub_map
= FALSE
;
2512 user_entry
->is_pager
= FALSE
;
2513 user_entry
->offset
= obj_off
;
2514 user_entry
->protection
= permission
;
2515 user_entry
->size
= map_size
;
2517 /* user_object pager and internal fields are not used */
2518 /* when the object field is filled in. */
2520 *size
= CAST_DOWN(vm_size_t
, map_size
);
2521 *object_handle
= user_handle
;
2522 return KERN_SUCCESS
;
2525 /* The new object will be base on an existing named object */
2527 if (parent_entry
== NULL
) {
2528 kr
= KERN_INVALID_ARGUMENT
;
2531 if((offset
+ map_size
) > parent_entry
->size
) {
2532 kr
= KERN_INVALID_ARGUMENT
;
2536 if((protections
& parent_entry
->protection
) != protections
) {
2537 kr
= KERN_PROTECTION_FAILURE
;
2541 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2547 user_entry
->size
= map_size
;
2548 user_entry
->offset
= parent_entry
->offset
+ map_offset
;
2549 user_entry
->is_sub_map
= parent_entry
->is_sub_map
;
2550 user_entry
->is_pager
= parent_entry
->is_pager
;
2551 user_entry
->internal
= parent_entry
->internal
;
2552 user_entry
->protection
= protections
;
2554 if(access
!= MAP_MEM_NOOP
) {
2555 SET_MAP_MEM(access
, user_entry
->protection
);
2558 if(parent_entry
->is_sub_map
) {
2559 user_entry
->backing
.map
= parent_entry
->backing
.map
;
2560 vm_map_lock(user_entry
->backing
.map
);
2561 user_entry
->backing
.map
->ref_count
++;
2562 vm_map_unlock(user_entry
->backing
.map
);
2564 else if (parent_entry
->is_pager
) {
2565 user_entry
->backing
.pager
= parent_entry
->backing
.pager
;
2566 /* JMM - don't we need a reference here? */
2568 object
= parent_entry
->backing
.object
;
2569 assert(object
!= VM_OBJECT_NULL
);
2570 user_entry
->backing
.object
= object
;
2571 /* we now point to this object, hold on */
2572 vm_object_reference(object
);
2573 vm_object_lock(object
);
2574 object
->true_share
= TRUE
;
2575 if (object
->copy_strategy
== MEMORY_OBJECT_COPY_SYMMETRIC
)
2576 object
->copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
2577 vm_object_unlock(object
);
2579 *size
= CAST_DOWN(vm_size_t
, map_size
);
2580 *object_handle
= user_handle
;
2581 return KERN_SUCCESS
;
2585 if (user_handle
!= IP_NULL
) {
2586 ipc_port_dealloc_kernel(user_handle
);
2588 if (user_entry
!= NULL
) {
2589 kfree(user_entry
, sizeof *user_entry
);
2595 _mach_make_memory_entry(
2596 vm_map_t target_map
,
2597 memory_object_size_t
*size
,
2598 memory_object_offset_t offset
,
2599 vm_prot_t permission
,
2600 ipc_port_t
*object_handle
,
2601 ipc_port_t parent_entry
)
2603 memory_object_offset_t mo_size
;
2606 mo_size
= (memory_object_offset_t
)*size
;
2607 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
2608 (memory_object_offset_t
)offset
, permission
, object_handle
,
2615 mach_make_memory_entry(
2616 vm_map_t target_map
,
2619 vm_prot_t permission
,
2620 ipc_port_t
*object_handle
,
2621 ipc_port_t parent_entry
)
2623 memory_object_offset_t mo_size
;
2626 mo_size
= (memory_object_offset_t
)*size
;
2627 kr
= mach_make_memory_entry_64(target_map
, &mo_size
,
2628 (memory_object_offset_t
)offset
, permission
, object_handle
,
2630 *size
= CAST_DOWN(vm_size_t
, mo_size
);
2637 * Set or clear the map's wiring_required flag. This flag, if set,
2638 * will cause all future virtual memory allocation to allocate
2639 * user wired memory. Unwiring pages wired down as a result of
2640 * this routine is done with the vm_wire interface.
2645 boolean_t must_wire
)
2647 if (map
== VM_MAP_NULL
)
2648 return(KERN_INVALID_ARGUMENT
);
2651 map
->wiring_required
= TRUE
;
2653 map
->wiring_required
= FALSE
;
2655 return(KERN_SUCCESS
);
2658 __private_extern__ kern_return_t
2659 mach_memory_entry_allocate(
2660 vm_named_entry_t
*user_entry_p
,
2661 ipc_port_t
*user_handle_p
)
2663 vm_named_entry_t user_entry
;
2664 ipc_port_t user_handle
;
2665 ipc_port_t previous
;
2667 user_entry
= (vm_named_entry_t
) kalloc(sizeof *user_entry
);
2668 if (user_entry
== NULL
)
2669 return KERN_FAILURE
;
2671 named_entry_lock_init(user_entry
);
2673 user_handle
= ipc_port_alloc_kernel();
2674 if (user_handle
== IP_NULL
) {
2675 kfree(user_entry
, sizeof *user_entry
);
2676 return KERN_FAILURE
;
2678 ip_lock(user_handle
);
2680 /* make a sonce right */
2681 user_handle
->ip_sorights
++;
2682 ip_reference(user_handle
);
2684 user_handle
->ip_destination
= IP_NULL
;
2685 user_handle
->ip_receiver_name
= MACH_PORT_NULL
;
2686 user_handle
->ip_receiver
= ipc_space_kernel
;
2688 /* make a send right */
2689 user_handle
->ip_mscount
++;
2690 user_handle
->ip_srights
++;
2691 ip_reference(user_handle
);
2693 ipc_port_nsrequest(user_handle
, 1, user_handle
, &previous
);
2694 /* nsrequest unlocks user_handle */
2696 user_entry
->backing
.pager
= NULL
;
2697 user_entry
->is_sub_map
= FALSE
;
2698 user_entry
->is_pager
= FALSE
;
2699 user_entry
->size
= 0;
2700 user_entry
->internal
= FALSE
;
2701 user_entry
->ref_count
= 1;
2703 ipc_kobject_set(user_handle
, (ipc_kobject_t
) user_entry
,
2706 *user_entry_p
= user_entry
;
2707 *user_handle_p
= user_handle
;
2709 return KERN_SUCCESS
;
2713 * mach_memory_object_memory_entry_64
2715 * Create a named entry backed by the provided pager.
2717 * JMM - we need to hold a reference on the pager -
2718 * and release it when the named entry is destroyed.
2721 mach_memory_object_memory_entry_64(
2724 vm_object_offset_t size
,
2725 vm_prot_t permission
,
2726 memory_object_t pager
,
2727 ipc_port_t
*entry_handle
)
2729 unsigned int access
;
2730 vm_named_entry_t user_entry
;
2731 ipc_port_t user_handle
;
2733 if (host
== HOST_NULL
)
2734 return(KERN_INVALID_HOST
);
2736 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
2738 return KERN_FAILURE
;
2741 user_entry
->backing
.pager
= pager
;
2742 user_entry
->size
= size
;
2743 user_entry
->offset
= 0;
2744 user_entry
->protection
= permission
& VM_PROT_ALL
;
2745 access
= GET_MAP_MEM(permission
);
2746 SET_MAP_MEM(access
, user_entry
->protection
);
2747 user_entry
->internal
= internal
;
2748 user_entry
->is_sub_map
= FALSE
;
2749 user_entry
->is_pager
= TRUE
;
2750 assert(user_entry
->ref_count
== 1);
2752 *entry_handle
= user_handle
;
2753 return KERN_SUCCESS
;
2757 mach_memory_object_memory_entry(
2761 vm_prot_t permission
,
2762 memory_object_t pager
,
2763 ipc_port_t
*entry_handle
)
2765 return mach_memory_object_memory_entry_64( host
, internal
,
2766 (vm_object_offset_t
)size
, permission
, pager
, entry_handle
);
2771 mach_memory_entry_purgable_control(
2772 ipc_port_t entry_port
,
2773 vm_purgable_t control
,
2777 vm_named_entry_t mem_entry
;
2780 if (entry_port
== IP_NULL
||
2781 ip_kotype(entry_port
) != IKOT_NAMED_ENTRY
) {
2782 return KERN_INVALID_ARGUMENT
;
2785 mem_entry
= (vm_named_entry_t
) entry_port
->ip_kobject
;
2787 named_entry_lock(mem_entry
);
2789 if (mem_entry
->is_sub_map
|| mem_entry
->is_pager
) {
2790 named_entry_unlock(mem_entry
);
2791 return KERN_INVALID_ARGUMENT
;
2794 object
= mem_entry
->backing
.object
;
2795 if (object
== VM_OBJECT_NULL
) {
2796 named_entry_unlock(mem_entry
);
2797 return KERN_INVALID_ARGUMENT
;
2800 vm_object_lock(object
);
2802 /* check that named entry covers entire object ? */
2803 if (mem_entry
->offset
!= 0 || object
->size
!= mem_entry
->size
) {
2804 vm_object_unlock(object
);
2805 named_entry_unlock(mem_entry
);
2806 return KERN_INVALID_ARGUMENT
;
2809 named_entry_unlock(mem_entry
);
2811 kr
= vm_object_purgable_control(object
, control
, state
);
2813 vm_object_unlock(object
);
2819 * mach_memory_entry_port_release:
2821 * Release a send right on a named entry port. This is the correct
2822 * way to destroy a named entry. When the last right on the port is
2823 * released, ipc_kobject_destroy() will call mach_destroy_memory_entry().
2826 mach_memory_entry_port_release(
2829 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
2830 ipc_port_release_send(port
);
2834 * mach_destroy_memory_entry:
2836 * Drops a reference on a memory entry and destroys the memory entry if
2837 * there are no more references on it.
2838 * NOTE: This routine should not be called to destroy a memory entry from the
2839 * kernel, as it will not release the Mach port associated with the memory
2840 * entry. The proper way to destroy a memory entry in the kernel is to
2841 * call mach_memort_entry_port_release() to release the kernel's send-right on
2842 * the memory entry's port. When the last send right is released, the memory
2843 * entry will be destroyed via ipc_kobject_destroy().
2846 mach_destroy_memory_entry(
2849 vm_named_entry_t named_entry
;
2851 assert(ip_kotype(port
) == IKOT_NAMED_ENTRY
);
2852 #endif /* MACH_ASSERT */
2853 named_entry
= (vm_named_entry_t
)port
->ip_kobject
;
2854 mutex_lock(&(named_entry
)->Lock
);
2855 named_entry
->ref_count
-= 1;
2856 if(named_entry
->ref_count
== 0) {
2857 if (named_entry
->is_sub_map
) {
2858 vm_map_deallocate(named_entry
->backing
.map
);
2859 } else if (!named_entry
->is_pager
) {
2860 /* release the memory object we've been pointing to */
2861 vm_object_deallocate(named_entry
->backing
.object
);
2862 } /* else JMM - need to drop reference on pager in that case */
2864 mutex_unlock(&(named_entry
)->Lock
);
2866 kfree((void *) port
->ip_kobject
,
2867 sizeof (struct vm_named_entry
));
2869 mutex_unlock(&(named_entry
)->Lock
);
2875 set_dp_control_port(
2876 host_priv_t host_priv
,
2877 ipc_port_t control_port
)
2879 if (host_priv
== HOST_PRIV_NULL
)
2880 return (KERN_INVALID_HOST
);
2882 if (IP_VALID(dynamic_pager_control_port
))
2883 ipc_port_release_send(dynamic_pager_control_port
);
2885 dynamic_pager_control_port
= control_port
;
2886 return KERN_SUCCESS
;
2890 get_dp_control_port(
2891 host_priv_t host_priv
,
2892 ipc_port_t
*control_port
)
2894 if (host_priv
== HOST_PRIV_NULL
)
2895 return (KERN_INVALID_HOST
);
2897 *control_port
= ipc_port_copy_send(dynamic_pager_control_port
);
2898 return KERN_SUCCESS
;
2902 /* ******* Temporary Internal calls to UPL for BSD ***** */
2904 extern int kernel_upl_map(
2907 vm_offset_t
*dst_addr
);
2909 extern int kernel_upl_unmap(
2913 extern int kernel_upl_commit(
2915 upl_page_info_t
*pl
,
2916 mach_msg_type_number_t count
);
2918 extern int kernel_upl_commit_range(
2920 upl_offset_t offset
,
2923 upl_page_info_array_t pl
,
2924 mach_msg_type_number_t count
);
2926 extern int kernel_upl_abort(
2930 extern int kernel_upl_abort_range(
2932 upl_offset_t offset
,
2941 vm_offset_t
*dst_addr
)
2943 return vm_upl_map(map
, upl
, dst_addr
);
2952 return vm_upl_unmap(map
, upl
);
2958 upl_page_info_t
*pl
,
2959 mach_msg_type_number_t count
)
2963 kr
= upl_commit(upl
, pl
, count
);
2964 upl_deallocate(upl
);
2970 kernel_upl_commit_range(
2972 upl_offset_t offset
,
2975 upl_page_info_array_t pl
,
2976 mach_msg_type_number_t count
)
2978 boolean_t finished
= FALSE
;
2981 if (flags
& UPL_COMMIT_FREE_ON_EMPTY
)
2982 flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
2984 kr
= upl_commit_range(upl
, offset
, size
, flags
, pl
, count
, &finished
);
2986 if ((flags
& UPL_COMMIT_NOTIFY_EMPTY
) && finished
)
2987 upl_deallocate(upl
);
2993 kernel_upl_abort_range(
2995 upl_offset_t offset
,
3000 boolean_t finished
= FALSE
;
3002 if (abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
)
3003 abort_flags
|= UPL_COMMIT_NOTIFY_EMPTY
;
3005 kr
= upl_abort_range(upl
, offset
, size
, abort_flags
, &finished
);
3007 if ((abort_flags
& UPL_COMMIT_FREE_ON_EMPTY
) && finished
)
3008 upl_deallocate(upl
);
3020 kr
= upl_abort(upl
, abort_type
);
3021 upl_deallocate(upl
);
3026 * Now a kernel-private interface (for BootCache
3027 * use only). Need a cleaner way to create an
3028 * empty vm_map() and return a handle to it.
3032 vm_region_object_create(
3033 __unused vm_map_t target_map
,
3035 ipc_port_t
*object_handle
)
3037 vm_named_entry_t user_entry
;
3038 ipc_port_t user_handle
;
3042 if (mach_memory_entry_allocate(&user_entry
, &user_handle
)
3044 return KERN_FAILURE
;
3047 /* Create a named object based on a submap of specified size */
3049 new_map
= vm_map_create(PMAP_NULL
, VM_MAP_MIN_ADDRESS
,
3050 vm_map_round_page(size
), TRUE
);
3052 user_entry
->backing
.map
= new_map
;
3053 user_entry
->internal
= TRUE
;
3054 user_entry
->is_sub_map
= TRUE
;
3055 user_entry
->offset
= 0;
3056 user_entry
->protection
= VM_PROT_ALL
;
3057 user_entry
->size
= size
;
3058 assert(user_entry
->ref_count
== 1);
3060 *object_handle
= user_handle
;
3061 return KERN_SUCCESS
;
3065 ppnum_t
vm_map_get_phys_page( /* forward */
3067 vm_offset_t offset
);
3070 vm_map_get_phys_page(
3074 vm_object_offset_t offset
;
3076 vm_map_offset_t map_offset
;
3077 vm_map_entry_t entry
;
3078 ppnum_t phys_page
= 0;
3080 map_offset
= vm_map_trunc_page(addr
);
3083 while (vm_map_lookup_entry(map
, map_offset
, &entry
)) {
3085 if (entry
->object
.vm_object
== VM_OBJECT_NULL
) {
3089 if (entry
->is_sub_map
) {
3091 vm_map_lock(entry
->object
.sub_map
);
3093 map
= entry
->object
.sub_map
;
3094 map_offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3095 vm_map_unlock(old_map
);
3098 if (entry
->object
.vm_object
->phys_contiguous
) {
3099 /* These are not standard pageable memory mappings */
3100 /* If they are not present in the object they will */
3101 /* have to be picked up from the pager through the */
3102 /* fault mechanism. */
3103 if(entry
->object
.vm_object
->shadow_offset
== 0) {
3104 /* need to call vm_fault */
3106 vm_fault(map
, map_offset
, VM_PROT_NONE
,
3107 FALSE
, THREAD_UNINT
, NULL
, 0);
3111 offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3112 phys_page
= (ppnum_t
)
3113 ((entry
->object
.vm_object
->shadow_offset
3118 offset
= entry
->offset
+ (map_offset
- entry
->vme_start
);
3119 object
= entry
->object
.vm_object
;
3120 vm_object_lock(object
);
3122 vm_page_t dst_page
= vm_page_lookup(object
,offset
);
3123 if(dst_page
== VM_PAGE_NULL
) {
3124 if(object
->shadow
) {
3125 vm_object_t old_object
;
3126 vm_object_lock(object
->shadow
);
3127 old_object
= object
;
3128 offset
= offset
+ object
->shadow_offset
;
3129 object
= object
->shadow
;
3130 vm_object_unlock(old_object
);
3132 vm_object_unlock(object
);
3136 phys_page
= (ppnum_t
)(dst_page
->phys_page
);
3137 vm_object_unlock(object
);
3151 kern_return_t
kernel_object_iopl_request( /* forward */
3152 vm_named_entry_t named_entry
,
3153 memory_object_offset_t offset
,
3154 vm_size_t
*upl_size
,
3156 upl_page_info_array_t user_page_list
,
3157 unsigned int *page_list_count
,
3161 kernel_object_iopl_request(
3162 vm_named_entry_t named_entry
,
3163 memory_object_offset_t offset
,
3164 vm_size_t
*upl_size
,
3166 upl_page_info_array_t user_page_list
,
3167 unsigned int *page_list_count
,
3175 caller_flags
= *flags
;
3177 if (caller_flags
& ~UPL_VALID_FLAGS
) {
3179 * For forward compatibility's sake,
3180 * reject any unknown flag.
3182 return KERN_INVALID_VALUE
;
3185 /* a few checks to make sure user is obeying rules */
3186 if(*upl_size
== 0) {
3187 if(offset
>= named_entry
->size
)
3188 return(KERN_INVALID_RIGHT
);
3189 *upl_size
= named_entry
->size
- offset
;
3191 if(caller_flags
& UPL_COPYOUT_FROM
) {
3192 if((named_entry
->protection
& VM_PROT_READ
)
3194 return(KERN_INVALID_RIGHT
);
3197 if((named_entry
->protection
&
3198 (VM_PROT_READ
| VM_PROT_WRITE
))
3199 != (VM_PROT_READ
| VM_PROT_WRITE
)) {
3200 return(KERN_INVALID_RIGHT
);
3203 if(named_entry
->size
< (offset
+ *upl_size
))
3204 return(KERN_INVALID_ARGUMENT
);
3206 /* the callers parameter offset is defined to be the */
3207 /* offset from beginning of named entry offset in object */
3208 offset
= offset
+ named_entry
->offset
;
3210 if(named_entry
->is_sub_map
)
3211 return (KERN_INVALID_ARGUMENT
);
3213 named_entry_lock(named_entry
);
3215 if (named_entry
->is_pager
) {
3216 object
= vm_object_enter(named_entry
->backing
.pager
,
3217 named_entry
->offset
+ named_entry
->size
,
3218 named_entry
->internal
,
3221 if (object
== VM_OBJECT_NULL
) {
3222 named_entry_unlock(named_entry
);
3223 return(KERN_INVALID_OBJECT
);
3226 /* JMM - drop reference on the pager here? */
3228 /* create an extra reference for the object */
3229 vm_object_lock(object
);
3230 vm_object_reference_locked(object
);
3231 named_entry
->backing
.object
= object
;
3232 named_entry
->is_pager
= FALSE
;
3233 named_entry_unlock(named_entry
);
3235 /* wait for object (if any) to be ready */
3236 if (!named_entry
->internal
) {
3237 while (!object
->pager_ready
) {
3238 vm_object_wait(object
,
3239 VM_OBJECT_EVENT_PAGER_READY
,
3241 vm_object_lock(object
);
3244 vm_object_unlock(object
);
3247 /* This is the case where we are going to operate */
3248 /* an an already known object. If the object is */
3249 /* not ready it is internal. An external */
3250 /* object cannot be mapped until it is ready */
3251 /* we can therefore avoid the ready check */
3253 object
= named_entry
->backing
.object
;
3254 vm_object_reference(object
);
3255 named_entry_unlock(named_entry
);
3258 if (!object
->private) {
3259 if (*upl_size
> (MAX_UPL_TRANSFER
*PAGE_SIZE
))
3260 *upl_size
= (MAX_UPL_TRANSFER
*PAGE_SIZE
);
3261 if (object
->phys_contiguous
) {
3262 *flags
= UPL_PHYS_CONTIG
;
3267 *flags
= UPL_DEV_MEMORY
| UPL_PHYS_CONTIG
;
3270 ret
= vm_object_iopl_request(object
,
3277 vm_object_deallocate(object
);