xref: /xnu-11215.41.3/osfmk/vm/vm_kern.h (revision 33de042d024d46de5ff4e89f2471de6608e37fa4)
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  [email protected]
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:	vm/vm_kern.h
60  *	Author:	Avadis Tevanian, Jr., Michael Wayne Young
61  *	Date:	1985
62  *
63  *	Kernel memory management definitions.
64  */
65 
66 #ifndef _VM_VM_KERN_H_
67 #define _VM_VM_KERN_H_
68 
69 #include <mach/mach_types.h>
70 #include <mach/boolean.h>
71 #include <mach/kern_return.h>
72 #include <mach/vm_types.h>
73 #ifdef XNU_KERNEL_PRIVATE
74 #include <kern/locks.h>
75 #endif /* XNU_KERNEL_PRIVATE */
76 
77 
78 __BEGIN_DECLS
79 
80 #ifdef KERNEL_PRIVATE
81 
82 /*!
83  * @brief
84  * The VM map for the kernel.
85  *
86  * @discussion
87  * This represents the VM-managed portion of the address space.
88  *
89  * The actual address space of the kernel is larger but is managed
90  * by the pmap directly and the VM is oblivious to it. Unmanaged regions
91  * of that kind include the physical aperture or the KASAN shadow map.
92  */
93 extern vm_map_t kernel_map;
94 
95 
96 /*!
97  * @brief
98  * The IPC VM submap.
99  *
100  * @discussion
101  * The IPC submap is used by the Mach IPC subsystem in order to stage
102  * allocations for IPC kmsgs or to throttle debugging interfaces.
103  *
104  * This submap doesn't zero on page fault, and clients must properly
105  * erase memory or risk memory disclosures.
106  */
107 extern vm_map_t ipc_kernel_map;
108 
109 #if XNU_KERNEL_PRIVATE
110 
111 /*!
112  * @brief
113  * The Kext VM submap
114  *
115  * @discussion
116  * This submap is used to support unloading and paging out kexts.
117  */
118 extern vm_map_t g_kext_map __XNU_PRIVATE_EXTERN;
119 
120 #else
121 
122 #pragma mark - the kmem subsystem
123 
124 /*!
125  * @function kmem_alloc()
126  *
127  * @brief
128  * Allocate anonymous wired memory from the kernel map or a kernel submap.
129  *
130  * @discussion
131  * The memory allocated is wired and must be deallocated with @c kmem_free()
132  * or @c mach_vm_deallocate().
133  *
134  * Kernel extensions are discouraged from using this function:
135  * consider @c IOMallocType() instead.
136  *
137  * Per kernel allocation security policies (see doc/allocators/api-basics.md),
138  * this allocation cannot be used to store pure data, @c IOMallocData()
139  * must be used instead.
140  *
141  * @param [in]  map     the map to allocate from, this must be the kernel map
142  *                      or one of its submaps.
143  * @param [out] addrp   a non-NULL pointer used to return the newly allocated
144  *                      memory.
145  * @param [in]  size    the size of the memory to allocate.
146  *
147  * @returns
148  * KERN_SUCCESS         the allocation succeeded,
149  *                      the returned address will be non-zero.
150  * KERN_INVALID_ARGUMENT
151  *                      the allocation failed because @c size was 0.
152  * KERN_NO_SPACE        the allocation failed because the specified map
153  *                      is out of address space.
154  * KERN_RESOURCE_SHORTAGE
155  *                      the allocation failed because the kernel
156  *                      was out of pages and couldn't satisfy the demand.
157  */
158 extern kern_return_t kmem_alloc(
159 	vm_map_t                map,
160 	vm_offset_t            *addrp,
161 	vm_size_t               size);
162 
163 
164 /*!
165  * @function kmem_alloc_pageable()
166  *
167  * @brief
168  * Allocate anonymous pageable memory from the kernel map or a kernel submap.
169  *
170  * @discussion
171  * This call is equivalent to @c mach_vm_allocate(map, addr, size, VM_FLAGS_ANYWHERE)
172  * which should be preferred to this legacy call.
173  *
174  * The memory allocated is wired and must be deallocated with @c kmem_free()
175  * or @c mach_vm_deallocate().
176  *
177  * Per kernel allocation security policies (see doc/allocators/api-basics.md),
178  * this allocation must not be used to store kernel pointers.
179  *
180  * @param [in]  map     the map to allocate from, this must be the kernel map
181  *                      or one of its submaps.
182  * @param [out] addrp   a non-NULL pointer used to return the newly allocated
183  *                      memory.
184  * @param [in]  size    the size of the memory to allocate.
185  *
186  * @returns
187  * KERN_SUCCESS         the allocation succeeded,
188  *                      the returned address will be non-zero.
189  * KERN_NO_SPACE        the allocation failed because the specified map
190  *                      is out of address space.
191  */
192 extern kern_return_t kmem_alloc_pageable(
193 	vm_map_t                map,
194 	vm_offset_t            *addrp,
195 	vm_size_t               size);
196 
197 
198 /*!
199  * @function kmem_alloc_kobject()
200  *
201  * @brief
202  * Allocate kobject wired memory from the kernel map or a kernel submap.
203  *
204  * @discussion
205  * The memory allocated is wired and must be deallocated with @c kmem_free()
206  * or @c mach_vm_deallocate().
207  *
208  * Memory allocated by this function is added to the VM kernel object rather
209  * than a new VM object. This makes it possible to avoid the cost of that extra
210  * VM object, but forgoes any advanced VM features such as unwiring memory, or
211  * sharing it (whether it be to an IOMMU or another address space).
212  *
213  * Kernel extensions are discouraged from using this function:
214  * consider @c IOMallocType() instead.
215  *
216  * Per kernel allocation security policies (see doc/allocators/api-basics.md),
217  * this allocation cannot be used to store pure data, @c IOMallocData()
218  * must be used instead.
219  *
220  * @param [in]  map     the map to allocate from, this must be the kernel map
221  *                      or one of its submaps.
222  * @param [out] addrp   a non-NULL pointer used to return the newly allocated
223  *                      memory.
224  * @param [in]  size    the size of the memory to allocate.
225  *
226  * @returns
227  * KERN_SUCCESS         the allocation succeeded,
228  *                      the returned address will be non-zero.
229  * KERN_INVALID_ARGUMENT
230  *                      the allocation failed because @c size was 0.
231  * KERN_NO_SPACE        the allocation failed because the specified map
232  *                      is out of address space.
233  * KERN_RESOURCE_SHORTAGE
234  *                      the allocation failed because the kernel
235  *                      was out of pages and couldn't satisfy the demand.
236  */
237 extern kern_return_t kmem_alloc_kobject(
238 	vm_map_t                map,
239 	vm_offset_t            *addrp,
240 	vm_size_t               size);
241 
242 /*!
243  * @function kmem_free()
244  *
245  * @brief
246  * Deallocates a range of memory.
247  *
248  * @discussion
249  * This call is roughly equivalent to @c mach_vm_deallocate(map, addr, size).
250  *
251  * It is possible to deallocate an allocation in several steps provided that
252  * the deallocations form a partition of the range allocated with one of
253  * the functions from the @c kmem_alloc*() family.
254  *
255  * Unlike @c mach_vm_deallocate(), this function will panic for invalid
256  * arguments, in particular for invalid sizes or a @c map argument
257  * not matching the one used for allocating.
258  *
259  * @param map           the map to allocate from, this must be the kernel map
260  *                      or one of its submaps.
261  * @param addr          the address to deallocate.
262  * @param size          the size of the address to deallocate.
263  */
264 extern void kmem_free(
265 	vm_map_t                map,
266 	vm_offset_t             addr,
267 	vm_size_t               size);
268 
269 #endif /* !XNU_KERNEL_PRIVATE */
270 #endif /* KERNEL_PRIVATE */
271 
272 #pragma mark - kernel address obfuscation / hashing for logging
273 
274 /*!
275  * @function vm_kernel_addrhide()
276  *
277  * @brief
278  * Unslides a kernel pointer.
279  *
280  * @discussion
281  * This is exporting the VM_KERNEL_ADDRHIDE() functionality to kernel
282  * extensions.
283  *
284  * @param addr          the kernel address to unslide
285  * @param hide_addr     the unslid value of @c addr if it was part of a slid
286  *                      region of the kernel.
287  *
288  *                      0 on release kernels if @c addr is not part of a slid
289  *                      region of the kernel.
290  *
291  *                      @c addr on development kernels if @c addr is not part of
292  *                      a slid region of the kernel.
293  */
294 extern void vm_kernel_addrhide(
295 	vm_offset_t             addr,
296 	vm_offset_t            *hide_addr);
297 
298 
299 /*!
300  * @function vm_kernel_addrperm_external()
301  *
302  * @brief
303  * Unslides or "permutate" a kernel pointer.
304  *
305  * @discussion
306  * This is exporting the VM_KERNEL_ADDRPERM() functionality to kernel
307  * extensions.
308  *
309  * The level of "hiding" of heap kernel pointers done by this function is
310  * insufficient. Using @c vm_kernel_addrhash() is preferred when possible.
311  *
312  * Note that this function might cause lazy allocation to preserve the floating
313  * point register state on Intel and is generally unsafe to call under lock.
314  *
315  * @param addr          the kernel address to unslide
316  * @param perm_addr     the unslid value of @c addr if it was part of a slid
317  *                      region of the kernel.
318  */
319 extern void vm_kernel_addrperm_external(
320 	vm_offset_t             addr,
321 	vm_offset_t            *perm_addr);
322 
323 
324 /*!
325  * @function vm_kernel_unslide_or_perm_external()
326  *
327  * @brief
328  * Equivalent to vm_kernel_addrperm_external().
329  */
330 extern void vm_kernel_unslide_or_perm_external(
331 	vm_offset_t             addr,
332 	vm_offset_t            *perm_addr);
333 
334 #if !XNU_KERNEL_PRIVATE
335 
336 /*!
337  * @function vm_kernel_addrhash()
338  *
339  * @brief
340  * Unslides or hashes a kernel pointer.
341  *
342  * @discussion
343  * This is exporting the VM_KERNEL_ADDRHASH() functionality to kernel
344  * extensions.
345  *
346  * @param addr          the kernel address to unslide
347  * @returns             the unslid value of @c addr if it was part of a slid
348  *                      region of the kernel.
349  *
350  *                      a hashed value of @c addr otherwise.
351  */
352 extern vm_offset_t vm_kernel_addrhash(
353 	vm_offset_t             addr);
354 
355 #else /* XNU_KERNEL_PRIVATE */
356 #pragma GCC visibility push(hidden)
357 
358 /*!
359  * @brief
360  * The quantity @c vm_kernel_addrhide() uses to slide heap pointers.
361  */
362 extern vm_offset_t vm_kernel_addrperm_ext;
363 
364 
365 /*!
366  * @brief
367  * The quantity @c vm_kernel_addrhash() uses to hash heap pointers inside XNU.
368  */
369 extern uint64_t vm_kernel_addrhash_salt;
370 
371 
372 /*!
373  * @brief
374  * The quantity @c vm_kernel_addrhash() uses to hash heap pointers for kernel
375  * extensions.
376  */
377 extern uint64_t vm_kernel_addrhash_salt_ext;
378 
379 
380 /*!
381  * @function vm_kernel_addrhash_internal()
382  *
383  * @brief
384  * Internal function used to implement the @c vm_kernel_addrhash*() functions.
385  */
386 extern vm_offset_t vm_kernel_addrhash_internal(
387 	vm_offset_t             addr,
388 	uint64_t                salt);
389 
390 
391 /*!
392  * @function vm_kernel_addrhash()
393  *
394  * @brief
395  * Unslides or hashes a kernel pointer.
396  *
397  * @discussion
398  * This is exporting the VM_KERNEL_ADDRHASH() functionality to kernel
399  * extensions.
400  *
401  * @param addr          the kernel address to unslide
402  * @returns             the unslid value of @c addr if it was part of a slid
403  *                      region of the kernel.
404  *
405  *                      a hashed value of @c addr otherwise.
406  */
407 static inline vm_offset_t
vm_kernel_addrhash(vm_offset_t addr)408 vm_kernel_addrhash(vm_offset_t addr)
409 {
410 	return vm_kernel_addrhash_internal(addr, vm_kernel_addrhash_salt);
411 }
412 
413 #pragma GCC visibility pop
414 #endif /* XNU_KERNEL_PRIVATE */
415 #ifdef KERNEL_PRIVATE
416 
417 #pragma mark - kern allocation names
418 
419 /*!
420  * @typedef kern_allocation_name_t
421  *
422  * @brief
423  * This type is used to perform different kinds of accounting
424  * in the Mach VM subsystem.
425  */
426 #ifdef XNU_KERNEL_PRIVATE
427 typedef struct vm_allocation_site       kern_allocation_name;
428 typedef kern_allocation_name           *kern_allocation_name_t;
429 #else
430 typedef struct kern_allocation_name    *kern_allocation_name_t;
431 #endif
432 
433 
434 /*!
435  * @brief
436  * Allocate a kernel allocation accounting structure.
437  *
438  * @param name          a symbolic name for this accounting group.
439  * @param suballocs     how many subtotals will be used for accounting.
440  *                      see @c kern_allocation_update_subtotal().
441  * @returns             the new allocated accounting structure,
442  *                      this function never fails.
443  */
444 extern kern_allocation_name_t kern_allocation_name_allocate(
445 	const char             *name,
446 	uint16_t                suballocs);
447 
448 /*!
449  * @brief
450  * Frees a kernel allocation accounting structure.
451  *
452  * @param allocation    a structure made with @c kern_allocation_name_allocate().
453  */
454 extern void kern_allocation_name_release(
455 	kern_allocation_name_t  allocation);
456 
457 
458 /*!
459  * @brief
460  * Returns the name associated with an allocation accounting structure.
461  *
462  * @returns             the name associated with that accounting structure,
463  *                      when made with @c kern_allocation_name_allocate().
464  */
465 extern const char *kern_allocation_get_name(
466 	kern_allocation_name_t  allocation);
467 
468 #endif  /* KERNEL_PRIVATE */
469 
470 __END_DECLS
471 
472 #endif  /* _VM_VM_KERN_H_ */
473