| 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 | * File: vm/vm_shared_region.h |
| 26 | * |
| 27 | * protos and struct definitions for shared region |
| 28 | */ |
| 29 | |
| 30 | #ifndef _VM_SHARED_REGION_H_ |
| 31 | #define _VM_SHARED_REGION_H_ |
| 32 | |
| 33 | #ifdef KERNEL_PRIVATE |
| 34 | |
| 35 | #include <mach/vm_prot.h> |
| 36 | #include <mach/mach_types.h> |
| 37 | #include <mach/shared_region.h> |
| 38 | |
| 39 | #include <kern/kern_types.h> |
| 40 | #include <kern/macro_help.h> |
| 41 | |
| 42 | #include <vm/vm_map.h> |
| 43 | |
| 44 | extern int shared_region_version; |
| 45 | extern int shared_region_persistence; |
| 46 | |
| 47 | #if DEBUG |
| 48 | extern int shared_region_debug; |
| 49 | #define SHARED_REGION_DEBUG(args) \ |
| 50 | MACRO_BEGIN \ |
| 51 | if (shared_region_debug) { \ |
| 52 | kprintf args; \ |
| 53 | } \ |
| 54 | MACRO_END |
| 55 | #else /* DEBUG */ |
| 56 | #define SHARED_REGION_DEBUG(args) |
| 57 | #endif /* DEBUG */ |
| 58 | |
| 59 | extern int shared_region_trace_level; |
| 60 | |
| 61 | extern struct vm_shared_region *init_task_shared_region; |
| 62 | |
| 63 | #define SHARED_REGION_TRACE_NONE_LVL 0 /* no trace */ |
| 64 | #define SHARED_REGION_TRACE_ERROR_LVL 1 /* trace abnormal events */ |
| 65 | #define SHARED_REGION_TRACE_INFO_LVL 2 /* trace all events */ |
| 66 | #define SHARED_REGION_TRACE_DEBUG_LVL 3 /* extra traces for debug */ |
| 67 | #define SHARED_REGION_TRACE(level, args) \ |
| 68 | MACRO_BEGIN \ |
| 69 | if (shared_region_trace_level >= level) { \ |
| 70 | printf args; \ |
| 71 | } \ |
| 72 | MACRO_END |
| 73 | #define SHARED_REGION_TRACE_NONE(args) |
| 74 | #define SHARED_REGION_TRACE_ERROR(args) \ |
| 75 | MACRO_BEGIN \ |
| 76 | SHARED_REGION_TRACE(SHARED_REGION_TRACE_ERROR_LVL, \ |
| 77 | args); \ |
| 78 | MACRO_END |
| 79 | #define SHARED_REGION_TRACE_INFO(args) \ |
| 80 | MACRO_BEGIN \ |
| 81 | SHARED_REGION_TRACE(SHARED_REGION_TRACE_INFO_LVL, \ |
| 82 | args); \ |
| 83 | MACRO_END |
| 84 | #define SHARED_REGION_TRACE_DEBUG(args) \ |
| 85 | MACRO_BEGIN \ |
| 86 | SHARED_REGION_TRACE(SHARED_REGION_TRACE_DEBUG_LVL, \ |
| 87 | args); \ |
| 88 | MACRO_END |
| 89 | |
| 90 | typedef struct vm_shared_region *vm_shared_region_t; |
| 91 | |
| 92 | #ifdef MACH_KERNEL_PRIVATE |
| 93 | |
| 94 | #include <kern/queue.h> |
| 95 | #include <vm/vm_object.h> |
| 96 | #include <vm/memory_object.h> |
| 97 | |
| 98 | #define PAGE_SIZE_FOR_SR_SLIDE 4096 |
| 99 | |
| 100 | /* Documentation for the slide info format can be found in the dyld project in |
| 101 | * the file 'launch-cache/dyld_cache_format.h'. */ |
| 102 | |
| 103 | typedef struct vm_shared_region_slide_info_entry_v1 *vm_shared_region_slide_info_entry_v1_t; |
| 104 | struct vm_shared_region_slide_info_entry_v1 { |
| 105 | uint32_t version; |
| 106 | uint32_t toc_offset; // offset from start of header to table-of-contents |
| 107 | uint32_t toc_count; // number of entries in toc (same as number of pages in r/w mapping) |
| 108 | uint32_t entry_offset; |
| 109 | uint32_t entry_count; |
| 110 | // uint16_t toc[toc_count]; |
| 111 | // entrybitmap entries[entries_count]; |
| 112 | }; |
| 113 | |
| 114 | #define NBBY 8 |
| 115 | #define NUM_SLIDING_BITMAPS_PER_PAGE (0x1000/sizeof(int)/NBBY) /*128*/ |
| 116 | typedef struct slide_info_entry_toc *slide_info_entry_toc_t; |
| 117 | struct slide_info_entry_toc { |
| 118 | uint8_t entry[NUM_SLIDING_BITMAPS_PER_PAGE]; |
| 119 | }; |
| 120 | |
| 121 | typedef struct vm_shared_region_slide_info_entry_v2 *vm_shared_region_slide_info_entry_v2_t; |
| 122 | struct vm_shared_region_slide_info_entry_v2 { |
| 123 | uint32_t version; |
| 124 | uint32_t page_size; |
| 125 | uint32_t page_starts_offset; |
| 126 | uint32_t page_starts_count; |
| 127 | uint32_t ; |
| 128 | uint32_t ; |
| 129 | uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location |
| 130 | uint64_t value_add; |
| 131 | // uint16_t page_starts[page_starts_count]; |
| 132 | // uint16_t page_extras[page_extras_count]; |
| 133 | }; |
| 134 | |
| 135 | #define DYLD_CACHE_SLIDE_PAGE_ATTRS 0xC000 // high bits of uint16_t are flags |
| 136 | #define 0x8000 // index is into extras array (not starts array) |
| 137 | #define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE 0x4000 // page has no rebasing |
| 138 | #define DYLD_CACHE_SLIDE_PAGE_ATTR_END 0x8000 // last chain entry for page |
| 139 | #define DYLD_CACHE_SLIDE_PAGE_VALUE 0x3FFF // bitwise negation of DYLD_CACHE_SLIDE_PAGE_ATTRS |
| 140 | #define DYLD_CACHE_SLIDE_PAGE_OFFSET_SHIFT 2 |
| 141 | |
| 142 | typedef struct vm_shared_region_slide_info_entry_v3 *vm_shared_region_slide_info_entry_v3_t; |
| 143 | struct vm_shared_region_slide_info_entry_v3 |
| 144 | { |
| 145 | uint32_t version; // currently 3 |
| 146 | uint32_t page_size; // currently 4096 (may also be 16384) |
| 147 | uint32_t page_starts_count; |
| 148 | uint64_t value_add; |
| 149 | uint16_t page_starts[/* page_starts_count */]; |
| 150 | }; |
| 151 | |
| 152 | #define DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE 0xFFFF // page has no rebasing |
| 153 | |
| 154 | |
| 155 | typedef struct vm_shared_region_slide_info_entry_v4 *vm_shared_region_slide_info_entry_v4_t; |
| 156 | struct vm_shared_region_slide_info_entry_v4 { |
| 157 | uint32_t version; // currently 4 |
| 158 | uint32_t page_size; // currently 4096 (may also be 16384) |
| 159 | uint32_t page_starts_offset; |
| 160 | uint32_t page_starts_count; |
| 161 | uint32_t ; |
| 162 | uint32_t ; |
| 163 | uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location (0xC0000000) |
| 164 | uint64_t value_add; // base address of cache |
| 165 | // uint16_t page_starts[page_starts_count]; |
| 166 | // uint16_t page_extras[page_extras_count]; |
| 167 | }; |
| 168 | |
| 169 | #define DYLD_CACHE_SLIDE4_PAGE_NO_REBASE 0xFFFF // page has no rebasing |
| 170 | #define DYLD_CACHE_SLIDE4_PAGE_INDEX 0x7FFF // index into starts or extras |
| 171 | #define 0x8000 // index is into extras array (not starts array) |
| 172 | #define 0x8000 // last chain entry for page |
| 173 | |
| 174 | |
| 175 | |
| 176 | typedef union vm_shared_region_slide_info_entry *vm_shared_region_slide_info_entry_t; |
| 177 | union vm_shared_region_slide_info_entry { |
| 178 | uint32_t version; |
| 179 | struct vm_shared_region_slide_info_entry_v1 v1; |
| 180 | struct vm_shared_region_slide_info_entry_v2 v2; |
| 181 | struct vm_shared_region_slide_info_entry_v3 v3; |
| 182 | struct vm_shared_region_slide_info_entry_v4 v4; |
| 183 | }; |
| 184 | |
| 185 | typedef struct vm_shared_region_slide_info *vm_shared_region_slide_info_t; |
| 186 | struct vm_shared_region_slide_info { |
| 187 | mach_vm_address_t slid_address; |
| 188 | mach_vm_offset_t start; |
| 189 | mach_vm_offset_t end; |
| 190 | uint32_t slide; |
| 191 | vm_object_t slide_object; |
| 192 | mach_vm_size_t slide_info_size; |
| 193 | vm_shared_region_slide_info_entry_t slide_info_entry; |
| 194 | }; |
| 195 | |
| 196 | /* address space shared region descriptor */ |
| 197 | struct vm_shared_region { |
| 198 | uint32_t sr_ref_count; |
| 199 | queue_chain_t sr_q; |
| 200 | void *sr_root_dir; |
| 201 | cpu_type_t sr_cpu_type; |
| 202 | cpu_subtype_t sr_cpu_subtype; |
| 203 | boolean_t sr_64bit; |
| 204 | boolean_t sr_mapping_in_progress; |
| 205 | boolean_t sr_slide_in_progress; |
| 206 | boolean_t sr_persists; |
| 207 | boolean_t sr_slid; |
| 208 | ipc_port_t sr_mem_entry; |
| 209 | mach_vm_offset_t sr_first_mapping; |
| 210 | mach_vm_offset_t sr_base_address; |
| 211 | mach_vm_size_t sr_size; |
| 212 | mach_vm_offset_t sr_pmap_nesting_start; |
| 213 | mach_vm_size_t sr_pmap_nesting_size; |
| 214 | thread_call_t sr_timer_call; |
| 215 | struct vm_shared_region_slide_info sr_slide_info; |
| 216 | uuid_t sr_uuid; |
| 217 | boolean_t sr_uuid_copied; |
| 218 | uint32_t sr_images_count; |
| 219 | struct dyld_uuid_info_64 *sr_images; |
| 220 | }; |
| 221 | |
| 222 | extern kern_return_t vm_shared_region_slide_page(vm_shared_region_slide_info_t si, |
| 223 | vm_offset_t vaddr, |
| 224 | mach_vm_offset_t uservaddr, |
| 225 | uint32_t pageIndex); |
| 226 | extern vm_shared_region_slide_info_t vm_shared_region_get_slide_info(vm_shared_region_t sr); |
| 227 | #else /* !MACH_KERNEL_PRIVATE */ |
| 228 | |
| 229 | struct vm_shared_region; |
| 230 | struct vm_shared_region_slide_info; |
| 231 | struct vm_shared_region_slide_info_entry; |
| 232 | struct slide_info_entry_toc; |
| 233 | |
| 234 | #endif /* MACH_KERNEL_PRIVATE */ |
| 235 | |
| 236 | extern void vm_shared_region_init(void); |
| 237 | extern kern_return_t vm_shared_region_enter( |
| 238 | struct _vm_map *map, |
| 239 | struct task *task, |
| 240 | boolean_t is_64bit, |
| 241 | void *fsroot, |
| 242 | cpu_type_t cpu, |
| 243 | cpu_subtype_t cpu_subtype); |
| 244 | extern kern_return_t vm_shared_region_remove( |
| 245 | struct _vm_map *map, |
| 246 | struct task *task); |
| 247 | extern vm_shared_region_t vm_shared_region_get( |
| 248 | struct task *task); |
| 249 | extern vm_shared_region_t vm_shared_region_trim_and_get( |
| 250 | struct task *task); |
| 251 | extern void vm_shared_region_deallocate( |
| 252 | struct vm_shared_region *shared_region); |
| 253 | extern mach_vm_offset_t vm_shared_region_base_address( |
| 254 | struct vm_shared_region *shared_region); |
| 255 | extern mach_vm_size_t vm_shared_region_size( |
| 256 | struct vm_shared_region *shared_region); |
| 257 | extern ipc_port_t vm_shared_region_mem_entry( |
| 258 | struct vm_shared_region *shared_region); |
| 259 | extern vm_map_t vm_shared_region_vm_map( |
| 260 | struct vm_shared_region *shared_region); |
| 261 | extern uint32_t vm_shared_region_get_slide( |
| 262 | vm_shared_region_t shared_region); |
| 263 | extern void vm_shared_region_set( |
| 264 | struct task *task, |
| 265 | struct vm_shared_region *new_shared_region); |
| 266 | extern vm_shared_region_t vm_shared_region_lookup( |
| 267 | void *root_dir, |
| 268 | cpu_type_t cpu, |
| 269 | cpu_subtype_t cpu_subtype, |
| 270 | boolean_t is_64bit); |
| 271 | extern kern_return_t vm_shared_region_start_address( |
| 272 | struct vm_shared_region *shared_region, |
| 273 | mach_vm_offset_t *start_address); |
| 274 | extern void vm_shared_region_undo_mappings( |
| 275 | vm_map_t sr_map, |
| 276 | mach_vm_offset_t sr_base_address, |
| 277 | struct shared_file_mapping_np *mappings, |
| 278 | unsigned int mappings_count); |
| 279 | extern kern_return_t vm_shared_region_map_file( |
| 280 | struct vm_shared_region *shared_region, |
| 281 | unsigned int mappings_count, |
| 282 | struct shared_file_mapping_np *mappings, |
| 283 | memory_object_control_t file_control, |
| 284 | memory_object_size_t file_size, |
| 285 | void *root_dir, |
| 286 | uint32_t slide, |
| 287 | user_addr_t slide_start, |
| 288 | user_addr_t slide_size); |
| 289 | extern kern_return_t vm_shared_region_sliding_valid(uint32_t slide); |
| 290 | extern kern_return_t vm_shared_region_slide_sanity_check(vm_shared_region_t sr); |
| 291 | extern void* vm_shared_region_get_slide_info_entry(vm_shared_region_t sr); |
| 292 | extern void vm_commpage_init(void); |
| 293 | extern void vm_commpage_text_init(void); |
| 294 | extern kern_return_t vm_commpage_enter( |
| 295 | struct _vm_map *map, |
| 296 | struct task *task, |
| 297 | boolean_t is64bit); |
| 298 | extern kern_return_t vm_commpage_remove( |
| 299 | struct _vm_map *map, |
| 300 | struct task *task); |
| 301 | int vm_shared_region_slide(uint32_t, |
| 302 | mach_vm_offset_t, |
| 303 | mach_vm_size_t, |
| 304 | mach_vm_offset_t, |
| 305 | mach_vm_size_t, |
| 306 | mach_vm_offset_t, |
| 307 | memory_object_control_t); |
| 308 | |
| 309 | #endif /* KERNEL_PRIVATE */ |
| 310 | |
| 311 | #endif /* _VM_SHARED_REGION_H_ */ |
| 312 | |