1/*
2 * Copyright (c) 2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * Shared region (... and comm page)
26 *
27 * This file handles the VM shared region and comm page.
28 *
29 */
30/*
31 * SHARED REGIONS
32 * --------------
33 *
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).
37 *
38 * The point of a shared region is to reduce the setup overhead when exec'ing
39 * a new process.
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
45 * region.
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.
51 *
52 *
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.
58 *
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.
63 *
64 * The shared region is inherited on fork() and the child simply takes an
65 * extra reference on its parent's shared region.
66 *
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.
69 *
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.
74 */
75/*
76 * COMM PAGE
77 *
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 !
83 *
84 * The comm pages are created and populated at boot time.
85 *
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().
89 *
90 * The comm page is shared between the kernel and all applications of
91 * a given platform.  Only the kernel can modify it.
92 *
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.
97 */
98
99#include <debug.h>
100
101#include <kern/ipc_tt.h>
102#include <kern/kalloc.h>
103
104#include <mach/mach_vm.h>
105
106#include <vm/vm_map.h>
107#include <vm/vm_shared_region.h>
108
109#include <vm/vm_protos.h>
110
111#include <machine/commpage.h>
112#include <machine/cpu_capabilities.h>
113
114/* "dyld" uses this to figure out what the kernel supports */
115int shared_region_version = 3;
116
117/* should local (non-chroot) shared regions persist when no task uses them ? */
118int shared_region_persistence = 1;	/* yes by default */
119
120/* trace level, output is sent to the system log file */
121int shared_region_trace_level = SHARED_REGION_TRACE_ERROR_LVL;
122
123/* this lock protects all the shared region data structures */
124lck_grp_t *vm_shared_region_lck_grp;
125lck_mtx_t vm_shared_region_lock;
126
127#define vm_shared_region_lock() lck_mtx_lock(&vm_shared_region_lock)
128#define vm_shared_region_unlock() lck_mtx_unlock(&vm_shared_region_lock)
129#define vm_shared_region_sleep(event, interruptible)			\
130	lck_mtx_sleep(&vm_shared_region_lock,				\
131		      LCK_SLEEP_DEFAULT,				\
132		      (event_t) (event),				\
133		      (interruptible))
134
135/* the list of currently available shared regions (one per environment) */
136queue_head_t	vm_shared_region_queue;
137
138static void vm_shared_region_reference_locked(vm_shared_region_t shared_region);
139static vm_shared_region_t vm_shared_region_create(
140	void			*root_dir,
141	cpu_type_t		cputype,
142	boolean_t		is_64bit);
143static void vm_shared_region_destroy(vm_shared_region_t shared_region);
144
145/*
146 * Initialize the module...
147 */
148void
149vm_shared_region_init(void)
150{
151	SHARED_REGION_TRACE_DEBUG(
152		("shared_region: -> init\n"));
153
154	vm_shared_region_lck_grp = lck_grp_alloc_init("vm shared region",
155						      LCK_GRP_ATTR_NULL);
156	lck_mtx_init(&vm_shared_region_lock,
157		     vm_shared_region_lck_grp,
158		     LCK_ATTR_NULL);
159
160	queue_init(&vm_shared_region_queue);
161
162	SHARED_REGION_TRACE_DEBUG(
163		("shared_region: <- init\n"));
164}
165
166/*
167 * Retrieve a task's shared region and grab an extra reference to
168 * make sure it doesn't disappear while the caller is using it.
169 * The caller is responsible for consuming that extra reference if
170 * necessary.
171 */
172vm_shared_region_t
173vm_shared_region_get(
174	task_t		task)
175{
176	vm_shared_region_t	shared_region;
177
178	SHARED_REGION_TRACE_DEBUG(
179		("shared_region: -> get(%p)\n",
180		 task));
181
182	task_lock(task);
183	vm_shared_region_lock();
184	shared_region = task->shared_region;
185	if (shared_region) {
186		assert(shared_region->sr_ref_count > 0);
187		vm_shared_region_reference_locked(shared_region);
188	}
189	vm_shared_region_unlock();
190	task_unlock(task);
191
192	SHARED_REGION_TRACE_DEBUG(
193		("shared_region: get(%p) <- %p\n",
194		 task, shared_region));
195
196	return shared_region;
197}
198
199/*
200 * Get the base address of the shared region.
201 * That's the address at which it needs to be mapped in the process's address
202 * space.
203 * No need to lock since this data is set when the shared region is
204 * created and is never modified after that.  The caller must hold an extra
205 * reference on the shared region to prevent it from being destroyed.
206 */
207mach_vm_offset_t
208vm_shared_region_base_address(
209	vm_shared_region_t	shared_region)
210{
211	SHARED_REGION_TRACE_DEBUG(
212		("shared_region: -> base_address(%p)\n",
213		 shared_region));
214	assert(shared_region->sr_ref_count > 1);
215	SHARED_REGION_TRACE_DEBUG(
216		("shared_region: base_address(%p) <- 0x%llx\n",
217		 shared_region, (long long)shared_region->sr_base_address));
218	return shared_region->sr_base_address;
219}
220
221/*
222 * Get the size of the shared region.
223 * That's the size that needs to be mapped in the process's address
224 * space.
225 * No need to lock since this data is set when the shared region is
226 * created and is never modified after that.  The caller must hold an extra
227 * reference on the shared region to prevent it from being destroyed.
228 */
229mach_vm_size_t
230vm_shared_region_size(
231	vm_shared_region_t	shared_region)
232{
233	SHARED_REGION_TRACE_DEBUG(
234		("shared_region: -> size(%p)\n",
235		 shared_region));
236	assert(shared_region->sr_ref_count > 1);
237	SHARED_REGION_TRACE_DEBUG(
238		("shared_region: size(%p) <- 0x%llx\n",
239		 shared_region, (long long)shared_region->sr_size));
240	return shared_region->sr_size;
241}
242
243/*
244 * Get the memory entry of the shared region.
245 * That's the "memory object" that needs to be mapped in the process's address
246 * space.
247 * No need to lock since this data is set when the shared region is
248 * created and is never modified after that.  The caller must hold an extra
249 * reference on the shared region to prevent it from being destroyed.
250 */
251ipc_port_t
252vm_shared_region_mem_entry(
253	vm_shared_region_t	shared_region)
254{
255	SHARED_REGION_TRACE_DEBUG(
256		("shared_region: -> mem_entry(%p)\n",
257		 shared_region));
258	assert(shared_region->sr_ref_count > 1);
259	SHARED_REGION_TRACE_DEBUG(
260		("shared_region: mem_entry(%p) <- %p\n",
261		 shared_region, shared_region->sr_mem_entry));
262	return shared_region->sr_mem_entry;
263}
264
265/*
266 * Set the shared region the process should use.
267 * A NULL new shared region means that we just want to release the old
268 * shared region.
269 * The caller should already have an extra reference on the new shared region
270 * (if any).  We release a reference on the old shared region (if any).
271 */
272void
273vm_shared_region_set(
274	task_t			task,
275	vm_shared_region_t	new_shared_region)
276{
277	vm_shared_region_t	old_shared_region;
278
279	SHARED_REGION_TRACE_DEBUG(
280		("shared_region: -> set(%p, %p)\n",
281		 task, new_shared_region));
282
283	task_lock(task);
284	vm_shared_region_lock();
285
286	old_shared_region = task->shared_region;
287	if (new_shared_region) {
288		assert(new_shared_region->sr_ref_count > 0);
289	}
290
291	task->shared_region = new_shared_region;
292
293	vm_shared_region_unlock();
294	task_unlock(task);
295
296	if (old_shared_region) {
297		assert(old_shared_region->sr_ref_count > 0);
298		vm_shared_region_deallocate(old_shared_region);
299	}
300
301	SHARED_REGION_TRACE_DEBUG(
302		("shared_region: set(%p) <- old=%p new=%p\n",
303		 task, old_shared_region, new_shared_region));
304}
305
306/*
307 * Lookup up the shared region for the desired environment.
308 * If none is found, create a new (empty) one.
309 * Grab an extra reference on the returned shared region, to make sure
310 * it doesn't get destroyed before the caller is done with it.  The caller
311 * is responsible for consuming that extra reference if necessary.
312 */
313vm_shared_region_t
314vm_shared_region_lookup(
315	void		*root_dir,
316	cpu_type_t	cputype,
317	boolean_t	is_64bit)
318{
319	vm_shared_region_t	shared_region;
320	vm_shared_region_t	new_shared_region;
321
322	SHARED_REGION_TRACE_DEBUG(
323		("shared_region: -> lookup(root=%p,cpu=%d,64bit=%d)\n",
324		 root_dir, cputype, is_64bit));
325
326	shared_region = NULL;
327	new_shared_region = NULL;
328
329	vm_shared_region_lock();
330	for (;;) {
331		queue_iterate(&vm_shared_region_queue,
332			      shared_region,
333			      vm_shared_region_t,
334			      sr_q) {
335			assert(shared_region->sr_ref_count > 0);
336			if (shared_region->sr_cpu_type == cputype &&
337			    shared_region->sr_root_dir == root_dir &&
338			    shared_region->sr_64bit == is_64bit) {
339				/* found a match ! */
340				vm_shared_region_reference_locked(shared_region);
341				goto done;
342			}
343		}
344		if (new_shared_region == NULL) {
345			/* no match: create a new one */
346			vm_shared_region_unlock();
347			new_shared_region = vm_shared_region_create(root_dir,
348								    cputype,
349								    is_64bit);
350			/* do the lookup again, in case we lost a race */
351			vm_shared_region_lock();
352			continue;
353		}
354		/* still no match: use our new one */
355		shared_region = new_shared_region;
356		new_shared_region = NULL;
357		queue_enter(&vm_shared_region_queue,
358			    shared_region,
359			    vm_shared_region_t,
360			    sr_q);
361		break;
362	}
363
364done:
365	vm_shared_region_unlock();
366
367	if (new_shared_region) {
368		/*
369		 * We lost a race with someone else to create a new shared
370		 * region for that environment.  Get rid of our unused one.
371		 */
372		assert(new_shared_region->sr_ref_count == 1);
373		new_shared_region->sr_ref_count--;
374		vm_shared_region_destroy(new_shared_region);
375		new_shared_region = NULL;
376	}
377
378	SHARED_REGION_TRACE_DEBUG(
379		("shared_region: lookup(root=%p,cpu=%d,64bit=%d) <- %p\n",
380		 root_dir, cputype, is_64bit, shared_region));
381
382	assert(shared_region->sr_ref_count > 0);
383	return shared_region;
384}
385
386/*
387 * Take an extra reference on a shared region.
388 * The vm_shared_region_lock should already be held by the caller.
389 */
390static void
391vm_shared_region_reference_locked(
392	vm_shared_region_t	shared_region)
393{
394#if DEBUG
395	lck_mtx_assert(&vm_shared_region_lock, LCK_MTX_ASSERT_OWNED);
396#endif
397
398	SHARED_REGION_TRACE_DEBUG(
399		("shared_region: -> reference_locked(%p)\n",
400		 shared_region));
401	assert(shared_region->sr_ref_count > 0);
402	shared_region->sr_ref_count++;
403	SHARED_REGION_TRACE_DEBUG(
404		("shared_region: reference_locked(%p) <- %d\n",
405		 shared_region, shared_region->sr_ref_count));
406}
407
408/*
409 * Release a reference on the shared region.
410 * Destroy it if there are no references left.
411 */
412void
413vm_shared_region_deallocate(
414	vm_shared_region_t	shared_region)
415{
416	SHARED_REGION_TRACE_DEBUG(
417		("shared_region: -> deallocate(%p)\n",
418		 shared_region));
419
420	vm_shared_region_lock();
421
422	assert(shared_region->sr_ref_count > 0);
423
424	if (shared_region->sr_root_dir == NULL) {
425		/*
426		 * Local (i.e. based on the boot volume) shared regions
427		 * can persist or not based on the "shared_region_persistence"
428		 * sysctl.
429		 * Make sure that this one complies.
430		 */
431		if (shared_region_persistence &&
432		    !shared_region->sr_persists) {
433			/* make this one persistent */
434			shared_region->sr_ref_count++;
435			shared_region->sr_persists = TRUE;
436		} else if (!shared_region_persistence &&
437			   shared_region->sr_persists) {
438			/* make this one no longer persistent */
439			assert(shared_region->sr_ref_count > 1);
440			shared_region->sr_ref_count--;
441			shared_region->sr_persists = FALSE;
442		}
443	}
444
445	assert(shared_region->sr_ref_count > 0);
446	shared_region->sr_ref_count--;
447	SHARED_REGION_TRACE_DEBUG(
448		("shared_region: deallocate(%p): ref now %d\n",
449		 shared_region, shared_region->sr_ref_count));
450
451	if (shared_region->sr_ref_count == 0) {
452		assert(! shared_region->sr_mapping_in_progress);
453		/* remove it from the queue first, so no one can find it... */
454		queue_remove(&vm_shared_region_queue,
455			     shared_region,
456			     vm_shared_region_t,
457			     sr_q);
458		vm_shared_region_unlock();
459		/* ... and destroy it */
460		vm_shared_region_destroy(shared_region);
461		shared_region = NULL;
462	} else {
463		vm_shared_region_unlock();
464	}
465
466	SHARED_REGION_TRACE_DEBUG(
467		("shared_region: deallocate(%p) <-\n",
468		 shared_region));
469}
470
471/*
472 * Create a new (empty) shared region for a new environment.
473 */
474static vm_shared_region_t
475vm_shared_region_create(
476	void			*root_dir,
477	cpu_type_t		cputype,
478	boolean_t		is_64bit)
479{
480	kern_return_t		kr;
481	vm_named_entry_t	mem_entry;
482	ipc_port_t		mem_entry_port;
483	vm_shared_region_t	shared_region;
484	vm_map_t		sub_map;
485	mach_vm_offset_t	base_address, pmap_nesting_start;
486	mach_vm_size_t		size, pmap_nesting_size;
487
488	SHARED_REGION_TRACE_DEBUG(
489		("shared_region: -> create(root=%p,cpu=%d,64bit=%d)\n",
490		 root_dir, cputype, is_64bit));
491
492	base_address = 0;
493	size = 0;
494	mem_entry = NULL;
495	mem_entry_port = IPC_PORT_NULL;
496	sub_map = VM_MAP_NULL;
497
498	/* create a new shared region structure... */
499	shared_region = kalloc(sizeof (*shared_region));
500	if (shared_region == NULL) {
501		SHARED_REGION_TRACE_ERROR(
502			("shared_region: create: couldn't allocate\n"));
503		goto done;
504	}
505
506	/* figure out the correct settings for the desired environment */
507	if (is_64bit) {
508		switch (cputype) {
509		case CPU_TYPE_I386:
510			base_address = SHARED_REGION_BASE_X86_64;
511			size = SHARED_REGION_SIZE_X86_64;
512			pmap_nesting_start = SHARED_REGION_NESTING_BASE_X86_64;
513			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_X86_64;
514			break;
515		case CPU_TYPE_POWERPC:
516			base_address = SHARED_REGION_BASE_PPC64;
517			size = SHARED_REGION_SIZE_PPC64;
518			pmap_nesting_start = SHARED_REGION_NESTING_BASE_PPC64;
519			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_PPC64;
520			break;
521		default:
522			SHARED_REGION_TRACE_ERROR(
523				("shared_region: create: unknown cpu type %d\n",
524				 cputype));
525			kfree(shared_region, sizeof (*shared_region));
526			shared_region = NULL;
527			goto done;
528		}
529	} else {
530		switch (cputype) {
531		case CPU_TYPE_I386:
532			base_address = SHARED_REGION_BASE_I386;
533			size = SHARED_REGION_SIZE_I386;
534			pmap_nesting_start = SHARED_REGION_NESTING_BASE_I386;
535			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_I386;
536			break;
537		case CPU_TYPE_POWERPC:
538			base_address = SHARED_REGION_BASE_PPC;
539			size = SHARED_REGION_SIZE_PPC;
540			pmap_nesting_start = SHARED_REGION_NESTING_BASE_PPC;
541			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_PPC;
542			break;
543#ifdef CPU_TYPE_ARM
544		case CPU_TYPE_ARM:
545			base_address = SHARED_REGION_BASE_ARM;
546			size = SHARED_REGION_SIZE_ARM;
547			pmap_nesting_start = SHARED_REGION_NESTING_BASE_ARM;
548			pmap_nesting_size = SHARED_REGION_NESTING_SIZE_ARM;
549			break;
550#endif /* CPU_TYPE_ARM */
551		default:
552			SHARED_REGION_TRACE_ERROR(
553				("shared_region: create: unknown cpu type %d\n",
554				 cputype));
555			kfree(shared_region, sizeof (*shared_region));
556			shared_region = NULL;
557			goto done;
558
559		}
560	}
561
562	/* create a memory entry structure and a Mach port handle */
563	kr = mach_memory_entry_allocate(&mem_entry,
564					&mem_entry_port);
565	if (kr != KERN_SUCCESS) {
566		kfree(shared_region, sizeof (*shared_region));
567		shared_region = NULL;
568		SHARED_REGION_TRACE_ERROR(
569			("shared_region: create: "
570			 "couldn't allocate mem_entry\n"));
571		goto done;
572	}
573
574	/* create a VM sub map and its pmap */
575	sub_map = vm_map_create(pmap_create(0, is_64bit),
576				0, size,
577				TRUE);
578	if (sub_map == VM_MAP_NULL) {
579		ipc_port_release_send(mem_entry_port);
580		kfree(shared_region, sizeof (*shared_region));
581		shared_region = NULL;
582		SHARED_REGION_TRACE_ERROR(
583			("shared_region: create: "
584			 "couldn't allocate map\n"));
585		goto done;
586	}
587
588	/* make the memory entry point to the VM sub map */
589	mem_entry->is_sub_map = TRUE;
590	mem_entry->backing.map = sub_map;
591	mem_entry->size = size;
592	mem_entry->protection = VM_PROT_ALL;
593
594	/* make the shared region point at the memory entry */
595	shared_region->sr_mem_entry = mem_entry_port;
596
597	/* fill in the shared region's environment and settings */
598	shared_region->sr_base_address = base_address;
599	shared_region->sr_size = size;
600	shared_region->sr_pmap_nesting_start = pmap_nesting_start;
601	shared_region->sr_pmap_nesting_size = pmap_nesting_size;
602	shared_region->sr_cpu_type = cputype;
603	shared_region->sr_64bit = is_64bit;
604	shared_region->sr_root_dir = root_dir;
605
606	queue_init(&shared_region->sr_q);
607	shared_region->sr_mapping_in_progress = FALSE;
608	shared_region->sr_persists = FALSE;
609	shared_region->sr_first_mapping = (mach_vm_offset_t) -1;
610
611	/* grab a reference for the caller */
612	shared_region->sr_ref_count = 1;
613
614done:
615	if (shared_region) {
616		SHARED_REGION_TRACE_INFO(
617			("shared_region: create(root=%p,cpu=%d,64bit=%d,"
618			 "base=0x%llx,size=0x%llx) <- "
619			 "%p mem=(%p,%p) map=%p pmap=%p\n",
620			 root_dir, cputype, is_64bit, (long long)base_address,
621			 (long long)size, shared_region,
622			 mem_entry_port, mem_entry, sub_map, sub_map->pmap));
623	} else {
624		SHARED_REGION_TRACE_INFO(
625			("shared_region: create(root=%p,cpu=%d,64bit=%d,"
626			 "base=0x%llx,size=0x%llx) <- NULL",
627			 root_dir, cputype, is_64bit, (long long)base_address,
628			 (long long)size));
629	}
630	return shared_region;
631}
632
633/*
634 * Destroy a now-unused shared region.
635 * The shared region is no longer in the queue and can not be looked up.
636 */
637static void
638vm_shared_region_destroy(
639	vm_shared_region_t	shared_region)
640{
641	vm_named_entry_t	mem_entry;
642	vm_map_t		map;
643
644	SHARED_REGION_TRACE_INFO(
645		("shared_region: -> destroy(%p) (root=%p,cpu=%d,64bit=%d)\n",
646		 shared_region,
647		 shared_region->sr_root_dir,
648		 shared_region->sr_cpu_type,
649		 shared_region->sr_64bit));
650
651	assert(shared_region->sr_ref_count == 0);
652	assert(!shared_region->sr_persists);
653
654	mem_entry = (vm_named_entry_t) shared_region->sr_mem_entry->ip_kobject;
655	assert(mem_entry->is_sub_map);
656	assert(!mem_entry->internal);
657	assert(!mem_entry->is_pager);
658	map = mem_entry->backing.map;
659
660	/*
661	 * Clean up the pmap first.  The virtual addresses that were
662	 * entered in this possibly "nested" pmap may have different values
663	 * than the VM map's min and max offsets, if the VM sub map was
664	 * mapped at a non-zero offset in the processes' main VM maps, which
665	 * is usually the case, so the clean-up we do in vm_map_destroy() would
666	 * not be enough.
667	 */
668	if (map->pmap) {
669		pmap_remove(map->pmap,
670			    shared_region->sr_base_address,
671			    (shared_region->sr_base_address +
672			     shared_region->sr_size));
673	}
674
675	/*
676	 * Release our (one and only) handle on the memory entry.
677	 * This will generate a no-senders notification, which will be processed
678	 * by ipc_kobject_notify(), which will release the one and only
679	 * reference on the memory entry and cause it to be destroyed, along
680	 * with the VM sub map and its pmap.
681	 */
682	mach_memory_entry_port_release(shared_region->sr_mem_entry);
683	mem_entry = NULL;
684	shared_region->sr_mem_entry = IPC_PORT_NULL;
685
686	/* release the shared region structure... */
687	kfree(shared_region, sizeof (*shared_region));
688	SHARED_REGION_TRACE_DEBUG(
689		("shared_region: destroy(%p) <-\n",
690		 shared_region));
691	shared_region = NULL;
692
693}
694
695/*
696 * Gets the address of the first (in time) mapping in the shared region.
697 */
698kern_return_t
699vm_shared_region_start_address(
700	vm_shared_region_t	shared_region,
701	mach_vm_offset_t	*start_address)
702{
703	kern_return_t		kr;
704	mach_vm_offset_t	sr_base_address;
705	mach_vm_offset_t	sr_first_mapping;
706
707	SHARED_REGION_TRACE_DEBUG(
708		("shared_region: -> start_address(%p)\n",
709		 shared_region));
710	assert(shared_region->sr_ref_count > 1);
711
712	vm_shared_region_lock();
713
714	/*
715	 * Wait if there's another thread establishing a mapping
716	 * in this shared region right when we're looking at it.
717	 * We want a consistent view of the map...
718	 */
719	while (shared_region->sr_mapping_in_progress) {
720		/* wait for our turn... */
721		assert(shared_region->sr_ref_count > 1);
722		vm_shared_region_sleep(&shared_region->sr_mapping_in_progress,
723				       THREAD_UNINT);
724	}
725	assert(! shared_region->sr_mapping_in_progress);
726	assert(shared_region->sr_ref_count > 1);
727
728	sr_base_address = shared_region->sr_base_address;
729	sr_first_mapping = shared_region->sr_first_mapping;
730
731	if (sr_first_mapping == (mach_vm_offset_t) -1) {
732		/* shared region is empty */
733		kr = KERN_INVALID_ADDRESS;
734	} else {
735		kr = KERN_SUCCESS;
736		*start_address = sr_base_address + sr_first_mapping;
737	}
738
739	vm_shared_region_unlock();
740
741	SHARED_REGION_TRACE_DEBUG(
742		("shared_region: start_address(%p) <- 0x%llx\n",
743		 shared_region, (long long)shared_region->sr_base_address));
744
745	return kr;
746}
747/*
748 * Establish some mappings of a file in the shared region.
749 * This is used by "dyld" via the shared_region_map_np() system call
750 * to populate the shared region with the appropriate shared cache.
751 *
752 * One could also call it several times to incrementally load several
753 * libraries, as long as they do not overlap.
754 * It will return KERN_SUCCESS if the mappings were successfully established
755 * or if they were already established identically by another process.
756 */
757kern_return_t
758vm_shared_region_map_file(
759	vm_shared_region_t		shared_region,
760	unsigned int			mappings_count,
761	struct shared_file_mapping_np	*mappings,
762	memory_object_control_t		file_control,
763	memory_object_size_t		file_size,
764	void				*root_dir)
765{
766	kern_return_t		kr;
767	vm_object_t		file_object;
768	ipc_port_t		sr_handle;
769	vm_named_entry_t	sr_mem_entry;
770	vm_map_t		sr_map;
771	mach_vm_offset_t	sr_base_address;
772	unsigned int		i;
773	mach_port_t		map_port;
774	mach_vm_offset_t	target_address;
775	vm_object_t		object;
776	vm_object_size_t	obj_size;
777
778
779	kr = KERN_SUCCESS;
780
781	vm_shared_region_lock();
782	assert(shared_region->sr_ref_count > 1);
783
784	if (shared_region->sr_root_dir != root_dir) {
785		/*
786		 * This shared region doesn't match the current root
787		 * directory of this process.  Deny the mapping to
788		 * avoid tainting the shared region with something that
789		 * doesn't quite belong into it.
790		 */
791		vm_shared_region_unlock();
792		kr = KERN_PROTECTION_FAILURE;
793		goto done;
794	}
795
796	/*
797	 * Make sure we handle only one mapping at a time in a given
798	 * shared region, to avoid race conditions.  This should not
799	 * happen frequently...
800	 */
801	while (shared_region->sr_mapping_in_progress) {
802		/* wait for our turn... */
803		vm_shared_region_sleep(&shared_region->sr_mapping_in_progress,
804				       THREAD_UNINT);
805	}
806	assert(! shared_region->sr_mapping_in_progress);
807	assert(shared_region->sr_ref_count > 1);
808	/* let others know we're working in this shared region */
809	shared_region->sr_mapping_in_progress = TRUE;
810
811	vm_shared_region_unlock();
812
813	/* no need to lock because this data is never modified... */
814	sr_handle = shared_region->sr_mem_entry;
815	sr_mem_entry = (vm_named_entry_t) sr_handle->ip_kobject;
816	sr_map = sr_mem_entry->backing.map;
817	sr_base_address = shared_region->sr_base_address;
818
819	SHARED_REGION_TRACE_DEBUG(
820		("shared_region: -> map(%p,%d,%p,%p,0x%llx)\n",
821		 shared_region, mappings_count, mappings,
822		 file_control, file_size));
823
824	/* get the VM object associated with the file to be mapped */
825	file_object = memory_object_control_to_vm_object(file_control);
826
827	/* establish the mappings */
828	for (i = 0; i < mappings_count; i++) {
829		SHARED_REGION_TRACE_INFO(
830			("shared_region: mapping[%d]: "
831			 "address:0x%016llx size:0x%016llx offset:0x%016llx "
832			 "maxprot:0x%x prot:0x%x\n",
833			 i,
834			 (long long)mappings[i].sfm_address,
835			 (long long)mappings[i].sfm_size,
836			 (long long)mappings[i].sfm_file_offset,
837			 mappings[i].sfm_max_prot,
838			 mappings[i].sfm_init_prot));
839
840		if (mappings[i].sfm_init_prot & VM_PROT_ZF) {
841			/* zero-filled memory */
842			map_port = MACH_PORT_NULL;
843		} else {
844			/* file-backed memory */
845			map_port = (ipc_port_t) file_object->pager;
846		}
847
848		/* mapping's address is relative to the shared region base */
849		target_address =
850			mappings[i].sfm_address - sr_base_address;
851
852		/* establish that mapping, OK if it's "already" there */
853		if (map_port == MACH_PORT_NULL) {
854			/*
855			 * We want to map some anonymous memory in a
856			 * shared region.
857			 * We have to create the VM object now, so that it
858			 * can be mapped "copy-on-write".
859			 */
860			obj_size = vm_map_round_page(mappings[i].sfm_size);
861			object = vm_object_allocate(obj_size);
862			if (object == VM_OBJECT_NULL) {
863				kr = KERN_RESOURCE_SHORTAGE;
864			} else {
865				kr = vm_map_enter(
866					sr_map,
867					&target_address,
868					vm_map_round_page(mappings[i].sfm_size),
869					0,
870					VM_FLAGS_FIXED | VM_FLAGS_ALREADY,
871					object,
872					0,
873					TRUE,
874					mappings[i].sfm_init_prot & VM_PROT_ALL,
875					mappings[i].sfm_max_prot & VM_PROT_ALL,
876					VM_INHERIT_DEFAULT);
877			}
878		} else {
879			object = VM_OBJECT_NULL; /* no anonymous memory here */
880			kr = vm_map_enter_mem_object(
881				sr_map,
882				&target_address,
883				vm_map_round_page(mappings[i].sfm_size),
884				0,
885				VM_FLAGS_FIXED | VM_FLAGS_ALREADY,
886				map_port,
887				mappings[i].sfm_file_offset,
888				TRUE,
889				mappings[i].sfm_init_prot & VM_PROT_ALL,
890				mappings[i].sfm_max_prot & VM_PROT_ALL,
891				VM_INHERIT_DEFAULT);
892		}
893
894		if (kr != KERN_SUCCESS) {
895			if (map_port == MACH_PORT_NULL) {
896				/*
897				 * Get rid of the VM object we just created
898				 * but failed to map.
899				 */
900				vm_object_deallocate(object);
901				object = VM_OBJECT_NULL;
902			}
903			if (kr == KERN_MEMORY_PRESENT) {
904				/*
905				 * This exact mapping was already there:
906				 * that's fine.
907				 */
908				SHARED_REGION_TRACE_INFO(
909					("shared_region: mapping[%d]: "
910					 "address:0x%016llx size:0x%016llx "
911					 "offset:0x%016llx "
912					 "maxprot:0x%x prot:0x%x "
913					 "already mapped...\n",
914					 i,
915					 (long long)mappings[i].sfm_address,
916					 (long long)mappings[i].sfm_size,
917					 (long long)mappings[i].sfm_file_offset,
918					 mappings[i].sfm_max_prot,
919					 mappings[i].sfm_init_prot));
920				/*
921				 * We didn't establish this mapping ourselves;
922				 * let's reset its size, so that we do not
923				 * attempt to undo it if an error occurs later.
924				 */
925				mappings[i].sfm_size = 0;
926				kr = KERN_SUCCESS;
927			} else {
928				unsigned int j;
929
930				/* this mapping failed ! */
931				SHARED_REGION_TRACE_ERROR(
932					("shared_region: mapping[%d]: "
933					 "address:0x%016llx size:0x%016llx "
934					 "offset:0x%016llx "
935					 "maxprot:0x%x prot:0x%x failed 0x%x\n",
936					 i,
937					 (long long)mappings[i].sfm_address,
938					 (long long)mappings[i].sfm_size,
939					 (long long)mappings[i].sfm_file_offset,
940					 mappings[i].sfm_max_prot,
941					 mappings[i].sfm_init_prot,
942					 kr));
943
944				/*
945				 * Undo the mappings we've established so far.
946				 */
947				for (j = 0; j < i; j++) {
948					kern_return_t kr2;
949
950					if (mappings[j].sfm_size == 0) {
951						/*
952						 * We didn't establish this
953						 * mapping, so nothing to undo.
954						 */
955						continue;
956					}
957					SHARED_REGION_TRACE_INFO(
958						("shared_region: mapping[%d]: "
959						 "address:0x%016llx "
960						 "size:0x%016llx "
961						 "offset:0x%016llx "
962						 "maxprot:0x%x prot:0x%x: "
963						 "undoing...\n",
964						 j,
965						 (long long)mappings[j].sfm_address,
966						 (long long)mappings[j].sfm_size,
967						 (long long)mappings[j].sfm_file_offset,
968						 mappings[j].sfm_max_prot,
969						 mappings[j].sfm_init_prot));
970					kr2 = mach_vm_deallocate(
971						sr_map,
972						(mappings[j].sfm_address -
973						 sr_base_address),
974						mappings[j].sfm_size);
975					assert(kr2 == KERN_SUCCESS);
976				}
977
978				break;
979			}
980
981		}
982
983		/*
984		 * Record the first (chronologically) mapping in
985		 * this shared region.
986		 * We're protected by "sr_mapping_in_progress" here,
987		 * so no need to lock "shared_region".
988		 */
989		if (shared_region->sr_first_mapping == (mach_vm_offset_t) -1) {
990			shared_region->sr_first_mapping = target_address;
991		}
992	}
993
994	vm_shared_region_lock();
995	assert(shared_region->sr_ref_count > 1);
996	assert(shared_region->sr_mapping_in_progress);
997	/* we're done working on that shared region */
998	shared_region->sr_mapping_in_progress = FALSE;
999	thread_wakeup((event_t) &shared_region->sr_mapping_in_progress);
1000	vm_shared_region_unlock();
1001
1002done:
1003	SHARED_REGION_TRACE_DEBUG(
1004		("shared_region: map(%p,%d,%p,%p,0x%llx) <- 0x%x \n",
1005		 shared_region, mappings_count, mappings,
1006		 file_control, file_size, kr));
1007	return kr;
1008}
1009
1010/*
1011 * Enter the appropriate shared region into "map" for "task".
1012 * This involves looking up the shared region (and possibly creating a new
1013 * one) for the desired environment, then mapping the VM sub map into the
1014 * task's VM "map", with the appropriate level of pmap-nesting.
1015 */
1016kern_return_t
1017vm_shared_region_enter(
1018	struct _vm_map		*map,
1019	struct task		*task,
1020	void			*fsroot,
1021	cpu_type_t		cpu)
1022{
1023	kern_return_t		kr;
1024	vm_shared_region_t	shared_region;
1025	vm_map_offset_t		sr_address, sr_offset, target_address;
1026	vm_map_size_t		sr_size, mapping_size;
1027	vm_map_offset_t		sr_pmap_nesting_start;
1028	vm_map_size_t		sr_pmap_nesting_size;
1029	ipc_port_t		sr_handle;
1030	boolean_t		is_64bit;
1031
1032	is_64bit = task_has_64BitAddr(task);
1033
1034	SHARED_REGION_TRACE_DEBUG(
1035		("shared_region: -> "
1036		 "enter(map=%p,task=%p,root=%p,cpu=%d,64bit=%d)\n",
1037		 map, task, fsroot, cpu, is_64bit));
1038
1039	/* lookup (create if needed) the shared region for this environment */
1040	shared_region = vm_shared_region_lookup(fsroot, cpu, is_64bit);
1041	if (shared_region == NULL) {
1042		/* this should not happen ! */
1043		SHARED_REGION_TRACE_ERROR(
1044			("shared_region: -> "
1045			 "enter(map=%p,task=%p,root=%p,cpu=%d,64bit=%d): "
1046			 "lookup failed !\n",
1047			 map, task, fsroot, cpu, is_64bit));
1048		//panic("shared_region_enter: lookup failed\n");
1049		return KERN_FAILURE;
1050	}
1051
1052	/* let the task use that shared region */
1053	vm_shared_region_set(task, shared_region);
1054
1055	kr = KERN_SUCCESS;
1056	/* no need to lock since this data is never modified */
1057	sr_address = shared_region->sr_base_address;
1058	sr_size = shared_region->sr_size;
1059	sr_handle = shared_region->sr_mem_entry;
1060	sr_pmap_nesting_start = shared_region->sr_pmap_nesting_start;
1061	sr_pmap_nesting_size = shared_region->sr_pmap_nesting_size;
1062
1063	/*
1064	 * Start mapping the shared region's VM sub map into the task's VM map.
1065	 */
1066	sr_offset = 0;
1067
1068	if (sr_pmap_nesting_start > sr_address) {
1069		/* we need to map a range without pmap-nesting first */
1070		target_address = sr_address;
1071		mapping_size = sr_pmap_nesting_start - sr_address;
1072		kr = vm_map_enter_mem_object(
1073			map,
1074			&target_address,
1075			mapping_size,
1076			0,
1077			VM_FLAGS_FIXED,
1078			sr_handle,
1079			sr_offset,
1080			TRUE,
1081			VM_PROT_READ,
1082			VM_PROT_ALL,
1083			VM_INHERIT_SHARE);
1084		if (kr != KERN_SUCCESS) {
1085			SHARED_REGION_TRACE_ERROR(
1086				("shared_region: enter(%p,%p,%p,%d,%d): "
1087				 "vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1088				 map, task, fsroot, cpu, is_64bit,
1089				 (long long)target_address,
1090				 (long long)mapping_size, sr_handle, kr));
1091			goto done;
1092		}
1093		SHARED_REGION_TRACE_DEBUG(
1094			("shared_region: enter(%p,%p,%p,%d,%d): "
1095			 "vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1096			 map, task, fsroot, cpu, is_64bit,
1097			 (long long)target_address, (long long)mapping_size,
1098			 sr_handle, kr));
1099		sr_offset += mapping_size;
1100		sr_size -= mapping_size;
1101	}
1102	/*
1103	 * We may need to map several pmap-nested portions, due to platform
1104	 * specific restrictions on pmap nesting.
1105	 * The pmap-nesting is triggered by the "VM_MEMORY_SHARED_PMAP" alias...
1106	 */
1107	for (;
1108	     sr_pmap_nesting_size > 0;
1109	     sr_offset += mapping_size,
1110		     sr_size -= mapping_size,
1111		     sr_pmap_nesting_size -= mapping_size) {
1112		target_address = sr_address + sr_offset;
1113		mapping_size = sr_pmap_nesting_size;
1114		if (mapping_size > pmap_nesting_size_max) {
1115			mapping_size = (vm_map_offset_t) pmap_nesting_size_max;
1116		}
1117		kr = vm_map_enter_mem_object(
1118			map,
1119			&target_address,
1120			mapping_size,
1121			0,
1122			(VM_FLAGS_FIXED | VM_MAKE_TAG(VM_MEMORY_SHARED_PMAP)),
1123			sr_handle,
1124			sr_offset,
1125			TRUE,
1126			VM_PROT_READ,
1127			VM_PROT_ALL,
1128			VM_INHERIT_SHARE);
1129		if (kr != KERN_SUCCESS) {
1130			SHARED_REGION_TRACE_ERROR(
1131				("shared_region: enter(%p,%p,%p,%d,%d): "
1132				 "vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1133				 map, task, fsroot, cpu, is_64bit,
1134				 (long long)target_address,
1135				 (long long)mapping_size, sr_handle, kr));
1136			goto done;
1137		}
1138		SHARED_REGION_TRACE_DEBUG(
1139			("shared_region: enter(%p,%p,%p,%d,%d): "
1140			 "nested vm_map_enter(0x%llx,0x%llx,%p) error 0x%x\n",
1141			 map, task, fsroot, cpu, is_64bit,
1142			 (long long)target_address, (long long)mapping_size,
1143			 sr_handle, kr));
1144	}
1145	if (sr_size > 0) {
1146		/* and there's some left to be mapped without pmap-nesting */
1147		target_address = sr_address + sr_offset;
1148		mapping_size = sr_size;
1149		kr = vm_map_enter_mem_object(
1150			map,
1151			&target_address,
1152			mapping_size,
1153			0,
1154			VM_FLAGS_FIXED,
1155			sr_handle,
1156			sr_offset,
1157			TRUE,
1158			VM_PROT_READ,
1159			VM_PROT_ALL,
1160			VM_INHERIT_SHARE);
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));
1168			goto done;
1169		}
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,
1175			 sr_handle, kr));
1176		sr_offset += mapping_size;
1177		sr_size -= mapping_size;
1178	}
1179	assert(sr_size == 0);
1180
1181done:
1182	SHARED_REGION_TRACE_DEBUG(
1183		("shared_region: enter(%p,%p,%p,%d,%d) <- 0x%x\n",
1184		 map, task, fsroot, cpu, is_64bit, kr));
1185	return kr;
1186}
1187
1188/******************************************************************************/
1189/* Comm page support                                                          */
1190/******************************************************************************/
1191
1192ipc_port_t commpage32_handle = IPC_PORT_NULL;
1193ipc_port_t commpage64_handle = IPC_PORT_NULL;
1194vm_named_entry_t commpage32_entry = NULL;
1195vm_named_entry_t commpage64_entry = NULL;
1196vm_map_t commpage32_map = VM_MAP_NULL;
1197vm_map_t commpage64_map = VM_MAP_NULL;
1198
1199/*
1200 * Create a memory entry, VM submap and pmap for one commpage.
1201 */
1202static void
1203_vm_commpage_init(
1204	ipc_port_t	*handlep,
1205	vm_map_size_t	size)
1206{
1207	kern_return_t		kr;
1208	vm_named_entry_t	mem_entry;
1209	vm_map_t		new_map;
1210
1211	SHARED_REGION_TRACE_DEBUG(
1212		("commpage: -> _init(0x%llx)\n",
1213		 (long long)size));
1214
1215	kr = mach_memory_entry_allocate(&mem_entry,
1216					handlep);
1217	if (kr != KERN_SUCCESS) {
1218		panic("_vm_commpage_init: could not allocate mem_entry");
1219	}
1220	new_map = vm_map_create(pmap_create(0, FALSE), 0, size, TRUE);
1221	if (new_map == VM_MAP_NULL) {
1222		panic("_vm_commpage_init: could not allocate VM map");
1223	}
1224	mem_entry->backing.map = new_map;
1225	mem_entry->internal = TRUE;
1226	mem_entry->is_sub_map = TRUE;
1227	mem_entry->offset = 0;
1228	mem_entry->protection = VM_PROT_ALL;
1229	mem_entry->size = size;
1230
1231	SHARED_REGION_TRACE_DEBUG(
1232		("commpage: _init(0x%llx) <- %p\n",
1233		 (long long)size, *handlep));
1234}
1235
1236/*
1237 * Initialize the comm pages at boot time.
1238 */
1239void
1240vm_commpage_init(void)
1241{
1242	SHARED_REGION_TRACE_DEBUG(
1243		("commpage: -> init()\n"));
1244
1245	/* create the 32-bit comm page */
1246	_vm_commpage_init(&commpage32_handle, _COMM_PAGE32_AREA_LENGTH);
1247	commpage32_entry = (vm_named_entry_t) commpage32_handle->ip_kobject;
1248	commpage32_map = commpage32_entry->backing.map;
1249
1250	/* XXX if (cpu_is_64bit_capable()) ? */
1251	/* create the 64-bit comm page */
1252	_vm_commpage_init(&commpage64_handle, _COMM_PAGE64_AREA_LENGTH);
1253	commpage64_entry = (vm_named_entry_t) commpage64_handle->ip_kobject;
1254	commpage64_map = commpage64_entry->backing.map;
1255
1256	/* populate them according to this specific platform */
1257	commpage_populate();
1258
1259	SHARED_REGION_TRACE_DEBUG(
1260		("commpage: init() <-\n"));
1261}
1262
1263/*
1264 * Enter the appropriate comm page into the task's address space.
1265 * This is called at exec() time via vm_map_exec().
1266 */
1267kern_return_t
1268vm_commpage_enter(
1269	vm_map_t	map,
1270	task_t		task)
1271{
1272	ipc_port_t		commpage_handle;
1273	vm_map_offset_t		commpage_address, objc_address;
1274	vm_map_size_t		commpage_size, objc_size;
1275	int			vm_flags;
1276	kern_return_t		kr;
1277
1278	SHARED_REGION_TRACE_DEBUG(
1279		("commpage: -> enter(%p,%p)\n",
1280		 map, task));
1281
1282	/* the comm page is likely to be beyond the actual end of the VM map */
1283	vm_flags = VM_FLAGS_FIXED | VM_FLAGS_BEYOND_MAX;
1284
1285	/* select the appropriate comm page for this task */
1286	assert(! (task_has_64BitAddr(task) ^ vm_map_is_64bit(map)));
1287	if (task_has_64BitAddr(task)) {
1288#ifdef __ppc__
1289		/*
1290		 * PPC51: ppc64 is limited to 51-bit addresses.
1291		 * Memory above that limit is handled specially at the
1292		 * pmap level, so do not interfere.
1293		 */
1294		vm_flags |= VM_FLAGS_NO_PMAP_CHECK;
1295#endif /* __ppc__ */
1296		commpage_handle = commpage64_handle;
1297		commpage_address = (vm_map_offset_t) _COMM_PAGE64_BASE_ADDRESS;
1298		commpage_size = _COMM_PAGE64_AREA_LENGTH;
1299		objc_size = _COMM_PAGE64_OBJC_SIZE;
1300		objc_address = _COMM_PAGE64_OBJC_BASE;
1301	} else {
1302		commpage_handle = commpage32_handle;
1303		commpage_address =
1304			(vm_map_offset_t)(unsigned) _COMM_PAGE32_BASE_ADDRESS;
1305		commpage_size = _COMM_PAGE32_AREA_LENGTH;
1306		objc_size = _COMM_PAGE32_OBJC_SIZE;
1307		objc_address = _COMM_PAGE32_OBJC_BASE;
1308	}
1309
1310	if ((commpage_address & (pmap_nesting_size_min - 1)) == 0 &&
1311	    (commpage_size & (pmap_nesting_size_min - 1)) == 0) {
1312		/* the commpage is properly aligned or sized for pmap-nesting */
1313		vm_flags |= VM_MAKE_TAG(VM_MEMORY_SHARED_PMAP);
1314	}
1315
1316	/* map the comm page in the task's address space */
1317	assert(commpage_handle != IPC_PORT_NULL);
1318	kr = vm_map_enter_mem_object(
1319		map,
1320		&commpage_address,
1321		commpage_size,
1322		0,
1323		vm_flags,
1324		commpage_handle,
1325		0,
1326		FALSE,
1327		VM_PROT_READ|VM_PROT_EXECUTE,
1328		VM_PROT_READ|VM_PROT_EXECUTE,
1329		VM_INHERIT_SHARE);
1330	if (kr != KERN_SUCCESS) {
1331		SHARED_REGION_TRACE_ERROR(
1332			("commpage: enter(%p,0x%llx,0x%llx) "
1333			 "commpage %p mapping failed 0x%x\n",
1334			 map, (long long)commpage_address,
1335			 (long long)commpage_size, commpage_handle, kr));
1336	}
1337
1338	/*
1339	 * Since we're here, we also pre-allocate some virtual space for the
1340	 * Objective-C run-time, if needed...
1341	 */
1342	if (objc_size != 0) {
1343		kr = vm_map_enter_mem_object(
1344			map,
1345			&objc_address,
1346			objc_size,
1347			0,
1348			VM_FLAGS_FIXED | VM_FLAGS_BEYOND_MAX,
1349			IPC_PORT_NULL,
1350			0,
1351			FALSE,
1352			VM_PROT_ALL,
1353			VM_PROT_ALL,
1354			VM_INHERIT_DEFAULT);
1355		if (kr != KERN_SUCCESS) {
1356			SHARED_REGION_TRACE_ERROR(
1357				("commpage: enter(%p,0x%llx,0x%llx) "
1358				 "objc mapping failed 0x%x\n",
1359				 map, (long long)objc_address,
1360				 (long long)objc_size, kr));
1361		}
1362	}
1363
1364	SHARED_REGION_TRACE_DEBUG(
1365		("commpage: enter(%p,%p) <- 0x%x\n",
1366		 map, task, kr));
1367	return kr;
1368}
1369