- extern vm_map_t com_region_map; // the shared submap, set up in vm init
- vm_offset_t kernel_addr; // address of commpage in kernel map
- vm_offset_t zero = 0;
- vm_size_t size = _COMM_PAGE_AREA_LENGTH;
- ipc_port_t handle;
-
- if (com_region_map == NULL)
- panic("commpage map is null");
-
- if (vm_allocate(kernel_map,&kernel_addr,_COMM_PAGE_AREA_LENGTH,VM_FLAGS_ANYWHERE))
- panic("cannot allocate commpage");
-
- if (vm_map_wire(kernel_map,kernel_addr,kernel_addr+_COMM_PAGE_AREA_LENGTH,VM_PROT_DEFAULT,FALSE))
- panic("cannot wire commpage");
-
- if (mach_make_memory_entry( kernel_map, // target map
- &size, // size
- kernel_addr, // offset (address in kernel map)
- VM_PROT_DEFAULT, // map it RW
- &handle, // this is the object handle we get
- NULL )) // parent_entry (what is this?)
- panic("cannot make entry for commpage");
-
- if (vm_map_64( com_region_map, // target map (shared submap)
- &zero, // address (map into 1st page in submap)
- _COMM_PAGE_AREA_LENGTH, // size
- 0, // mask
- VM_FLAGS_FIXED, // flags (it must be 1st page in submap)
- handle, // port is the memory entry we just made
- 0, // offset (map 1st page in memory entry)
- FALSE, // copy
- VM_PROT_READ, // cur_protection (R-only in user map)
- VM_PROT_READ, // max_protection
- VM_INHERIT_SHARE )) // inheritance
- panic("cannot map commpage");
-
- ipc_port_release(handle);
-
- return (void*) kernel_addr; // return address in kernel map
+ vm_offset_t kernel_addr = 0; // address of commpage in kernel map
+ vm_offset_t zero = 0;
+ vm_size_t size = area_used; // size actually populated
+ vm_map_entry_t entry;
+ ipc_port_t handle;
+ kern_return_t kr;
+
+ if (submap == NULL)
+ panic("commpage submap is null");
+
+ if ((kr = vm_map(kernel_map,
+ &kernel_addr,
+ area_used,
+ 0,
+ VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_KERN_MEMORY_OSFMK),
+ NULL,
+ 0,
+ FALSE,
+ VM_PROT_ALL,
+ VM_PROT_ALL,
+ VM_INHERIT_NONE)))
+ panic("cannot allocate commpage %d", kr);
+
+ if ((kr = vm_map_wire(kernel_map,
+ kernel_addr,
+ kernel_addr+area_used,
+ VM_PROT_DEFAULT|VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_OSFMK),
+ FALSE)))
+ panic("cannot wire commpage: %d", kr);
+
+ /*
+ * Now that the object is created and wired into the kernel map, mark it so that no delay
+ * copy-on-write will ever be performed on it as a result of mapping it into user-space.
+ * If such a delayed copy ever occurred, we could remove the kernel's wired mapping - and
+ * that would be a real disaster.
+ *
+ * JMM - What we really need is a way to create it like this in the first place.
+ */
+ if (!(kr = vm_map_lookup_entry( kernel_map, vm_map_trunc_page(kernel_addr, VM_MAP_PAGE_MASK(kernel_map)), &entry) || entry->is_sub_map))
+ panic("cannot find commpage entry %d", kr);
+ VME_OBJECT(entry)->copy_strategy = MEMORY_OBJECT_COPY_NONE;
+
+ if ((kr = mach_make_memory_entry( kernel_map, // target map
+ &size, // size
+ kernel_addr, // offset (address in kernel map)
+ uperm, // protections as specified
+ &handle, // this is the object handle we get
+ NULL ))) // parent_entry (what is this?)
+ panic("cannot make entry for commpage %d", kr);
+
+ if ((kr = vm_map_64( submap, // target map (shared submap)
+ &zero, // address (map into 1st page in submap)
+ area_used, // size
+ 0, // mask
+ VM_FLAGS_FIXED, // flags (it must be 1st page in submap)
+ handle, // port is the memory entry we just made
+ 0, // offset (map 1st page in memory entry)
+ FALSE, // copy
+ uperm, // cur_protection (R-only in user map)
+ uperm, // max_protection
+ VM_INHERIT_SHARE ))) // inheritance
+ panic("cannot map commpage %d", kr);
+
+ ipc_port_release(handle);
+ /* Make the kernel mapping non-executable. This cannot be done
+ * at the time of map entry creation as mach_make_memory_entry
+ * cannot handle disjoint permissions at this time.
+ */
+ kr = vm_protect(kernel_map, kernel_addr, area_used, FALSE, VM_PROT_READ | VM_PROT_WRITE);
+ assert (kr == KERN_SUCCESS);
+
+ return (void*)(intptr_t)kernel_addr; // return address in kernel map