]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_OSREFERENCE_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. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
25 | * | |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
27 | */ | |
28 | /* | |
29 | * @OSF_COPYRIGHT@ | |
30 | */ | |
31 | /* | |
32 | * Mach Operating System | |
33 | * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University | |
34 | * All Rights Reserved. | |
35 | * | |
36 | * Permission to use, copy, modify and distribute this software and its | |
37 | * documentation is hereby granted, provided that both the copyright | |
38 | * notice and this permission notice appear in all copies of the | |
39 | * software, derivative works or modified versions, and any portions | |
40 | * thereof, and that both notices appear in supporting documentation. | |
41 | * | |
42 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
43 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
44 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
45 | * | |
46 | * Carnegie Mellon requests users of this software to return to | |
47 | * | |
48 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
49 | * School of Computer Science | |
50 | * Carnegie Mellon University | |
51 | * Pittsburgh PA 15213-3890 | |
52 | * | |
53 | * any improvements or extensions that they make and grant Carnegie Mellon | |
54 | * the rights to redistribute these changes. | |
55 | */ | |
56 | /* | |
57 | */ | |
58 | /* | |
59 | * File: mach/vm_param.h | |
60 | * Author: Avadis Tevanian, Jr., Michael Wayne Young | |
61 | * Date: 1985 | |
62 | * | |
63 | * Machine independent virtual memory parameters. | |
64 | * | |
65 | */ | |
66 | ||
67 | #ifndef _MACH_VM_PARAM_H_ | |
68 | #define _MACH_VM_PARAM_H_ | |
69 | ||
70 | #include <mach/machine/vm_param.h> | |
71 | ||
72 | #ifdef KERNEL | |
73 | ||
74 | #ifndef ASSEMBLER | |
75 | #include <mach/vm_types.h> | |
76 | #endif /* ASSEMBLER */ | |
77 | ||
78 | /* | |
79 | * The machine independent pages are refered to as PAGES. A page | |
80 | * is some number of hardware pages, depending on the target machine. | |
81 | */ | |
82 | ||
83 | #ifndef ASSEMBLER | |
84 | ||
85 | #define PAGE_SIZE_64 (unsigned long long)PAGE_SIZE /* pagesize in addr units */ | |
86 | #define PAGE_MASK_64 (unsigned long long)PAGE_MASK /* mask for off in page */ | |
87 | ||
88 | /* | |
89 | * Convert addresses to pages and vice versa. No rounding is used. | |
90 | * The atop_32 and ptoa_32 macros should not be use on 64 bit types. | |
91 | * The round_page_64 and trunc_page_64 macros should be used instead. | |
92 | */ | |
93 | ||
94 | #define atop_32(x) ((uint32_t)(x) >> PAGE_SHIFT) | |
95 | #define ptoa_32(x) ((uint32_t)(x) << PAGE_SHIFT) | |
96 | #define atop_64(x) ((uint64_t)(x) >> PAGE_SHIFT) | |
97 | #define ptoa_64(x) ((uint64_t)(x) << PAGE_SHIFT) | |
98 | ||
99 | #define atop_kernel(x) ((vm_address_t)(x) >> PAGE_SHIFT) | |
100 | #define ptoa_kernel(x) ((vm_address_t)(x) << PAGE_SHIFT) | |
101 | ||
102 | /* | |
103 | * While the following block is enabled, the legacy atop and ptoa | |
104 | * macros will behave correctly. If not, they will generate | |
105 | * invalid lvalue errors. | |
106 | */ | |
107 | ||
108 | #if 1 | |
109 | #define atop(x) ((vm_address_t)(x) >> PAGE_SHIFT) | |
110 | #define ptoa(x) ((vm_address_t)(x) << PAGE_SHIFT) | |
111 | #else | |
112 | #define atop(x) (0UL = 0) | |
113 | #define ptoa(x) (0UL = 0) | |
114 | #endif | |
115 | ||
116 | /* | |
117 | * Page-size rounding macros for the Public fixed-width VM types. | |
118 | */ | |
119 | #define mach_vm_round_page(x) (((mach_vm_offset_t)(x) + PAGE_MASK) & ~((signed)PAGE_MASK)) | |
120 | #define mach_vm_trunc_page(x) ((mach_vm_offset_t)(x) & ~((signed)PAGE_MASK)) | |
121 | ||
122 | #define memory_object_round_page(x) (((memory_object_offset_t)(x) + PAGE_MASK) & ~((signed)PAGE_MASK)) | |
123 | #define memory_object_trunc_page(x) ((memory_object_offset_t)(x) & ~((signed)PAGE_MASK)) | |
124 | ||
125 | /* | |
126 | * Rounding macros for the legacy (scalable with the current task's | |
127 | * address space size) VM types. | |
128 | */ | |
129 | ||
130 | #define round_page(x) (((vm_offset_t)(x) + PAGE_MASK) & ~((vm_offset_t)PAGE_MASK)) | |
131 | #define trunc_page(x) ((vm_offset_t)(x) & ~((vm_offset_t)PAGE_MASK)) | |
132 | ||
133 | /* | |
134 | * Round off or truncate to the nearest page. These will work | |
135 | * for either addresses or counts. (i.e. 1 byte rounds to 1 page | |
136 | * bytes. The round_page_32 and trunc_page_32 macros should not be | |
137 | * use on 64 bit types. The round_page_64 and trunc_page_64 macros | |
138 | * should be used instead. | |
139 | * | |
140 | * These should only be used in the rare case the size of the address | |
141 | * or length is hard-coded as 32 or 64 bit. Otherwise, the macros | |
142 | * associated with the specific VM type should be used. | |
143 | */ | |
144 | ||
145 | #define round_page_32(x) (((uint32_t)(x) + PAGE_MASK) & ~((uint32_t)PAGE_MASK)) | |
146 | #define trunc_page_32(x) ((uint32_t)(x) & ~((uint32_t)PAGE_MASK)) | |
147 | #define round_page_64(x) (((uint64_t)(x) + PAGE_MASK_64) & ~((uint64_t)PAGE_MASK_64)) | |
148 | #define trunc_page_64(x) ((uint64_t)(x) & ~((uint64_t)PAGE_MASK_64)) | |
149 | ||
150 | /* | |
151 | * Enable the following block to find uses of xxx_32 macros that should | |
152 | * be xxx_64. These macros only work in C code, not C++. The resulting | |
153 | * binaries are not functional. Look for invalid lvalue errors in | |
154 | * the compiler output. | |
155 | * | |
156 | * Enabling the following block will also find use of the xxx_64 macros | |
157 | * that have been passed pointers. The parameters should be case to an | |
158 | * unsigned long type first. Look for invalid operands to binary + error | |
159 | * in the compiler output. | |
160 | */ | |
161 | ||
162 | #if 0 | |
163 | #undef atop_32 | |
164 | #undef ptoa_32 | |
165 | #undef round_page_32 | |
166 | #undef trunc_page_32 | |
167 | #undef atop_64 | |
168 | #undef ptoa_64 | |
169 | #undef round_page_64 | |
170 | #undef trunc_page_64 | |
171 | ||
172 | #ifndef __cplusplus | |
173 | ||
174 | #define atop_32(x) \ | |
175 | (__builtin_choose_expr (sizeof(x) != sizeof(uint64_t), \ | |
176 | (*(long *)0), \ | |
177 | (0UL)) = 0) | |
178 | ||
179 | #define ptoa_32(x) \ | |
180 | (__builtin_choose_expr (sizeof(x) != sizeof(uint64_t), \ | |
181 | (*(long *)0), \ | |
182 | (0UL)) = 0) | |
183 | ||
184 | #define round_page_32(x) \ | |
185 | (__builtin_choose_expr (sizeof(x) != sizeof(uint64_t), \ | |
186 | (*(long *)0), \ | |
187 | (0UL)) = 0) | |
188 | ||
189 | #define trunc_page_32(x) \ | |
190 | (__builtin_choose_expr (sizeof(x) != sizeof(uint64_t), \ | |
191 | (*(long *)0), \ | |
192 | (0UL)) = 0) | |
193 | #else | |
194 | ||
195 | #define atop_32(x) (0) | |
196 | #define ptoa_32(x) (0) | |
197 | #define round_page_32(x) (0) | |
198 | #define trunc_page_32(x) (0) | |
199 | ||
200 | #endif /* ! __cplusplus */ | |
201 | ||
202 | #define atop_64(x) ((uint64_t)((x) + (uint8_t *)0)) | |
203 | #define ptoa_64(x) ((uint64_t)((x) + (uint8_t *)0)) | |
204 | #define round_page_64(x) ((uint64_t)((x) + (uint8_t *)0)) | |
205 | #define trunc_page_64(x) ((uint64_t)((x) + (uint8_t *)0)) | |
206 | ||
207 | #endif | |
208 | ||
209 | /* | |
210 | * Determine whether an address is page-aligned, or a count is | |
211 | * an exact page multiple. | |
212 | */ | |
213 | ||
214 | #define page_aligned(x) (((x) & PAGE_MASK) == 0) | |
215 | ||
216 | extern vm_size_t mem_size; /* 32-bit size of memory - limited by maxmem - deprecated */ | |
217 | extern uint64_t max_mem; /* 64-bit size of memory - limited by maxmem */ | |
218 | ||
219 | /* | |
220 | * The default pager does not handle 64-bit offsets inside its objects, | |
221 | * so this limits the size of anonymous memory objects to 4GB minus 1 page. | |
222 | * When we need to allocate a chunk of anonymous memory over that size, | |
223 | * we have to allocate more than one chunk. | |
224 | */ | |
225 | #define ANON_MAX_SIZE 0xFFFFF000ULL | |
226 | /* | |
227 | * Work-around for <rdar://problem/6626493> | |
228 | * Break large anonymous memory areas into 128MB chunks to alleviate | |
229 | * the cost of copying when copy-on-write is not possible because a small | |
230 | * portion of it being wired. | |
231 | */ | |
232 | #define ANON_CHUNK_SIZE (128ULL * 1024 * 1024) /* 128MB */ | |
233 | ||
234 | #ifdef XNU_KERNEL_PRIVATE | |
235 | ||
236 | extern uint64_t mem_actual; /* 64-bit size of memory - not limited by maxmem */ | |
237 | extern uint64_t sane_size; /* Memory size to use for defaults calculations */ | |
238 | extern addr64_t vm_last_addr; /* Highest kernel virtual address known to the VM system */ | |
239 | ||
240 | extern const vm_offset_t vm_min_kernel_address; | |
241 | extern const vm_offset_t vm_max_kernel_address; | |
242 | ||
243 | extern vm_offset_t vm_kernel_stext; | |
244 | extern vm_offset_t vm_kernel_etext; | |
245 | extern vm_offset_t vm_kernel_base; | |
246 | extern vm_offset_t vm_kernel_top; | |
247 | extern vm_offset_t vm_kernel_slide; | |
248 | extern vm_offset_t vm_hib_base; | |
249 | extern vm_offset_t vm_kernel_addrperm; | |
250 | ||
251 | extern vm_offset_t vm_kext_base; | |
252 | extern vm_offset_t vm_kext_top; | |
253 | extern vm_offset_t vm_prelink_stext; | |
254 | extern vm_offset_t vm_prelink_etext; | |
255 | extern vm_offset_t vm_prelink_sinfo; | |
256 | extern vm_offset_t vm_prelink_einfo; | |
257 | extern vm_offset_t vm_slinkedit; | |
258 | extern vm_offset_t vm_elinkedit; | |
259 | ||
260 | #define VM_KERNEL_IS_SLID(_o) \ | |
261 | (((vm_offset_t)(_o) >= vm_kernel_base) && \ | |
262 | ((vm_offset_t)(_o) < vm_kernel_top)) | |
263 | #define VM_KERNEL_IS_KEXT(_o) \ | |
264 | (((vm_offset_t)(_o) >= vm_kext_base) && \ | |
265 | ((vm_offset_t)(_o) < vm_kext_top)) | |
266 | ||
267 | #define VM_KERNEL_IS_PRELINKTEXT(_o) \ | |
268 | (((vm_offset_t)(_o) >= vm_prelink_stext) && \ | |
269 | ((vm_offset_t)(_o) < vm_prelink_etext)) | |
270 | ||
271 | #define VM_KERNEL_IS_PRELINKINFO(_o) \ | |
272 | (((vm_offset_t)(_o) >= vm_prelink_sinfo) && \ | |
273 | ((vm_offset_t)(_o) < vm_prelink_einfo)) | |
274 | ||
275 | #define VM_KERNEL_IS_KEXT_LINKEDIT(_o) \ | |
276 | (((vm_offset_t)(_o) >= vm_slinkedit) && \ | |
277 | ((vm_offset_t)(_o) < vm_elinkedit)) | |
278 | ||
279 | #define VM_KERNEL_SLIDE(_u) \ | |
280 | ((vm_offset_t)(_u) + vm_kernel_slide) | |
281 | ||
282 | /* | |
283 | * The following macros are to be used when exposing kernel addresses to | |
284 | * userspace via any of the various debug or info facilities that might exist | |
285 | * (e.g. stackshot, proc_info syscall, etc.). It is important to understand | |
286 | * the goal of each macro and choose the right one depending on what you are | |
287 | * trying to do. Misuse of these macros can result in critical data leaks | |
288 | * which in turn lead to all sorts of system vulnerabilities. | |
289 | * | |
290 | * Note that in general the ideal goal is to protect addresses from userspace | |
291 | * in a way that is reversible assuming you know the permutation and/or slide. | |
292 | * | |
293 | * The macros are as follows: | |
294 | * | |
295 | * VM_KERNEL_UNSLIDE: | |
296 | * Use this macro when you are exposing an address to userspace which is | |
297 | * a "static" kernel or kext address (i.e. coming from text or data | |
298 | * sections). These are the addresses which get "slid" via ASLR on kernel | |
299 | * or kext load, and it's precisely the slide value we are trying to | |
300 | * protect from userspace. | |
301 | * | |
302 | * VM_KERNEL_ADDRPERM: | |
303 | * Use this macro when you are exposing an address to userspace which is | |
304 | * coming from the kernel's "heap". Since these adresses are not "loaded" | |
305 | * from anywhere, there is no slide applied and we instead apply the | |
306 | * permutation value to obscure the address. | |
307 | * | |
308 | * VM_KERNEL_UNSLIDE_OR_ADDRPERM: | |
309 | * Use this macro when you are exposing an address to userspace that could | |
310 | * come from either kernel text/data *or* the heap. This is a rare case, | |
311 | * but one that does come up and must be handled correctly. | |
312 | * | |
313 | * Nesting of these macros should be considered invalid. | |
314 | */ | |
315 | #define VM_KERNEL_UNSLIDE(_v) \ | |
316 | ((VM_KERNEL_IS_SLID(_v) || \ | |
317 | VM_KERNEL_IS_KEXT(_v) || \ | |
318 | VM_KERNEL_IS_PRELINKTEXT(_v) || \ | |
319 | VM_KERNEL_IS_PRELINKINFO(_v) || \ | |
320 | VM_KERNEL_IS_KEXT_LINKEDIT(_v)) ? \ | |
321 | (vm_offset_t)(_v) - vm_kernel_slide : \ | |
322 | (vm_offset_t)(_v)) | |
323 | ||
324 | #define VM_KERNEL_ADDRPERM(_v) \ | |
325 | (((vm_offset_t)(_v) == 0) ? \ | |
326 | (vm_offset_t)(0) : \ | |
327 | (vm_offset_t)(_v) + vm_kernel_addrperm) | |
328 | ||
329 | #define VM_KERNEL_UNSLIDE_OR_PERM(_v) \ | |
330 | ((VM_KERNEL_IS_SLID(_v) || \ | |
331 | VM_KERNEL_IS_KEXT(_v) || \ | |
332 | VM_KERNEL_IS_PRELINKTEXT(_v) || \ | |
333 | VM_KERNEL_IS_PRELINKINFO(_v) || \ | |
334 | VM_KERNEL_IS_KEXT_LINKEDIT(_v)) ? \ | |
335 | (vm_offset_t)(_v) - vm_kernel_slide : \ | |
336 | VM_KERNEL_ADDRPERM(_v)) | |
337 | ||
338 | ||
339 | #endif /* XNU_KERNEL_PRIVATE */ | |
340 | ||
341 | extern vm_size_t page_size; | |
342 | extern vm_size_t page_mask; | |
343 | extern int page_shift; | |
344 | ||
345 | /* We need a way to get rid of compiler warnings when we cast from */ | |
346 | /* a 64 bit value to an address (which may be 32 bits or 64-bits). */ | |
347 | /* An intptr_t is used convert the value to the right precision, and */ | |
348 | /* then to an address. This macro is also used to convert addresses */ | |
349 | /* to 32-bit integers, which is a hard failure for a 64-bit kernel */ | |
350 | #include <stdint.h> | |
351 | #ifndef __CAST_DOWN_CHECK | |
352 | #define __CAST_DOWN_CHECK | |
353 | ||
354 | #define CAST_DOWN( type, addr ) \ | |
355 | ( ((type)((uintptr_t) (addr)/(sizeof(type) < sizeof(uintptr_t) ? 0 : 1))) ) | |
356 | ||
357 | #define CAST_DOWN_EXPLICIT( type, addr ) ( ((type)((uintptr_t) (addr))) ) | |
358 | ||
359 | #endif /* __CAST_DOWN_CHECK */ | |
360 | ||
361 | #endif /* ASSEMBLER */ | |
362 | ||
363 | #endif /* KERNEL */ | |
364 | ||
365 | #endif /* _MACH_VM_PARAM_H_ */ |