2 * Copyright (c) 2007 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * Shared region (... and comm page)
27 * This file handles the VM shared region and comm page.
34 * A shared region is a submap that contains the most common system shared
35 * libraries for a given environment.
36 * An environment is defined by (cpu-type, 64-bitness, root directory).
38 * The point of a shared region is to reduce the setup overhead when exec'ing
40 * A shared region uses a shared VM submap that gets mapped automatically
41 * at exec() time (see vm_map_exec()). The first process of a given
42 * environment sets up the shared region and all further processes in that
43 * environment can re-use that shared region without having to re-create
44 * the same mappings in their VM map. All they need is contained in the shared
46 * It can also shared a pmap (mostly for read-only parts but also for the
47 * initial version of some writable parts), which gets "nested" into the
48 * process's pmap. This reduces the number of soft faults: once one process
49 * brings in a page in the shared region, all the other processes can access
50 * it without having to enter it in their own pmap.
53 * When a process is being exec'ed, vm_map_exec() calls vm_shared_region_enter()
54 * to map the appropriate shared region in the process's address space.
55 * We look up the appropriate shared region for the process's environment.
56 * If we can't find one, we create a new (empty) one and add it to the list.
57 * Otherwise, we just take an extra reference on the shared region we found.
59 * The "dyld" runtime (mapped into the process's address space at exec() time)
60 * will then use the shared_region_check_np() and shared_region_map_np()
61 * system call to validate and/or populate the shared region with the
62 * appropriate dyld_shared_cache file.
64 * The shared region is inherited on fork() and the child simply takes an
65 * extra reference on its parent's shared region.
67 * When the task terminates, we release a reference on its shared region.
68 * When the last reference is released, we destroy the shared region.
70 * After a chroot(), the calling process keeps using its original shared region,
71 * since that's what was mapped when it was started. But its children
72 * will use a different shared region, because they need to use the shared
73 * cache that's relative to the new root directory.
78 * A "comm page" is an area of memory that is populated by the kernel with
79 * the appropriate platform-specific version of some commonly used code.
80 * There is one "comm page" per platform (cpu-type, 64-bitness) but only
81 * for the native cpu-type. No need to overly optimize translated code
82 * for hardware that is not really there !
84 * The comm pages are created and populated at boot time.
86 * The appropriate comm page is mapped into a process's address space
87 * at exec() time, in vm_map_exec().
88 * It is then inherited on fork().
90 * The comm page is shared between the kernel and all applications of
91 * a given platform. Only the kernel can modify it.
93 * Applications just branch to fixed addresses in the comm page and find
94 * the right version of the code for the platform. There is also some
95 * data provided and updated by the kernel for processes to retrieve easily
96 * without having to do a system call.
101 #include <kern/ipc_tt.h>
102 #include <kern/kalloc.h>
103 #include <kern/thread_call.h>
105 #include <mach/mach_vm.h>
107 #include <vm/vm_map.h>
108 #include <vm/vm_shared_region.h>
110 #include <vm/vm_protos.h>
112 #include <machine/commpage.h>
113 #include <machine/cpu_capabilities.h>
115 /* "dyld" uses this to figure out what the kernel supports */
116 int shared_region_version
= 3;
118 /* trace level, output is sent to the system log file */
119 int shared_region_trace_level
= SHARED_REGION_TRACE_ERROR_LVL
;
121 /* should local (non-chroot) shared regions persist when no task uses them ? */
122 int shared_region_persistence
= 0; /* no by default */
124 /* delay before reclaiming an unused shared region */
125 int shared_region_destroy_delay
= 120; /* in seconds */
127 /* this lock protects all the shared region data structures */
128 lck_grp_t
*vm_shared_region_lck_grp
;
129 lck_mtx_t vm_shared_region_lock
;
131 #define vm_shared_region_lock() lck_mtx_lock(&vm_shared_region_lock)
132 #define vm_shared_region_unlock() lck_mtx_unlock(&vm_shared_region_lock)
133 #define vm_shared_region_sleep(event, interruptible) \
134 lck_mtx_sleep(&vm_shared_region_lock, \
139 /* the list of currently available shared regions (one per environment) */
140 queue_head_t vm_shared_region_queue
;
142 static void vm_shared_region_reference_locked(vm_shared_region_t shared_region
);
143 static vm_shared_region_t
vm_shared_region_create(
147 static void vm_shared_region_destroy(vm_shared_region_t shared_region
);
149 static void vm_shared_region_timeout(thread_call_param_t param0
,
150 thread_call_param_t param1
);
152 static int __commpage_setup
= 0;
153 #if defined(__i386__) || defined(__x86_64__)
154 static int __system_power_source
= 1; /* init to extrnal power source */
155 static void post_sys_powersource_internal(int i
, int internal
);
156 #endif /* __i386__ || __x86_64__ */
160 * Initialize the module...
163 vm_shared_region_init(void)
165 SHARED_REGION_TRACE_DEBUG(
166 ("shared_region: -> init\n"));
168 vm_shared_region_lck_grp
= lck_grp_alloc_init("vm shared region",
170 lck_mtx_init(&vm_shared_region_lock
,
171 vm_shared_region_lck_grp
,
174 queue_init(&vm_shared_region_queue
);
176 SHARED_REGION_TRACE_DEBUG(
177 ("shared_region: <- init\n"));
181 * Retrieve a task's shared region and grab an extra reference to
182 * make sure it doesn't disappear while the caller is using it.
183 * The caller is responsible for consuming that extra reference if
187 vm_shared_region_get(
190 vm_shared_region_t shared_region
;
192 SHARED_REGION_TRACE_DEBUG(
193 ("shared_region: -> get(%p)\n",
197 vm_shared_region_lock();
198 shared_region
= task
->shared_region
;
200 assert(shared_region
->sr_ref_count
> 0);
201 vm_shared_region_reference_locked(shared_region
);
203 vm_shared_region_unlock();
206 SHARED_REGION_TRACE_DEBUG(
207 ("shared_region: get(%p) <- %p\n",
208 task
, shared_region
));
210 return shared_region
;
214 * Get the base address of the shared region.
215 * That's the address at which it needs to be mapped in the process's address
217 * No need to lock since this data is set when the shared region is
218 * created and is never modified after that. The caller must hold an extra
219 * reference on the shared region to prevent it from being destroyed.
222 vm_shared_region_base_address(
223 vm_shared_region_t shared_region
)
225 SHARED_REGION_TRACE_DEBUG(
226 ("shared_region: -> base_address(%p)\n",
228 assert(shared_region
->sr_ref_count
> 1);
229 SHARED_REGION_TRACE_DEBUG(
230 ("shared_region: base_address(%p) <- 0x%llx\n",
231 shared_region
, (long long)shared_region
->sr_base_address
));
232 return shared_region
->sr_base_address
;
236 * Get the size of the shared region.
237 * That's the size that needs to be mapped in the process's address
239 * No need to lock since this data is set when the shared region is
240 * created and is never modified after that. The caller must hold an extra
241 * reference on the shared region to prevent it from being destroyed.
244 vm_shared_region_size(
245 vm_shared_region_t shared_region
)
247 SHARED_REGION_TRACE_DEBUG(
248 ("shared_region: -> size(%p)\n",
250 assert(shared_region
->sr_ref_count
> 1);
251 SHARED_REGION_TRACE_DEBUG(
252 ("shared_region: size(%p) <- 0x%llx\n",
253 shared_region
, (long long)shared_region
->sr_size
));
254 return shared_region
->sr_size
;
258 * Get the memory entry of the shared region.
259 * That's the "memory object" that needs to be mapped in the process's address
261 * No need to lock since this data is set when the shared region is
262 * created and is never modified after that. The caller must hold an extra
263 * reference on the shared region to prevent it from being destroyed.
266 vm_shared_region_mem_entry(
267 vm_shared_region_t shared_region
)
269 SHARED_REGION_TRACE_DEBUG(
270 ("shared_region: -> mem_entry(%p)\n",
272 assert(shared_region
->sr_ref_count
> 1);
273 SHARED_REGION_TRACE_DEBUG(
274 ("shared_region: mem_entry(%p) <- %p\n",
275 shared_region
, shared_region
->sr_mem_entry
));
276 return shared_region
->sr_mem_entry
;
280 * Set the shared region the process should use.
281 * A NULL new shared region means that we just want to release the old
283 * The caller should already have an extra reference on the new shared region
284 * (if any). We release a reference on the old shared region (if any).
287 vm_shared_region_set(
289 vm_shared_region_t new_shared_region
)
291 vm_shared_region_t old_shared_region
;
293 SHARED_REGION_TRACE_DEBUG(
294 ("shared_region: -> set(%p, %p)\n",
295 task
, new_shared_region
));
298 vm_shared_region_lock();
300 old_shared_region
= task
->shared_region
;
301 if (new_shared_region
) {
302 assert(new_shared_region
->sr_ref_count
> 0);
305 task
->shared_region
= new_shared_region
;
307 vm_shared_region_unlock();
310 if (old_shared_region
) {
311 assert(old_shared_region
->sr_ref_count
> 0);
312 vm_shared_region_deallocate(old_shared_region
);
315 SHARED_REGION_TRACE_DEBUG(
316 ("shared_region: set(%p) <- old=%p new=%p\n",
317 task
, old_shared_region
, new_shared_region
));
321 * Lookup up the shared region for the desired environment.
322 * If none is found, create a new (empty) one.
323 * Grab an extra reference on the returned shared region, to make sure
324 * it doesn't get destroyed before the caller is done with it. The caller
325 * is responsible for consuming that extra reference if necessary.
328 vm_shared_region_lookup(
333 vm_shared_region_t shared_region
;
334 vm_shared_region_t new_shared_region
;
336 SHARED_REGION_TRACE_DEBUG(
337 ("shared_region: -> lookup(root=%p,cpu=%d,64bit=%d)\n",
338 root_dir
, cputype
, is_64bit
));
340 shared_region
= NULL
;
341 new_shared_region
= NULL
;
343 vm_shared_region_lock();
345 queue_iterate(&vm_shared_region_queue
,
349 assert(shared_region
->sr_ref_count
> 0);
350 if (shared_region
->sr_cpu_type
== cputype
&&
351 shared_region
->sr_root_dir
== root_dir
&&
352 shared_region
->sr_64bit
== is_64bit
) {
353 /* found a match ! */
354 vm_shared_region_reference_locked(shared_region
);
358 if (new_shared_region
== NULL
) {
359 /* no match: create a new one */
360 vm_shared_region_unlock();
361 new_shared_region
= vm_shared_region_create(root_dir
,
364 /* do the lookup again, in case we lost a race */
365 vm_shared_region_lock();
368 /* still no match: use our new one */
369 shared_region
= new_shared_region
;
370 new_shared_region
= NULL
;
371 queue_enter(&vm_shared_region_queue
,
379 vm_shared_region_unlock();
381 if (new_shared_region
) {
383 * We lost a race with someone else to create a new shared
384 * region for that environment. Get rid of our unused one.
386 assert(new_shared_region
->sr_ref_count
== 1);
387 new_shared_region
->sr_ref_count
--;
388 vm_shared_region_destroy(new_shared_region
);
389 new_shared_region
= NULL
;
392 SHARED_REGION_TRACE_DEBUG(
393 ("shared_region: lookup(root=%p,cpu=%d,64bit=%d) <- %p\n",
394 root_dir
, cputype
, is_64bit
, shared_region
));
396 assert(shared_region
->sr_ref_count
> 0);
397 return shared_region
;
401 * Take an extra reference on a shared region.
402 * The vm_shared_region_lock should already be held by the caller.
405 vm_shared_region_reference_locked(
406 vm_shared_region_t shared_region
)
409 lck_mtx_assert(&vm_shared_region_lock
, LCK_MTX_ASSERT_OWNED
);
412 SHARED_REGION_TRACE_DEBUG(
413 ("shared_region: -> reference_locked(%p)\n",
415 assert(shared_region
->sr_ref_count
> 0);
416 shared_region
->sr_ref_count
++;
418 if (shared_region
->sr_timer_call
!= NULL
) {
421 /* cancel and free any pending timeout */
422 cancelled
= thread_call_cancel(shared_region
->sr_timer_call
);
424 thread_call_free(shared_region
->sr_timer_call
);
425 shared_region
->sr_timer_call
= NULL
;
426 /* release the reference held by the cancelled timer */
427 shared_region
->sr_ref_count
--;
429 /* the timer will drop the reference and free itself */
433 SHARED_REGION_TRACE_DEBUG(
434 ("shared_region: reference_locked(%p) <- %d\n",
435 shared_region
, shared_region
->sr_ref_count
));
439 * Release a reference on the shared region.
440 * Destroy it if there are no references left.
443 vm_shared_region_deallocate(
444 vm_shared_region_t shared_region
)
446 SHARED_REGION_TRACE_DEBUG(
447 ("shared_region: -> deallocate(%p)\n",
450 vm_shared_region_lock();
452 assert(shared_region
->sr_ref_count
> 0);
454 if (shared_region
->sr_root_dir
== NULL
) {
456 * Local (i.e. based on the boot volume) shared regions
457 * can persist or not based on the "shared_region_persistence"
459 * Make sure that this one complies.
461 if (shared_region_persistence
&&
462 !shared_region
->sr_persists
) {
463 /* make this one persistent */
464 shared_region
->sr_ref_count
++;
465 shared_region
->sr_persists
= TRUE
;
466 } else if (!shared_region_persistence
&&
467 shared_region
->sr_persists
) {
468 /* make this one no longer persistent */
469 assert(shared_region
->sr_ref_count
> 1);
470 shared_region
->sr_ref_count
--;
471 shared_region
->sr_persists
= FALSE
;
475 assert(shared_region
->sr_ref_count
> 0);
476 shared_region
->sr_ref_count
--;
477 SHARED_REGION_TRACE_DEBUG(
478 ("shared_region: deallocate(%p): ref now %d\n",
479 shared_region
, shared_region
->sr_ref_count
));
481 if (shared_region
->sr_ref_count
== 0) {
484 if (shared_region
->sr_timer_call
== NULL
) {
485 /* hold one reference for the timer */
486 assert(! shared_region
->sr_mapping_in_progress
);
487 shared_region
->sr_ref_count
++;
489 /* set up the timer */
490 shared_region
->sr_timer_call
= thread_call_allocate(
491 (thread_call_func_t
) vm_shared_region_timeout
,
492 (thread_call_param_t
) shared_region
);
494 /* schedule the timer */
495 clock_interval_to_deadline(shared_region_destroy_delay
,
498 thread_call_enter_delayed(shared_region
->sr_timer_call
,
501 SHARED_REGION_TRACE_DEBUG(
502 ("shared_region: deallocate(%p): armed timer\n",
505 vm_shared_region_unlock();
507 /* timer expired: let go of this shared region */
510 * Remove it from the queue first, so no one can find
513 queue_remove(&vm_shared_region_queue
,
517 vm_shared_region_unlock();
518 /* ... and destroy it */
519 vm_shared_region_destroy(shared_region
);
520 shared_region
= NULL
;
523 vm_shared_region_unlock();
526 SHARED_REGION_TRACE_DEBUG(
527 ("shared_region: deallocate(%p) <-\n",
532 vm_shared_region_timeout(
533 thread_call_param_t param0
,
534 __unused thread_call_param_t param1
)
536 vm_shared_region_t shared_region
;
538 shared_region
= (vm_shared_region_t
) param0
;
540 vm_shared_region_deallocate(shared_region
);
544 * Create a new (empty) shared region for a new environment.
546 static vm_shared_region_t
547 vm_shared_region_create(
553 vm_named_entry_t mem_entry
;
554 ipc_port_t mem_entry_port
;
555 vm_shared_region_t shared_region
;
557 mach_vm_offset_t base_address
, pmap_nesting_start
;
558 mach_vm_size_t size
, pmap_nesting_size
;
560 SHARED_REGION_TRACE_DEBUG(
561 ("shared_region: -> create(root=%p,cpu=%d,64bit=%d)\n",
562 root_dir
, cputype
, is_64bit
));
567 mem_entry_port
= IPC_PORT_NULL
;
568 sub_map
= VM_MAP_NULL
;
570 /* create a new shared region structure... */
571 shared_region
= kalloc(sizeof (*shared_region
));
572 if (shared_region
== NULL
) {
573 SHARED_REGION_TRACE_ERROR(
574 ("shared_region: create: couldn't allocate\n"));
578 /* figure out the correct settings for the desired environment */
582 base_address
= SHARED_REGION_BASE_X86_64
;
583 size
= SHARED_REGION_SIZE_X86_64
;
584 pmap_nesting_start
= SHARED_REGION_NESTING_BASE_X86_64
;
585 pmap_nesting_size
= SHARED_REGION_NESTING_SIZE_X86_64
;
587 case CPU_TYPE_POWERPC
:
588 base_address
= SHARED_REGION_BASE_PPC64
;
589 size
= SHARED_REGION_SIZE_PPC64
;
590 pmap_nesting_start
= SHARED_REGION_NESTING_BASE_PPC64
;
591 pmap_nesting_size
= SHARED_REGION_NESTING_SIZE_PPC64
;
594 SHARED_REGION_TRACE_ERROR(
595 ("shared_region: create: unknown cpu type %d\n",
597 kfree(shared_region
, sizeof (*shared_region
));
598 shared_region
= NULL
;
604 base_address
= SHARED_REGION_BASE_I386
;
605 size
= SHARED_REGION_SIZE_I386
;
606 pmap_nesting_start
= SHARED_REGION_NESTING_BASE_I386
;
607 pmap_nesting_size
= SHARED_REGION_NESTING_SIZE_I386
;
609 case CPU_TYPE_POWERPC
:
610 base_address
= SHARED_REGION_BASE_PPC
;
611 size
= SHARED_REGION_SIZE_PPC
;
612 pmap_nesting_start
= SHARED_REGION_NESTING_BASE_PPC
;
613 pmap_nesting_size
= SHARED_REGION_NESTING_SIZE_PPC
;
617 base_address
= SHARED_REGION_BASE_ARM
;
618 size
= SHARED_REGION_SIZE_ARM
;
619 pmap_nesting_start
= SHARED_REGION_NESTING_BASE_ARM
;
620 pmap_nesting_size
= SHARED_REGION_NESTING_SIZE_ARM
;
622 #endif /* CPU_TYPE_ARM */
624 SHARED_REGION_TRACE_ERROR(
625 ("shared_region: create: unknown cpu type %d\n",
627 kfree(shared_region
, sizeof (*shared_region
));
628 shared_region
= NULL
;
634 /* create a memory entry structure and a Mach port handle */
635 kr
= mach_memory_entry_allocate(&mem_entry
,
637 if (kr
!= KERN_SUCCESS
) {
638 kfree(shared_region
, sizeof (*shared_region
));
639 shared_region
= NULL
;
640 SHARED_REGION_TRACE_ERROR(
641 ("shared_region: create: "
642 "couldn't allocate mem_entry\n"));
646 /* create a VM sub map and its pmap */
647 sub_map
= vm_map_create(pmap_create(0, is_64bit
),
650 if (sub_map
== VM_MAP_NULL
) {
651 ipc_port_release_send(mem_entry_port
);
652 kfree(shared_region
, sizeof (*shared_region
));
653 shared_region
= NULL
;
654 SHARED_REGION_TRACE_ERROR(
655 ("shared_region: create: "
656 "couldn't allocate map\n"));
660 /* make the memory entry point to the VM sub map */
661 mem_entry
->is_sub_map
= TRUE
;
662 mem_entry
->backing
.map
= sub_map
;
663 mem_entry
->size
= size
;
664 mem_entry
->protection
= VM_PROT_ALL
;
666 /* make the shared region point at the memory entry */
667 shared_region
->sr_mem_entry
= mem_entry_port
;
669 /* fill in the shared region's environment and settings */
670 shared_region
->sr_base_address
= base_address
;
671 shared_region
->sr_size
= size
;
672 shared_region
->sr_pmap_nesting_start
= pmap_nesting_start
;
673 shared_region
->sr_pmap_nesting_size
= pmap_nesting_size
;
674 shared_region
->sr_cpu_type
= cputype
;
675 shared_region
->sr_64bit
= is_64bit
;
676 shared_region
->sr_root_dir
= root_dir
;
678 queue_init(&shared_region
->sr_q
);
679 shared_region
->sr_mapping_in_progress
= FALSE
;
680 shared_region
->sr_persists
= FALSE
;
681 shared_region
->sr_timer_call
= NULL
;
682 shared_region
->sr_first_mapping
= (mach_vm_offset_t
) -1;
684 /* grab a reference for the caller */
685 shared_region
->sr_ref_count
= 1;
689 SHARED_REGION_TRACE_INFO(
690 ("shared_region: create(root=%p,cpu=%d,64bit=%d,"
691 "base=0x%llx,size=0x%llx) <- "
692 "%p mem=(%p,%p) map=%p pmap=%p\n",
693 root_dir
, cputype
, is_64bit
, (long long)base_address
,
694 (long long)size
, shared_region
,
695 mem_entry_port
, mem_entry
, sub_map
, sub_map
->pmap
));
697 SHARED_REGION_TRACE_INFO(
698 ("shared_region: create(root=%p,cpu=%d,64bit=%d,"
699 "base=0x%llx,size=0x%llx) <- NULL",
700 root_dir
, cputype
, is_64bit
, (long long)base_address
,
703 return shared_region
;
707 * Destroy a now-unused shared region.
708 * The shared region is no longer in the queue and can not be looked up.
711 vm_shared_region_destroy(
712 vm_shared_region_t shared_region
)
714 vm_named_entry_t mem_entry
;
717 SHARED_REGION_TRACE_INFO(
718 ("shared_region: -> destroy(%p) (root=%p,cpu=%d,64bit=%d)\n",
720 shared_region
->sr_root_dir
,
721 shared_region
->sr_cpu_type
,
722 shared_region
->sr_64bit
));
724 assert(shared_region
->sr_ref_count
== 0);
725 assert(!shared_region
->sr_persists
);
727 mem_entry
= (vm_named_entry_t
) shared_region
->sr_mem_entry
->ip_kobject
;
728 assert(mem_entry
->is_sub_map
);
729 assert(!mem_entry
->internal
);
730 assert(!mem_entry
->is_pager
);
731 map
= mem_entry
->backing
.map
;
734 * Clean up the pmap first. The virtual addresses that were
735 * entered in this possibly "nested" pmap may have different values
736 * than the VM map's min and max offsets, if the VM sub map was
737 * mapped at a non-zero offset in the processes' main VM maps, which
738 * is usually the case, so the clean-up we do in vm_map_destroy() would
742 pmap_remove(map
->pmap
,
743 shared_region
->sr_base_address
,
744 (shared_region
->sr_base_address
+
745 shared_region
->sr_size
));
749 * Release our (one and only) handle on the memory entry.
750 * This will generate a no-senders notification, which will be processed
751 * by ipc_kobject_notify(), which will release the one and only
752 * reference on the memory entry and cause it to be destroyed, along
753 * with the VM sub map and its pmap.
755 mach_memory_entry_port_release(shared_region
->sr_mem_entry
);
757 shared_region
->sr_mem_entry
= IPC_PORT_NULL
;
759 if (shared_region
->sr_timer_call
) {
760 thread_call_free(shared_region
->sr_timer_call
);
763 /* release the shared region structure... */
764 kfree(shared_region
, sizeof (*shared_region
));
765 SHARED_REGION_TRACE_DEBUG(
766 ("shared_region: destroy(%p) <-\n",
768 shared_region
= NULL
;
773 * Gets the address of the first (in time) mapping in the shared region.
776 vm_shared_region_start_address(
777 vm_shared_region_t shared_region
,
778 mach_vm_offset_t
*start_address
)
781 mach_vm_offset_t sr_base_address
;
782 mach_vm_offset_t sr_first_mapping
;
784 SHARED_REGION_TRACE_DEBUG(
785 ("shared_region: -> start_address(%p)\n",
787 assert(shared_region
->sr_ref_count
> 1);
789 vm_shared_region_lock();
792 * Wait if there's another thread establishing a mapping
793 * in this shared region right when we're looking at it.
794 * We want a consistent view of the map...
796 while (shared_region
->sr_mapping_in_progress
) {
797 /* wait for our turn... */
798 assert(shared_region
->sr_ref_count
> 1);
799 vm_shared_region_sleep(&shared_region
->sr_mapping_in_progress
,
802 assert(! shared_region
->sr_mapping_in_progress
);
803 assert(shared_region
->sr_ref_count
> 1);
805 sr_base_address
= shared_region
->sr_base_address
;
806 sr_first_mapping
= shared_region
->sr_first_mapping
;
808 if (sr_first_mapping
== (mach_vm_offset_t
) -1) {
809 /* shared region is empty */
810 kr
= KERN_INVALID_ADDRESS
;
813 *start_address
= sr_base_address
+ sr_first_mapping
;
816 vm_shared_region_unlock();
818 SHARED_REGION_TRACE_DEBUG(
819 ("shared_region: start_address(%p) <- 0x%llx\n",
820 shared_region
, (long long)shared_region
->sr_base_address
));
825 * Establish some mappings of a file in the shared region.
826 * This is used by "dyld" via the shared_region_map_np() system call
827 * to populate the shared region with the appropriate shared cache.
829 * One could also call it several times to incrementally load several
830 * libraries, as long as they do not overlap.
831 * It will return KERN_SUCCESS if the mappings were successfully established
832 * or if they were already established identically by another process.
835 vm_shared_region_map_file(
836 vm_shared_region_t shared_region
,
837 unsigned int mappings_count
,
838 struct shared_file_mapping_np
*mappings
,
839 memory_object_control_t file_control
,
840 memory_object_size_t file_size
,
844 vm_object_t file_object
;
845 ipc_port_t sr_handle
;
846 vm_named_entry_t sr_mem_entry
;
848 mach_vm_offset_t sr_base_address
;
850 mach_port_t map_port
;
851 mach_vm_offset_t target_address
;
853 vm_object_size_t obj_size
;
858 vm_shared_region_lock();
859 assert(shared_region
->sr_ref_count
> 1);
861 if (shared_region
->sr_root_dir
!= root_dir
) {
863 * This shared region doesn't match the current root
864 * directory of this process. Deny the mapping to
865 * avoid tainting the shared region with something that
866 * doesn't quite belong into it.
868 vm_shared_region_unlock();
869 kr
= KERN_PROTECTION_FAILURE
;
874 * Make sure we handle only one mapping at a time in a given
875 * shared region, to avoid race conditions. This should not
876 * happen frequently...
878 while (shared_region
->sr_mapping_in_progress
) {
879 /* wait for our turn... */
880 vm_shared_region_sleep(&shared_region
->sr_mapping_in_progress
,
883 assert(! shared_region
->sr_mapping_in_progress
);
884 assert(shared_region
->sr_ref_count
> 1);
885 /* let others know we're working in this shared region */
886 shared_region
->sr_mapping_in_progress
= TRUE
;
888 vm_shared_region_unlock();
890 /* no need to lock because this data is never modified... */
891 sr_handle
= shared_region
->sr_mem_entry
;
892 sr_mem_entry
= (vm_named_entry_t
) sr_handle
->ip_kobject
;
893 sr_map
= sr_mem_entry
->backing
.map
;
894 sr_base_address
= shared_region
->sr_base_address
;
896 SHARED_REGION_TRACE_DEBUG(
897 ("shared_region: -> map(%p,%d,%p,%p,0x%llx)\n",
898 shared_region
, mappings_count
, mappings
,
899 file_control
, file_size
));
901 /* get the VM object associated with the file to be mapped */
902 file_object
= memory_object_control_to_vm_object(file_control
);
904 /* establish the mappings */
905 for (i
= 0; i
< mappings_count
; i
++) {
906 SHARED_REGION_TRACE_INFO(
907 ("shared_region: mapping[%d]: "
908 "address:0x%016llx size:0x%016llx offset:0x%016llx "
909 "maxprot:0x%x prot:0x%x\n",
911 (long long)mappings
[i
].sfm_address
,
912 (long long)mappings
[i
].sfm_size
,
913 (long long)mappings
[i
].sfm_file_offset
,
914 mappings
[i
].sfm_max_prot
,
915 mappings
[i
].sfm_init_prot
));
917 if (mappings
[i
].sfm_init_prot
& VM_PROT_ZF
) {
918 /* zero-filled memory */
919 map_port
= MACH_PORT_NULL
;
921 /* file-backed memory */
922 map_port
= (ipc_port_t
) file_object
->pager
;
925 /* mapping's address is relative to the shared region base */
927 mappings
[i
].sfm_address
- sr_base_address
;
929 /* establish that mapping, OK if it's "already" there */
930 if (map_port
== MACH_PORT_NULL
) {
932 * We want to map some anonymous memory in a
934 * We have to create the VM object now, so that it
935 * can be mapped "copy-on-write".
937 obj_size
= vm_map_round_page(mappings
[i
].sfm_size
);
938 object
= vm_object_allocate(obj_size
);
939 if (object
== VM_OBJECT_NULL
) {
940 kr
= KERN_RESOURCE_SHORTAGE
;
945 vm_map_round_page(mappings
[i
].sfm_size
),
947 VM_FLAGS_FIXED
| VM_FLAGS_ALREADY
,
951 mappings
[i
].sfm_init_prot
& VM_PROT_ALL
,
952 mappings
[i
].sfm_max_prot
& VM_PROT_ALL
,
956 object
= VM_OBJECT_NULL
; /* no anonymous memory here */
957 kr
= vm_map_enter_mem_object(
960 vm_map_round_page(mappings
[i
].sfm_size
),
962 VM_FLAGS_FIXED
| VM_FLAGS_ALREADY
,
964 mappings
[i
].sfm_file_offset
,
966 mappings
[i
].sfm_init_prot
& VM_PROT_ALL
,
967 mappings
[i
].sfm_max_prot
& VM_PROT_ALL
,
971 if (kr
!= KERN_SUCCESS
) {
972 if (map_port
== MACH_PORT_NULL
) {
974 * Get rid of the VM object we just created
977 vm_object_deallocate(object
);
978 object
= VM_OBJECT_NULL
;
980 if (kr
== KERN_MEMORY_PRESENT
) {
982 * This exact mapping was already there:
985 SHARED_REGION_TRACE_INFO(
986 ("shared_region: mapping[%d]: "
987 "address:0x%016llx size:0x%016llx "
989 "maxprot:0x%x prot:0x%x "
990 "already mapped...\n",
992 (long long)mappings
[i
].sfm_address
,
993 (long long)mappings
[i
].sfm_size
,
994 (long long)mappings
[i
].sfm_file_offset
,
995 mappings
[i
].sfm_max_prot
,
996 mappings
[i
].sfm_init_prot
));
998 * We didn't establish this mapping ourselves;
999 * let's reset its size, so that we do not
1000 * attempt to undo it if an error occurs later.
1002 mappings
[i
].sfm_size
= 0;
1007 /* this mapping failed ! */
1008 SHARED_REGION_TRACE_ERROR(
1009 ("shared_region: mapping[%d]: "
1010 "address:0x%016llx size:0x%016llx "
1012 "maxprot:0x%x prot:0x%x failed 0x%x\n",
1014 (long long)mappings
[i
].sfm_address
,
1015 (long long)mappings
[i
].sfm_size
,
1016 (long long)mappings
[i
].sfm_file_offset
,
1017 mappings
[i
].sfm_max_prot
,
1018 mappings
[i
].sfm_init_prot
,
1022 * Undo the mappings we've established so far.
1024 for (j
= 0; j
< i
; j
++) {
1027 if (mappings
[j
].sfm_size
== 0) {
1029 * We didn't establish this
1030 * mapping, so nothing to undo.
1034 SHARED_REGION_TRACE_INFO(
1035 ("shared_region: mapping[%d]: "
1036 "address:0x%016llx "
1039 "maxprot:0x%x prot:0x%x: "
1042 (long long)mappings
[j
].sfm_address
,
1043 (long long)mappings
[j
].sfm_size
,
1044 (long long)mappings
[j
].sfm_file_offset
,
1045 mappings
[j
].sfm_max_prot
,
1046 mappings
[j
].sfm_init_prot
));
1047 kr2
= mach_vm_deallocate(
1049 (mappings
[j
].sfm_address
-
1051 mappings
[j
].sfm_size
);
1052 assert(kr2
== KERN_SUCCESS
);
1061 * Record the first (chronologically) mapping in
1062 * this shared region.
1063 * We're protected by "sr_mapping_in_progress" here,
1064 * so no need to lock "shared_region".
1066 if (shared_region
->sr_first_mapping
== (mach_vm_offset_t
) -1) {
1067 shared_region
->sr_first_mapping
= target_address
;
1071 vm_shared_region_lock();
1072 assert(shared_region
->sr_ref_count
> 1);
1073 assert(shared_region
->sr_mapping_in_progress
);
1074 /* we're done working on that shared region */
1075 shared_region
->sr_mapping_in_progress
= FALSE
;
1076 thread_wakeup((event_t
) &shared_region
->sr_mapping_in_progress
);
1077 vm_shared_region_unlock();
1080 SHARED_REGION_TRACE_DEBUG(
1081 ("shared_region: map(%p,%d,%p,%p,0x%llx) <- 0x%x \n",
1082 shared_region
, mappings_count
, mappings
,
1083 file_control
, file_size
, kr
));
1088 * Enter the appropriate shared region into "map" for "task".
1089 * This involves looking up the shared region (and possibly creating a new
1090 * one) for the desired environment, then mapping the VM sub map into the
1091 * task's VM "map", with the appropriate level of pmap-nesting.
1094 vm_shared_region_enter(
1095 struct _vm_map
*map
,
1101 vm_shared_region_t shared_region
;
1102 vm_map_offset_t sr_address
, sr_offset
, target_address
;
1103 vm_map_size_t sr_size
, mapping_size
;
1104 vm_map_offset_t sr_pmap_nesting_start
;
1105 vm_map_size_t sr_pmap_nesting_size
;
1106 ipc_port_t sr_handle
;
1109 is_64bit
= task_has_64BitAddr(task
);
1111 SHARED_REGION_TRACE_DEBUG(
1112 ("shared_region: -> "
1113 "enter(map=%p,task=%p,root=%p,cpu=%d,64bit=%d)\n",
1114 map
, task
, fsroot
, cpu
, is_64bit
));
1116 /* lookup (create if needed) the shared region for this environment */
1117 shared_region
= vm_shared_region_lookup(fsroot
, cpu
, is_64bit
);
1118 if (shared_region
== NULL
) {
1119 /* this should not happen ! */
1120 SHARED_REGION_TRACE_ERROR(
1121 ("shared_region: -> "
1122 "enter(map=%p,task=%p,root=%p,cpu=%d,64bit=%d): "
1123 "lookup failed !\n",
1124 map
, task
, fsroot
, cpu
, is_64bit
));
1125 //panic("shared_region_enter: lookup failed\n");
1126 return KERN_FAILURE
;
1129 /* let the task use that shared region */
1130 vm_shared_region_set(task
, shared_region
);
1133 /* no need to lock since this data is never modified */
1134 sr_address
= shared_region
->sr_base_address
;
1135 sr_size
= shared_region
->sr_size
;
1136 sr_handle
= shared_region
->sr_mem_entry
;
1137 sr_pmap_nesting_start
= shared_region
->sr_pmap_nesting_start
;
1138 sr_pmap_nesting_size
= shared_region
->sr_pmap_nesting_size
;
1141 * Start mapping the shared region's VM sub map into the task's VM map.
1145 if (sr_pmap_nesting_start
> sr_address
) {
1146 /* we need to map a range without pmap-nesting first */
1147 target_address
= sr_address
;
1148 mapping_size
= sr_pmap_nesting_start
- sr_address
;
1149 kr
= vm_map_enter_mem_object(
1161 if (kr
!= KERN_SUCCESS
) {
1162 SHARED_REGION_TRACE_ERROR(
1163 ("shared_region: enter(%p,%p,%p,%d,%d): "
1164 "vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1165 map
, task
, fsroot
, cpu
, is_64bit
,
1166 (long long)target_address
,
1167 (long long)mapping_size
, sr_handle
, kr
));
1170 SHARED_REGION_TRACE_DEBUG(
1171 ("shared_region: enter(%p,%p,%p,%d,%d): "
1172 "vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1173 map
, task
, fsroot
, cpu
, is_64bit
,
1174 (long long)target_address
, (long long)mapping_size
,
1176 sr_offset
+= mapping_size
;
1177 sr_size
-= mapping_size
;
1180 * We may need to map several pmap-nested portions, due to platform
1181 * specific restrictions on pmap nesting.
1182 * The pmap-nesting is triggered by the "VM_MEMORY_SHARED_PMAP" alias...
1185 sr_pmap_nesting_size
> 0;
1186 sr_offset
+= mapping_size
,
1187 sr_size
-= mapping_size
,
1188 sr_pmap_nesting_size
-= mapping_size
) {
1189 target_address
= sr_address
+ sr_offset
;
1190 mapping_size
= sr_pmap_nesting_size
;
1191 if (mapping_size
> pmap_nesting_size_max
) {
1192 mapping_size
= (vm_map_offset_t
) pmap_nesting_size_max
;
1194 kr
= vm_map_enter_mem_object(
1199 (VM_FLAGS_FIXED
| VM_MAKE_TAG(VM_MEMORY_SHARED_PMAP
)),
1206 if (kr
!= KERN_SUCCESS
) {
1207 SHARED_REGION_TRACE_ERROR(
1208 ("shared_region: enter(%p,%p,%p,%d,%d): "
1209 "vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1210 map
, task
, fsroot
, cpu
, is_64bit
,
1211 (long long)target_address
,
1212 (long long)mapping_size
, sr_handle
, kr
));
1215 SHARED_REGION_TRACE_DEBUG(
1216 ("shared_region: enter(%p,%p,%p,%d,%d): "
1217 "nested vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1218 map
, task
, fsroot
, cpu
, is_64bit
,
1219 (long long)target_address
, (long long)mapping_size
,
1223 /* and there's some left to be mapped without pmap-nesting */
1224 target_address
= sr_address
+ sr_offset
;
1225 mapping_size
= sr_size
;
1226 kr
= vm_map_enter_mem_object(
1238 if (kr
!= KERN_SUCCESS
) {
1239 SHARED_REGION_TRACE_ERROR(
1240 ("shared_region: enter(%p,%p,%p,%d,%d): "
1241 "vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1242 map
, task
, fsroot
, cpu
, is_64bit
,
1243 (long long)target_address
,
1244 (long long)mapping_size
, sr_handle
, kr
));
1247 SHARED_REGION_TRACE_DEBUG(
1248 ("shared_region: enter(%p,%p,%p,%d,%d): "
1249 "vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1250 map
, task
, fsroot
, cpu
, is_64bit
,
1251 (long long)target_address
, (long long)mapping_size
,
1253 sr_offset
+= mapping_size
;
1254 sr_size
-= mapping_size
;
1256 assert(sr_size
== 0);
1259 SHARED_REGION_TRACE_DEBUG(
1260 ("shared_region: enter(%p,%p,%p,%d,%d) <- 0x%x\n",
1261 map
, task
, fsroot
, cpu
, is_64bit
, kr
));
1265 /******************************************************************************/
1266 /* Comm page support */
1267 /******************************************************************************/
1269 ipc_port_t commpage32_handle
= IPC_PORT_NULL
;
1270 ipc_port_t commpage64_handle
= IPC_PORT_NULL
;
1271 vm_named_entry_t commpage32_entry
= NULL
;
1272 vm_named_entry_t commpage64_entry
= NULL
;
1273 vm_map_t commpage32_map
= VM_MAP_NULL
;
1274 vm_map_t commpage64_map
= VM_MAP_NULL
;
1277 * Create a memory entry, VM submap and pmap for one commpage.
1281 ipc_port_t
*handlep
,
1285 vm_named_entry_t mem_entry
;
1288 SHARED_REGION_TRACE_DEBUG(
1289 ("commpage: -> _init(0x%llx)\n",
1292 kr
= mach_memory_entry_allocate(&mem_entry
,
1294 if (kr
!= KERN_SUCCESS
) {
1295 panic("_vm_commpage_init: could not allocate mem_entry");
1297 new_map
= vm_map_create(pmap_create(0, FALSE
), 0, size
, TRUE
);
1298 if (new_map
== VM_MAP_NULL
) {
1299 panic("_vm_commpage_init: could not allocate VM map");
1301 mem_entry
->backing
.map
= new_map
;
1302 mem_entry
->internal
= TRUE
;
1303 mem_entry
->is_sub_map
= TRUE
;
1304 mem_entry
->offset
= 0;
1305 mem_entry
->protection
= VM_PROT_ALL
;
1306 mem_entry
->size
= size
;
1308 SHARED_REGION_TRACE_DEBUG(
1309 ("commpage: _init(0x%llx) <- %p\n",
1310 (long long)size
, *handlep
));
1314 * Initialize the comm pages at boot time.
1317 vm_commpage_init(void)
1319 SHARED_REGION_TRACE_DEBUG(
1320 ("commpage: -> init()\n"));
1322 /* create the 32-bit comm page */
1323 _vm_commpage_init(&commpage32_handle
, _COMM_PAGE32_AREA_LENGTH
);
1324 commpage32_entry
= (vm_named_entry_t
) commpage32_handle
->ip_kobject
;
1325 commpage32_map
= commpage32_entry
->backing
.map
;
1327 /* XXX if (cpu_is_64bit_capable()) ? */
1328 /* create the 64-bit comm page */
1329 _vm_commpage_init(&commpage64_handle
, _COMM_PAGE64_AREA_LENGTH
);
1330 commpage64_entry
= (vm_named_entry_t
) commpage64_handle
->ip_kobject
;
1331 commpage64_map
= commpage64_entry
->backing
.map
;
1333 /* populate them according to this specific platform */
1334 commpage_populate();
1335 __commpage_setup
= 1;
1336 #if defined(__i386__) || defined(__x86_64__)
1337 if (__system_power_source
== 0) {
1338 post_sys_powersource_internal(0, 1);
1340 #endif /* __i386__ || __x86_64__ */
1342 SHARED_REGION_TRACE_DEBUG(
1343 ("commpage: init() <-\n"));
1347 * Enter the appropriate comm page into the task's address space.
1348 * This is called at exec() time via vm_map_exec().
1355 ipc_port_t commpage_handle
;
1356 vm_map_offset_t commpage_address
, objc_address
;
1357 vm_map_size_t commpage_size
, objc_size
;
1361 SHARED_REGION_TRACE_DEBUG(
1362 ("commpage: -> enter(%p,%p)\n",
1365 /* the comm page is likely to be beyond the actual end of the VM map */
1366 vm_flags
= VM_FLAGS_FIXED
| VM_FLAGS_BEYOND_MAX
;
1368 /* select the appropriate comm page for this task */
1369 assert(! (task_has_64BitAddr(task
) ^ vm_map_is_64bit(map
)));
1370 if (task_has_64BitAddr(task
)) {
1373 * PPC51: ppc64 is limited to 51-bit addresses.
1374 * Memory above that limit is handled specially at the
1375 * pmap level, so do not interfere.
1377 vm_flags
|= VM_FLAGS_NO_PMAP_CHECK
;
1378 #endif /* __ppc__ */
1379 commpage_handle
= commpage64_handle
;
1380 commpage_address
= (vm_map_offset_t
) _COMM_PAGE64_BASE_ADDRESS
;
1381 commpage_size
= _COMM_PAGE64_AREA_LENGTH
;
1382 objc_size
= _COMM_PAGE64_OBJC_SIZE
;
1383 objc_address
= _COMM_PAGE64_OBJC_BASE
;
1385 commpage_handle
= commpage32_handle
;
1387 (vm_map_offset_t
)(unsigned) _COMM_PAGE32_BASE_ADDRESS
;
1388 commpage_size
= _COMM_PAGE32_AREA_LENGTH
;
1389 objc_size
= _COMM_PAGE32_OBJC_SIZE
;
1390 objc_address
= _COMM_PAGE32_OBJC_BASE
;
1393 if ((commpage_address
& (pmap_nesting_size_min
- 1)) == 0 &&
1394 (commpage_size
& (pmap_nesting_size_min
- 1)) == 0) {
1395 /* the commpage is properly aligned or sized for pmap-nesting */
1396 vm_flags
|= VM_MAKE_TAG(VM_MEMORY_SHARED_PMAP
);
1399 /* map the comm page in the task's address space */
1400 assert(commpage_handle
!= IPC_PORT_NULL
);
1401 kr
= vm_map_enter_mem_object(
1410 VM_PROT_READ
|VM_PROT_EXECUTE
,
1411 VM_PROT_READ
|VM_PROT_EXECUTE
,
1413 if (kr
!= KERN_SUCCESS
) {
1414 SHARED_REGION_TRACE_ERROR(
1415 ("commpage: enter(%p,0x%llx,0x%llx) "
1416 "commpage %p mapping failed 0x%x\n",
1417 map
, (long long)commpage_address
,
1418 (long long)commpage_size
, commpage_handle
, kr
));
1422 * Since we're here, we also pre-allocate some virtual space for the
1423 * Objective-C run-time, if needed...
1425 if (objc_size
!= 0) {
1426 kr
= vm_map_enter_mem_object(
1431 VM_FLAGS_FIXED
| VM_FLAGS_BEYOND_MAX
,
1437 VM_INHERIT_DEFAULT
);
1438 if (kr
!= KERN_SUCCESS
) {
1439 SHARED_REGION_TRACE_ERROR(
1440 ("commpage: enter(%p,0x%llx,0x%llx) "
1441 "objc mapping failed 0x%x\n",
1442 map
, (long long)objc_address
,
1443 (long long)objc_size
, kr
));
1447 SHARED_REGION_TRACE_DEBUG(
1448 ("commpage: enter(%p,%p) <- 0x%x\n",
1455 * This is called from powermanagement code to let kernel know the current source of power.
1456 * 0 if it is external source (connected to power )
1457 * 1 if it is internal power source ie battery
1460 #if defined(__i386__) || defined(__x86_64__)
1461 post_sys_powersource(int i
)
1463 post_sys_powersource(__unused
int i
)
1466 #if defined(__i386__) || defined(__x86_64__)
1467 post_sys_powersource_internal(i
, 0);
1468 #endif /* __i386__ || __x86_64__ */
1472 #if defined(__i386__) || defined(__x86_64__)
1474 post_sys_powersource_internal(int i
, int internal
)
1477 __system_power_source
= i
;
1479 if (__commpage_setup
!= 0) {
1480 if (__system_power_source
!= 0)
1481 commpage_set_spin_count(0);
1483 commpage_set_spin_count(MP_SPIN_TRIES
);
1486 #endif /* __i386__ || __x86_64__ */