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
44extern int shared_region_version;
45extern int shared_region_persistence;
46
47#if DEBUG
48extern 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
59extern int shared_region_trace_level;
60
61extern 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
90typedef 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
103typedef struct vm_shared_region_slide_info_entry_v1 *vm_shared_region_slide_info_entry_v1_t;
104struct 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*/
116typedef struct slide_info_entry_toc *slide_info_entry_toc_t;
117struct slide_info_entry_toc {
118 uint8_t entry[NUM_SLIDING_BITMAPS_PER_PAGE];
119};
120
121typedef struct vm_shared_region_slide_info_entry_v2 *vm_shared_region_slide_info_entry_v2_t;
122struct 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 page_extras_offset;
128 uint32_t page_extras_count;
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 DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA 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
142typedef struct vm_shared_region_slide_info_entry_v3 *vm_shared_region_slide_info_entry_v3_t;
143struct 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
155typedef struct vm_shared_region_slide_info_entry_v4 *vm_shared_region_slide_info_entry_v4_t;
156struct 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 page_extras_offset;
162 uint32_t page_extras_count;
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 DYLD_CACHE_SLIDE4_PAGE_USE_EXTRA 0x8000 // index is into extras array (not starts array)
172#define DYLD_CACHE_SLIDE4_PAGE_EXTRA_END 0x8000 // last chain entry for page
173
174
175
176typedef union vm_shared_region_slide_info_entry *vm_shared_region_slide_info_entry_t;
177union 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
185typedef struct vm_shared_region_slide_info *vm_shared_region_slide_info_t;
186struct 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 */
197struct 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
222extern 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);
226extern vm_shared_region_slide_info_t vm_shared_region_get_slide_info(vm_shared_region_t sr);
227#else /* !MACH_KERNEL_PRIVATE */
228
229struct vm_shared_region;
230struct vm_shared_region_slide_info;
231struct vm_shared_region_slide_info_entry;
232struct slide_info_entry_toc;
233
234#endif /* MACH_KERNEL_PRIVATE */
235
236extern void vm_shared_region_init(void);
237extern 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);
244extern kern_return_t vm_shared_region_remove(
245 struct _vm_map *map,
246 struct task *task);
247extern vm_shared_region_t vm_shared_region_get(
248 struct task *task);
249extern vm_shared_region_t vm_shared_region_trim_and_get(
250 struct task *task);
251extern void vm_shared_region_deallocate(
252 struct vm_shared_region *shared_region);
253extern mach_vm_offset_t vm_shared_region_base_address(
254 struct vm_shared_region *shared_region);
255extern mach_vm_size_t vm_shared_region_size(
256 struct vm_shared_region *shared_region);
257extern ipc_port_t vm_shared_region_mem_entry(
258 struct vm_shared_region *shared_region);
259extern vm_map_t vm_shared_region_vm_map(
260 struct vm_shared_region *shared_region);
261extern uint32_t vm_shared_region_get_slide(
262 vm_shared_region_t shared_region);
263extern void vm_shared_region_set(
264 struct task *task,
265 struct vm_shared_region *new_shared_region);
266extern 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);
271extern kern_return_t vm_shared_region_start_address(
272 struct vm_shared_region *shared_region,
273 mach_vm_offset_t *start_address);
274extern 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);
279extern 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);
289extern kern_return_t vm_shared_region_sliding_valid(uint32_t slide);
290extern kern_return_t vm_shared_region_slide_sanity_check(vm_shared_region_t sr);
291extern void* vm_shared_region_get_slide_info_entry(vm_shared_region_t sr);
292extern void vm_commpage_init(void);
293extern void vm_commpage_text_init(void);
294extern kern_return_t vm_commpage_enter(
295 struct _vm_map *map,
296 struct task *task,
297 boolean_t is64bit);
298extern kern_return_t vm_commpage_remove(
299 struct _vm_map *map,
300 struct task *task);
301int 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