xref: /xnu-11215.81.4/iokit/IOKit/IOLib.h (revision d4514f0bc1d3f944c22d92e68b646ac3fb40d452)
1 /*
2  * Copyright (c) 1998-2016 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  * Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
30  *
31  * HISTORY
32  *
33  */
34 
35 #ifndef __IOKIT_IOLIB_H
36 #define __IOKIT_IOLIB_H
37 
38 #ifndef KERNEL
39 #error IOLib.h is for kernel use only
40 #endif
41 
42 #include <stdarg.h>
43 #include <sys/cdefs.h>
44 #include <os/overflow.h>
45 #include <os/alloc_util.h>
46 
47 #include <sys/appleapiopts.h>
48 
49 #include <IOKit/system.h>
50 
51 #include <IOKit/IOReturn.h>
52 #include <IOKit/IOTypes.h>
53 #include <IOKit/IOLocks.h>
54 
55 #include <libkern/OSAtomic.h>
56 
57 __BEGIN_DECLS
58 
59 #include <kern/thread_call.h>
60 #include <kern/clock.h>
61 #ifdef KERNEL_PRIVATE
62 #include <kern/kalloc.h>
63 #include <kern/assert.h>
64 #endif
65 
66 /*
67  * min/max macros.
68  */
69 
70 #define min(a, b) ((a) < (b) ? (a) : (b))
71 #define max(a, b) ((a) > (b) ? (a) : (b))
72 
73 /*
74  * Safe functions to compute array sizes (saturate to a size that can't be
75  * allocated ever and will cause the allocation to return NULL always).
76  */
77 
78 static inline vm_size_t
IOMallocArraySize(vm_size_t hdr_size,vm_size_t elem_size,vm_size_t elem_count)79 IOMallocArraySize(vm_size_t hdr_size, vm_size_t elem_size, vm_size_t elem_count)
80 {
81 	/* IOMalloc() will reject this size before even asking the VM  */
82 	const vm_size_t limit = 1ull << (8 * sizeof(vm_size_t) - 1);
83 	vm_size_t s = hdr_size;
84 
85 	if (os_mul_and_add_overflow(elem_size, elem_count, s, &s) || (s & limit)) {
86 		return limit;
87 	}
88 	return s;
89 }
90 
91 #define IOKIT_TYPE_IS_COMPATIBLE_PTR(ptr, type) \
92 	(__builtin_xnu_types_compatible(os_get_pointee_type(ptr), type) ||   \
93 	    __builtin_xnu_types_compatible(os_get_pointee_type(ptr), void))  \
94 
95 #define IOKIT_TYPE_ASSERT_COMPATIBLE_POINTER(ptr, type) \
96 	_Static_assert(IOKIT_TYPE_IS_COMPATIBLE_PTR(ptr, type), \
97 	    "Pointer type is not compatible with specified type")
98 
99 /*
100  * These are opaque to the user.
101  */
102 typedef thread_t IOThread;
103 typedef void (*IOThreadFunc)(void *argument);
104 
105 /*
106  * Memory allocation functions.
107  */
108 #if XNU_KERNEL_PRIVATE
109 
110 /*
111  * IOMalloc_internal allocates memory from the specifed kalloc heap, which can be:
112  * - KHEAP_DATA_BUFFERS: Should be used for data buffers
113  * - KHEAP_DEFAULT: Should be used for allocations that aren't data buffers.
114  *
115  * For more details on kalloc_heaps see kalloc.h
116  */
117 
118 extern void *
119 IOMalloc_internal(
120 	struct kalloc_heap * kalloc_heap_cfg,
121 	vm_size_t            size,
122 	zalloc_flags_t       flags);
123 
124 __attribute__((alloc_size(2)))
125 static inline void *
__IOMalloc_internal(struct kalloc_heap * kalloc_heap_cfg,vm_size_t size,zalloc_flags_t flags)126 __IOMalloc_internal(
127 	struct kalloc_heap * kalloc_heap_cfg,
128 	vm_size_t            size,
129 	zalloc_flags_t       flags)
130 {
131 	void *addr = (IOMalloc_internal)(kalloc_heap_cfg, size, flags);
132 	if (flags & Z_NOFAIL) {
133 		__builtin_assume(addr != NULL);
134 	}
135 	return addr;
136 }
137 
138 #define IOMalloc(size)     __IOMalloc_internal(KHEAP_DEFAULT, size, Z_WAITOK)
139 #define IOMallocZero(size) __IOMalloc_internal(KHEAP_DEFAULT, size, Z_ZERO)
140 
141 #else /* XNU_KERNEL_PRIVATE */
142 
143 /*! @function IOMalloc
144  *   @abstract Allocates general purpose, wired memory in the kernel map.
145  *   @discussion This is a general purpose utility to allocate memory in the kernel. There are no alignment guarantees given on the returned memory, and alignment may vary depending on the kernel configuration. This function may block and so should not be called from interrupt level or while a simple lock is held.
146  *   @param size Size of the memory requested.
147  *   @result Pointer to the allocated memory, or zero on failure. */
148 
149 void * IOMalloc(vm_size_t size)      __attribute__((alloc_size(1)));
150 void * IOMallocZero(vm_size_t size)  __attribute__((alloc_size(1)));
151 
152 /*! @function IOFree
153  *   @abstract Frees memory allocated with IOMalloc.
154  *   @discussion This function frees memory allocated with IOMalloc, it may block and so should not be called from interrupt level or while a simple lock is held.
155  *   @param address Pointer to the allocated memory. Must be identical to result
156  *   @of a prior IOMalloc.
157  *   @param size Size of the memory allocated. Must be identical to size of
158  *   @the corresponding IOMalloc */
159 
160 #endif /* XNU_KERNEL_PRIVATE */
161 
162 #if XNU_KERNEL_PRIVATE
163 
164 /*
165  * IOFree_internal allows specifying the kalloc heap to free the allocation
166  * to
167  */
168 
169 extern void
170 IOFree_internal(
171 	struct kalloc_heap * kalloc_heap_cfg,
172 	void               * inAddress,
173 	vm_size_t            size);
174 
175 #endif /* XNU_KERNEL_PRIVATE */
176 
177 void   IOFree(void * address, vm_size_t size);
178 
179 /*! @function IOMallocAligned
180  *   @abstract Allocates wired memory in the kernel map, with an alignment restriction.
181  *   @discussion This is a utility to allocate memory in the kernel, with an alignment restriction which is specified as a byte count. This function may block and so should not be called from interrupt level or while a simple lock is held.
182  *   @param size Size of the memory requested.
183  *   @param alignment Byte count of the alignment for the memory. For example, pass 256 to get memory allocated at an address with bit 0-7 zero.
184  *   @result Pointer to the allocated memory, or zero on failure. */
185 
186 #if XNU_KERNEL_PRIVATE
187 
188 extern void *
189 IOMallocAligned_internal(
190 	struct kalloc_heap * kalloc_heap_cfg,
191 	vm_size_t            size,
192 	vm_size_t            alignment,
193 	zalloc_flags_t       flags);
194 
195 __attribute__((alloc_size(2)))
196 static inline void *
__IOMallocAligned_internal(struct kalloc_heap * kalloc_heap_cfg,vm_size_t size,vm_size_t alignment,zalloc_flags_t flags)197 __IOMallocAligned_internal(
198 	struct kalloc_heap * kalloc_heap_cfg,
199 	vm_size_t            size,
200 	vm_size_t            alignment,
201 	zalloc_flags_t       flags)
202 {
203 	void *addr = (IOMallocAligned_internal)(kalloc_heap_cfg, size, alignment, flags);
204 	if (flags & Z_NOFAIL) {
205 		__builtin_assume(addr != NULL);
206 	}
207 	return addr;
208 }
209 
210 #define IOMallocAligned(size, alignment) \
211 	__IOMallocAligned_internal(KHEAP_DATA_BUFFERS, size, alignment, Z_WAITOK)
212 
213 #else /* XNU_KERNEL_PRIVATE */
214 
215 void * IOMallocAligned(vm_size_t size, vm_offset_t alignment) __attribute__((alloc_size(1)));
216 
217 #endif /* !XNU_KERNEL_PRIVATE */
218 
219 
220 /*! @function IOFreeAligned
221  *   @abstract Frees memory allocated with IOMallocAligned.
222  *   @discussion This function frees memory allocated with IOMallocAligned, it may block and so should not be called from interrupt level or while a simple lock is held.
223  *   @param address Pointer to the allocated memory.
224  *   @param size Size of the memory allocated. */
225 
226 #if XNU_KERNEL_PRIVATE
227 
228 /*
229  * IOFreeAligned_internal allows specifying the kalloc heap to free the
230  * allocation to
231  */
232 
233 extern void
234 IOFreeAligned_internal(
235 	struct kalloc_heap * kalloc_heap_cfg,
236 	void               * address,
237 	vm_size_t            size);
238 
239 #endif /* XNU_KERNEL_PRIVATE */
240 
241 void   IOFreeAligned(void * address, vm_size_t size);
242 
243 /*! @function IOMallocContiguous
244  *   @abstract Deprecated - use IOBufferMemoryDescriptor. Allocates wired memory in the kernel map, with an alignment restriction and physically contiguous.
245  *   @discussion This is a utility to allocate memory in the kernel, with an alignment restriction which is specified as a byte count, and will allocate only physically contiguous memory. The request may fail if memory is fragmented, and may cause large amounts of paging activity. This function may block and so should not be called from interrupt level or while a simple lock is held.
246  *   @param size Size of the memory requested.
247  *   @param alignment Byte count of the alignment for the memory. For example, pass 256 to get memory allocated at an address with bits 0-7 zero.
248  *   @param physicalAddress IOMallocContiguous returns the physical address of the allocated memory here, if physicalAddress is a non-zero pointer. The physicalAddress argument is deprecated and should be passed as NULL. To obtain the physical address for a memory buffer, use the IODMACommand class in conjunction with the IOMemoryDescriptor or IOBufferMemoryDescriptor classes.
249  *   @result Virtual address of the allocated memory, or zero on failure. */
250 
251 void * IOMallocContiguous(vm_size_t size, vm_size_t alignment,
252     IOPhysicalAddress * physicalAddress) __attribute__((deprecated)) __attribute__((alloc_size(1)));
253 
254 /*! @function IOFreeContiguous
255  *   @abstract Deprecated - use IOBufferMemoryDescriptor. Frees memory allocated with IOMallocContiguous.
256  *   @discussion This function frees memory allocated with IOMallocContiguous, it may block and so should not be called from interrupt level or while a simple lock is held.
257  *   @param address Virtual address of the allocated memory.
258  *   @param size Size of the memory allocated. */
259 
260 void   IOFreeContiguous(void * address, vm_size_t size) __attribute__((deprecated));
261 
262 
263 /*! @function IOMallocPageable
264  *   @abstract Allocates pageable memory in the kernel map.
265  *   @discussion This is a utility to allocate pageable memory in the kernel. This function may block and so should not be called from interrupt level or while a simple lock is held.
266  *   @param size Size of the memory requested.
267  *   @param alignment Byte count of the alignment for the memory. For example, pass 256 to get memory allocated at an address with bits 0-7 zero.
268  *   @result Pointer to the allocated memory, or zero on failure. */
269 
270 void * IOMallocPageable(vm_size_t size, vm_size_t alignment) __attribute__((alloc_size(1)));
271 
272 /*! @function IOMallocPageableZero
273  *   @abstract Allocates pageable, zeroed memory in the kernel map.
274  *   @discussion Same as IOMallocPageable but guarantees the returned memory will be zeroed.
275  *   @param size Size of the memory requested.
276  *   @param alignment Byte count of the alignment for the memory. For example, pass 256 to get memory allocated at an address with bits 0-7 zero.
277  *   @result Pointer to the allocated memory, or zero on failure. */
278 
279 void * IOMallocPageableZero(vm_size_t size, vm_size_t alignment) __attribute__((alloc_size(1)));
280 
281 /*! @function IOFreePageable
282  *   @abstract Frees memory allocated with IOMallocPageable.
283  *   @discussion This function frees memory allocated with IOMallocPageable, it may block and so should not be called from interrupt level or while a simple lock is held.
284  *   @param address Virtual address of the allocated memory.
285  *   @param size Size of the memory allocated. */
286 
287 void IOFreePageable(void * address, vm_size_t size);
288 
289 #if XNU_KERNEL_PRIVATE
290 
291 #define IOMallocData(size)     __IOMalloc_internal(KHEAP_DATA_BUFFERS, size, Z_WAITOK)
292 #define IOMallocZeroData(size) __IOMalloc_internal(KHEAP_DATA_BUFFERS, size, Z_ZERO)
293 
294 #else /* XNU_KERNEL_PRIVATE */
295 
296 /*! @function IOMallocData
297  *   @abstract Allocates wired memory in the kernel map, from a separate section meant for pure data.
298  *   @discussion Same as IOMalloc except that this function should be used for allocating pure data.
299  *   @param size Size of the memory requested.
300  *   @result Pointer to the allocated memory, or zero on failure. */
301 void * IOMallocData(vm_size_t size) __attribute__((alloc_size(1)));
302 
303 /*! @function IOMallocZeroData
304  *   @abstract Allocates wired memory in the kernel map, from a separate section meant for pure data bytes that don't contain pointers.
305  *   @discussion Same as IOMallocData except that the memory returned is zeroed.
306  *   @param size Size of the memory requested.
307  *   @result Pointer to the allocated memory, or zero on failure. */
308 void * IOMallocZeroData(vm_size_t size) __attribute__((alloc_size(1)));
309 
310 #endif /* !XNU_KERNEL_PRIVATE */
311 
312 /*! @function IOFreeData
313  *   @abstract Frees memory allocated with IOMallocData or IOMallocZeroData.
314  *   @discussion This function frees memory allocated with IOMallocData/IOMallocZeroData, it may block and so should not be called from interrupt level or while a simple lock is held.
315  *   @param address Virtual address of the allocated memory. Passing NULL here is acceptable.
316  *   @param size Size of the memory allocated. It is acceptable to pass 0 size for a NULL address. */
317 void IOFreeData(void * address, vm_size_t size);
318 
319 #define IONewData(type, count) \
320 	((type *)IOMallocData(IOMallocArraySize(0, sizeof(type), count)))
321 
322 #define IONewZeroData(type, count) \
323 	((type *)IOMallocZeroData(IOMallocArraySize(0, sizeof(type), count)))
324 
325 #define IODeleteData(ptr, type, count) ({ \
326 	vm_size_t  __count = (vm_size_t)(count);             \
327 	IOKIT_TYPE_ASSERT_COMPATIBLE_POINTER(ptr, type);     \
328 	IOFreeData(os_ptr_load_and_erase(ptr),               \
329 	    IOMallocArraySize(0, sizeof(type), __count));    \
330 })
331 
332 #if KERNEL_PRIVATE
333 
334 /*
335  * Typed memory allocation macros. All may block.
336  */
337 
338 /*
339  * Use IOMallocType to allocate a single typed object.
340  *
341  * If you use IONew with count 1, please use IOMallocType
342  * instead. For arrays of typed objects use IONew.
343  *
344  * IOMallocType returns zeroed memory. It will not
345  * fail to allocate memory for sizes less than:
346  * - 16K (macos)
347  * - 8K  (embedded 32-bit)
348  * - 32K (embedded 64-bit)
349  */
350 #define IOMallocType(type) ({                           \
351 	static _KALLOC_TYPE_DEFINE(kt_view_var, type,       \
352 	    KT_SHARED_ACCT);                                \
353 	(type *) IOMallocTypeImpl(kt_view_var);             \
354 })
355 
356 #define IOFreeType(elem, type) ({                       \
357 	static _KALLOC_TYPE_DEFINE(kt_view_var, type,       \
358 	   KT_SHARED_ACCT);                                 \
359 	IOFREETYPE_ASSERT_COMPATIBLE_POINTER(elem, type);   \
360 	IOFreeTypeImpl(kt_view_var,                         \
361 	    os_ptr_load_and_erase(elem));                   \
362 })
363 
364 /*
365  * Versioning macro for the typed allocator APIs.
366  */
367 #define IO_TYPED_ALLOCATOR_VERSION    1
368 
369 #endif /* KERNEL_PRIVATE */
370 
371 /*
372  * IONew/IONewZero/IODelete/IOSafeDeleteNULL
373  *
374  * Those functions come in 2 variants:
375  *
376  * 1. IONew(element_type, count)
377  *    IONewZero(element_type, count)
378  *    IODelete(ptr, element_type, count)
379  *    IOSafeDeleteNULL(ptr, element_type, count)
380  *
381  *    Those allocate/free arrays of `count` elements of type `element_type`.
382  *
383  * 2. IONew(hdr_type, element_type, count)
384  *    IONewZero(hdr_type, element_type, count)
385  *    IODelete(ptr, hdr_type, element_type, count)
386  *    IOSafeDeleteNULL(ptr, hdr_type, element_type, count)
387  *
388  *    Those allocate/free arrays with `count` elements of type `element_type`,
389  *    prefixed with a header of type `hdr_type`, like this:
390  *
391  * Those perform safe math with the sizes, checking for overflow.
392  * An overflow in the sizes will cause the allocation to return NULL.
393  */
394 #define IONew(...)             __IOKIT_DISPATCH(IONew, ##__VA_ARGS__)
395 #define IONewZero(...)         __IOKIT_DISPATCH(IONewZero, ##__VA_ARGS__)
396 #define IODelete(...)          __IOKIT_DISPATCH(IODelete, ##__VA_ARGS__)
397 #if KERNEL_PRIVATE
398 #define IOSafeDeleteNULL(...)  __IOKIT_DISPATCH(IODelete, ##__VA_ARGS__)
399 #else
400 #define IOSafeDeleteNULL(...)  __IOKIT_DISPATCH(IOSafeDeleteNULL, ##__VA_ARGS__)
401 #endif
402 
403 #if KERNEL_PRIVATE
404 #define IONew_2(e_ty, count) ({                                             \
405 	static KALLOC_TYPE_VAR_DEFINE(kt_view_var, e_ty, KT_SHARED_ACCT);       \
406 	(e_ty *) IOMallocTypeVarImpl(kt_view_var,                               \
407 	    IOMallocArraySize(0, sizeof(e_ty), count));                         \
408 })
409 
410 #define IONew_3(h_ty, e_ty, count) ({                                       \
411 	static KALLOC_TYPE_VAR_DEFINE(kt_view_var, h_ty, e_ty, KT_SHARED_ACCT); \
412 	(h_ty *) IOMallocTypeVarImpl(kt_view_var,                               \
413 	    IOMallocArraySize(sizeof(h_ty), sizeof(e_ty), count));              \
414 })
415 
416 #define IONewZero_2(e_ty, count) \
417 	IONew_2(e_ty, count)
418 
419 #define IONewZero_3(h_ty, e_ty, count) \
420 	IONew_3(h_ty, e_ty, count)
421 
422 #else /* KERNEL_PRIVATE */
423 #define IONew_2(e_ty, count) \
424 	((e_ty *)IOMalloc(IOMallocArraySize(0, sizeof(e_ty), count)))
425 
426 #define IONew_3(h_ty, e_ty, count) \
427 	((h_ty *)IOMalloc(IOMallocArraySize(sizeof(h_ty), sizeof(e_ty), count)))
428 
429 #define IONewZero_2(e_ty, count) \
430 	((e_ty *)IOMallocZero(IOMallocArraySize(0, sizeof(e_ty), count)))
431 
432 #define IONewZero_3(h_ty, e_ty, count) \
433 	((h_ty *)IOMallocZero(IOMallocArraySize(sizeof(h_ty), sizeof(e_ty), count)))
434 #endif /* !KERNEL_PRIVATE */
435 
436 #if KERNEL_PRIVATE
437 #define IODelete_3(ptr, e_ty, count) ({                                     \
438 	vm_size_t __s = IOMallocArraySize(0, sizeof(e_ty), count);              \
439 	KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(ptr, e_ty);                       \
440 	static KALLOC_TYPE_VAR_DEFINE(kt_view_var, e_ty, KT_SHARED_ACCT);       \
441 	IOFreeTypeVarImpl(kt_view_var, os_ptr_load_and_erase(ptr), __s);        \
442 })
443 
444 #define IODelete_4(ptr, h_ty, e_ty, count) ({                               \
445 	vm_size_t __s = IOMallocArraySize(sizeof(h_ty), sizeof(e_ty), count);   \
446 	KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(ptr, h_ty);                       \
447 	static KALLOC_TYPE_VAR_DEFINE(kt_view_var, h_ty, e_ty, KT_SHARED_ACCT); \
448 	IOFreeTypeVarImpl(kt_view_var, os_ptr_load_and_erase(ptr), __s);        \
449 })
450 
451 #else /* KERNEL_PRIVATE */
452 #define IODelete_3(ptr, e_ty, count) \
453 	IOFree(ptr, IOMallocArraySize(0, sizeof(e_ty), count));
454 
455 #define IODelete_4(ptr, h_ty, e_ty, count) \
456 	IOFree(ptr, IOMallocArraySize(sizeof(h_ty), sizeof(e_ty), count));
457 
458 #define IOSafeDeleteNULL_3(ptr, e_ty, count)  ({                           \
459 	vm_size_t __s = IOMallocArraySize(0, sizeof(e_ty), count);             \
460 	IOFree(os_ptr_load_and_erase(ptr), __s);                               \
461 })
462 
463 #define IOSafeDeleteNULL_4(ptr, h_ty, e_ty, count)  ({                     \
464 	vm_size_t __s = IOMallocArraySize(sizeof(h_ty), sizeof(e_ty), count);  \
465 	IOFree(os_ptr_load_and_erase(ptr), __s);                               \
466 })
467 #endif /* !KERNEL_PRIVATE */
468 
469 /////////////////////////////////////////////////////////////////////////////
470 //
471 //
472 //	These functions are now implemented in IOMapper.cpp
473 //
474 //
475 /////////////////////////////////////////////////////////////////////////////
476 
477 /*! @function IOMappedRead8
478  *   @abstract Read one byte from the desired "Physical" IOSpace address.
479  *   @discussion Read one byte from the desired "Physical" IOSpace address.  This function allows the developer to read an address returned from any memory descriptor's getPhysicalSegment routine.  It can then be used by segmenting a physical page slightly to tag the physical page with its kernel space virtual address.
480  *   @param address The desired address, as returned by IOMemoryDescriptor::getPhysicalSegment.
481  *   @result Data contained at that location */
482 
483 UInt8 IOMappedRead8(IOPhysicalAddress address);
484 
485 /*! @function IOMappedRead16
486  *   @abstract Read two bytes from the desired "Physical" IOSpace address.
487  *   @discussion Read two bytes from the desired "Physical" IOSpace address.  This function allows the developer to read an address returned from any memory descriptor's getPhysicalSegment routine.  It can then be used by segmenting a physical page slightly to tag the physical page with its kernel space virtual address.
488  *   @param address The desired address, as returned by IOMemoryDescriptor::getPhysicalSegment.
489  *   @result Data contained at that location */
490 
491 UInt16 IOMappedRead16(IOPhysicalAddress address);
492 
493 /*! @function IOMappedRead32
494  *   @abstract Read four bytes from the desired "Physical" IOSpace address.
495  *   @discussion Read four bytes from the desired "Physical" IOSpace address.  This function allows the developer to read an address returned from any memory descriptor's getPhysicalSegment routine.  It can then be used by segmenting a physical page slightly to tag the physical page with its kernel space virtual address.
496  *   @param address The desired address, as returned by IOMemoryDescriptor::getPhysicalSegment.
497  *   @result Data contained at that location */
498 
499 UInt32 IOMappedRead32(IOPhysicalAddress address);
500 
501 /*! @function IOMappedRead64
502  *   @abstract Read eight bytes from the desired "Physical" IOSpace address.
503  *   @discussion Read eight bytes from the desired "Physical" IOSpace address.  This function allows the developer to read an address returned from any memory descriptor's getPhysicalSegment routine.  It can then be used by segmenting a physical page slightly to tag the physical page with its kernel space virtual address.
504  *   @param address The desired address, as returned by IOMemoryDescriptor::getPhysicalSegment.
505  *   @result Data contained at that location */
506 
507 UInt64 IOMappedRead64(IOPhysicalAddress address);
508 
509 /*! @function IOMappedWrite8
510  *   @abstract Write one byte to the desired "Physical" IOSpace address.
511  *   @discussion Write one byte to the desired "Physical" IOSpace address.  This function allows the developer to write to an address returned from any memory descriptor's getPhysicalSegment routine.
512  *   @param address The desired address, as returned by IOMemoryDescriptor::getPhysicalSegment.
513  *   @param value Data to be writen to the desired location */
514 
515 void IOMappedWrite8(IOPhysicalAddress address, UInt8 value);
516 
517 /*! @function IOMappedWrite16
518  *   @abstract Write two bytes to the desired "Physical" IOSpace address.
519  *   @discussion Write two bytes to the desired "Physical" IOSpace address.  This function allows the developer to write to an address returned from any memory descriptor's getPhysicalSegment routine.
520  *   @param address The desired address, as returned by IOMemoryDescriptor::getPhysicalSegment.
521  *   @param value Data to be writen to the desired location */
522 
523 void IOMappedWrite16(IOPhysicalAddress address, UInt16 value);
524 
525 /*! @function IOMappedWrite32
526  *   @abstract Write four bytes to the desired "Physical" IOSpace address.
527  *   @discussion Write four bytes to the desired "Physical" IOSpace address.  This function allows the developer to write to an address returned from any memory descriptor's getPhysicalSegment routine.
528  *   @param address The desired address, as returned by IOMemoryDescriptor::getPhysicalSegment.
529  *   @param value Data to be writen to the desired location */
530 
531 void IOMappedWrite32(IOPhysicalAddress address, UInt32 value);
532 
533 /*! @function IOMappedWrite64
534  *   @abstract Write eight bytes to the desired "Physical" IOSpace address.
535  *   @discussion Write eight bytes to the desired "Physical" IOSpace address.  This function allows the developer to write to an address returned from any memory descriptor's getPhysicalSegment routine.
536  *   @param address The desired address, as returned by IOMemoryDescriptor::getPhysicalSegment.
537  *   @param value Data to be writen to the desired location */
538 
539 void IOMappedWrite64(IOPhysicalAddress address, UInt64 value);
540 
541 /* This function is deprecated. Cache settings may be set for allocated memory with the IOBufferMemoryDescriptor api. */
542 
543 IOReturn IOSetProcessorCacheMode( task_t task, IOVirtualAddress address,
544     IOByteCount length, IOOptionBits cacheMode ) __attribute__((deprecated));
545 
546 /*! @function IOFlushProcessorCache
547  *   @abstract Flushes the processor cache for mapped memory.
548  *   @discussion This function flushes the processor cache of an already mapped memory range. Note in most cases it is preferable to use IOMemoryDescriptor::prepare and complete to manage cache coherency since they are aware of the architecture's requirements. Flushing the processor cache is not required for coherency in most situations.
549  *   @param task Task the memory is mapped into.
550  *   @param address Virtual address of the memory.
551  *   @param length Length of the range to set.
552  *   @result An IOReturn code. */
553 
554 IOReturn IOFlushProcessorCache( task_t task, IOVirtualAddress address,
555     IOByteCount length );
556 
557 /*! @function IOThreadSelf
558  *   @abstract Returns the osfmk identifier for the currently running thread.
559  *   @discussion This function returns the current thread (a pointer to the currently active osfmk thread_shuttle). */
560 
561 #define IOThreadSelf() (current_thread())
562 
563 /*! @function IOCreateThread
564  *   @abstract Deprecated function - use kernel_thread_start(). Create a kernel thread.
565  *   @discussion This function creates a kernel thread, and passes the caller supplied argument to the new thread.  Warning: the value returned by this function is not 100% reliable.  There is a race condition where it is possible that the new thread has already terminated before this call returns.  Under that circumstance the IOThread returned will be invalid.  In general there is little that can be done with this value except compare it against 0.  The thread itself can call IOThreadSelf() 100% reliably and that is the prefered mechanism to manipulate the IOThreads state.
566  *   @param function A C-function pointer where the thread will begin execution.
567  *   @param argument Caller specified data to be passed to the new thread.
568  *   @result An IOThread identifier for the new thread, equivalent to an osfmk thread_t. */
569 
570 IOThread IOCreateThread(IOThreadFunc function, void *argument) __attribute__((deprecated));
571 
572 /*! @function IOExitThread
573  *   @abstract Deprecated function - use thread_terminate(). Terminate execution of current thread.
574  *   @discussion This function destroys the currently running thread, and does not return. */
575 
576 void IOExitThread(void) __attribute__((deprecated));
577 
578 /*! @function IOSleep
579  *   @abstract Sleep the calling thread for a number of milliseconds.
580  *   @discussion This function blocks the calling thread for at least the number of specified milliseconds, giving time to other processes.
581  *   @param milliseconds The integer number of milliseconds to wait. */
582 
583 void IOSleep(unsigned milliseconds);
584 
585 /*! @function IOSleepWithLeeway
586  *   @abstract Sleep the calling thread for a number of milliseconds, with a specified leeway the kernel may use for timer coalescing.
587  *   @discussion This function blocks the calling thread for at least the number of specified milliseconds, giving time to other processes.  The kernel may also coalesce any timers involved in the delay, using the leeway given as a guideline.
588  *   @param intervalMilliseconds The integer number of milliseconds to wait.
589  *   @param leewayMilliseconds The integer number of milliseconds to use as a timer coalescing guideline. */
590 
591 void IOSleepWithLeeway(unsigned intervalMilliseconds, unsigned leewayMilliseconds);
592 
593 /*! @function IODelay
594  *   @abstract Spin delay for a number of microseconds.
595  *   @discussion This function spins to delay for at least the number of specified microseconds. Since the CPU is busy spinning no time is made available to other processes; this method of delay should be used only for short periods. Also, the AbsoluteTime based APIs of kern/clock.h provide finer grained and lower cost delays.
596  *   @param microseconds The integer number of microseconds to spin wait. */
597 
598 void IODelay(unsigned microseconds);
599 
600 /*! @function IOPause
601  *   @abstract Spin delay for a number of nanoseconds.
602  *   @discussion This function spins to delay for at least the number of specified nanoseconds. Since the CPU is busy spinning no time is made available to other processes; this method of delay should be used only for short periods.
603  *   @param nanoseconds The integer number of nanoseconds to spin wait. */
604 
605 void IOPause(unsigned nanoseconds);
606 
607 /*! @function IOLog
608  *   @abstract Log a message to console in text mode, and /var/log/system.log.
609  *   @discussion This function allows a driver to log diagnostic information to the screen during verbose boots, and to a log file found at /var/log/system.log. IOLog should not be called from interrupt context.
610  *   @param format A printf() style format string (see printf(3) documentation).
611  */
612 
613 void IOLog(const char *format, ...)
614 __attribute__((format(printf, 1, 2)));
615 
616 /*! @function IOLogv
617  *   @abstract Log a message to console in text mode, and /var/log/system.log.
618  *   @discussion This function allows a driver to log diagnostic information to the screen during verbose boots, and to a log file found at /var/log/system.log. IOLogv should not be called from interrupt context.
619  *   @param format A printf() style format string (see printf(3) documentation).
620  *   @param ap stdarg(3) style variable arguments. */
621 
622 void IOLogv(const char *format, va_list ap)
623 __attribute__((format(printf, 1, 0)));
624 
625 #ifndef _FN_KPRINTF
626 #define _FN_KPRINTF
627 void kprintf(const char *format, ...) __printflike(1, 2);
628 #endif
629 #ifndef _FN_KPRINTF_DECLARED
630 #define _FN_KPRINTF_DECLARED
631 #endif
632 
633 /*
634  * Convert a integer constant (typically a #define or enum) to a string
635  * via an array of IONamedValue.
636  */
637 const char *IOFindNameForValue(int value,
638     const IONamedValue *namedValueArray);
639 
640 /*
641  * Convert a string to an int via an array of IONamedValue. Returns
642  * kIOReturnSuccess of string found, else returns kIOReturnBadArgument.
643  */
644 IOReturn IOFindValueForName(const char *string,
645     const IONamedValue *regValueArray,
646     int *value);                                /* RETURNED */
647 
648 /*! @function Debugger
649  *   @abstract Enter the kernel debugger.
650  *   @discussion This function freezes the kernel and enters the builtin debugger. It may not be possible to exit the debugger without a second machine.
651  *   @param reason A C-string to describe why the debugger is being entered. */
652 
653 void Debugger(const char * reason);
654 #if __LP64__
655 #define IOPanic(reason) panic("%s", reason)
656 #else
657 void IOPanic(const char *reason) __attribute__((deprecated)) __abortlike;
658 #endif
659 
660 #ifdef __cplusplus
661 class OSDictionary;
662 #endif
663 
664 #ifdef __cplusplus
665 OSDictionary *
666 #else
667 struct OSDictionary *
668 #endif
669 IOBSDNameMatching( const char * name );
670 
671 #ifdef __cplusplus
672 OSDictionary *
673 #else
674 struct OSDictionary *
675 #endif
676 IOOFPathMatching( const char * path, char * buf, int maxLen ) __attribute__((deprecated));
677 
678 /*
679  * Convert between size and a power-of-two alignment.
680  */
681 IOAlignment IOSizeToAlignment(unsigned int size);
682 unsigned int IOAlignmentToSize(IOAlignment align);
683 
684 /*
685  * Multiply and divide routines for IOFixed datatype.
686  */
687 
688 static inline IOFixed
IOFixedMultiply(IOFixed a,IOFixed b)689 IOFixedMultiply(IOFixed a, IOFixed b)
690 {
691 	return (IOFixed)((((SInt64) a) * ((SInt64) b)) >> 16);
692 }
693 
694 static inline IOFixed
IOFixedDivide(IOFixed a,IOFixed b)695 IOFixedDivide(IOFixed a, IOFixed b)
696 {
697 	return (IOFixed)((((SInt64) a) << 16) / ((SInt64) b));
698 }
699 
700 /*
701  * IORound and IOTrunc convenience functions, in the spirit
702  * of vm's round_page() and trunc_page().
703  */
704 #define IORound(value, multiple) \
705 	((((value) + (multiple) - 1) / (multiple)) * (multiple))
706 
707 #define IOTrunc(value, multiple) \
708 	(((value) / (multiple)) * (multiple));
709 
710 
711 #if defined(__APPLE_API_OBSOLETE)
712 
713 /* The following API is deprecated */
714 
715 /* The API exported by kern/clock.h
716  *  should be used for high resolution timing. */
717 
718 void IOGetTime( mach_timespec_t * clock_time) __attribute__((deprecated));
719 
720 #if !defined(__LP64__)
721 
722 #undef eieio
723 #define eieio() \
724     OSSynchronizeIO()
725 
726 extern mach_timespec_t IOZeroTvalspec;
727 
728 #endif /* !defined(__LP64__) */
729 
730 #endif /* __APPLE_API_OBSOLETE */
731 
732 #if XNU_KERNEL_PRIVATE
733 vm_tag_t
734 IOMemoryTag(vm_map_t map);
735 
736 vm_size_t
737 log2up(vm_size_t size);
738 #endif
739 
740 /*
741  * Implementation details
742  */
743 #define __IOKIT_COUNT_ARGS1(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, N, ...) N
744 #define __IOKIT_COUNT_ARGS(...) \
745 	__IOKIT_COUNT_ARGS1(, ##__VA_ARGS__, _9, _8, _7, _6, _5, _4, _3, _2, _1, _0)
746 #define __IOKIT_DISPATCH1(base, N, ...) __CONCAT(base, N)(__VA_ARGS__)
747 #define __IOKIT_DISPATCH(base, ...) \
748 	__IOKIT_DISPATCH1(base, __IOKIT_COUNT_ARGS(__VA_ARGS__), ##__VA_ARGS__)
749 
750 
751 #ifdef XNU_KERNEL_PRIVATE
752 
753 #define IOFREETYPE_ASSERT_COMPATIBLE_POINTER(ptr, type) \
754     KALLOC_TYPE_ASSERT_COMPATIBLE_POINTER(ptr, type)
755 
756 #else  /* XNU_KERNEL_PRIVATE */
757 
758 #define IOFREETYPE_ASSERT_COMPATIBLE_POINTER(ptr, type) do {} while (0)
759 
760 #endif /* XNU_KERNEL_PRIVATE */
761 
762 #if KERNEL_PRIVATE
763 /*
764  * Implementation functions for IOMallocType/IOFreeType.
765  * Not intended to be used on their own.
766  */
767 void *
768 IOMallocTypeImpl(kalloc_type_view_t kt_view);
769 
770 void
771 IOFreeTypeImpl(kalloc_type_view_t kt_view, void * address);
772 
773 void *
774 IOMallocTypeVarImpl(kalloc_type_var_view_t kt_view, vm_size_t size);
775 
776 void
777 IOFreeTypeVarImpl(kalloc_type_var_view_t kt_view, void * address, vm_size_t size);
778 #endif
779 
780 #if KERNEL_PRIVATE
781 #if __cplusplus
782 
783 #if __has_feature(cxx_deleted_functions)
784 #define __IODeleteArrayOperators()                         \
785 	_Pragma("clang diagnostic push")                       \
786 	_Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
787 	void *operator new[](size_t) = delete;                 \
788 	void operator delete[](void *) = delete;               \
789 	void operator delete[](void *, size_t) = delete;       \
790 	_Pragma("clang diagnostic pop")
791 #else  /* __has_feature(cxx_deleted_functions) */
792 #define __IODeleteArrayOperators()
793 #endif /* __has_feature(cxx_deleted_functions) */
794 
795 #define __IOAddOperatorsSentinel(name, type) \
796 	static void __CONCAT(name, type) (void) __unused
797 
798 #define __IOAddTypedOperatorsSentinel(type) \
799 	__IOAddOperatorsSentinel(__kt_typed_operators_, type)
800 
801 #define __IOAddTypedArrayOperatorsSentinel(type) \
802 	__IOAddOperatorsSentinel(__kt_typed_array_operators_, type)
803 
804 #define __IODeclareTypedOperators(type)                    \
805 	void *operator new(size_t size __unused);              \
806 	void operator delete(void *mem, size_t size __unused); \
807 	__IOAddTypedOperatorsSentinel(type)
808 
809 #define __IODeclareTypedArrayOperators(type) \
810 	void *operator new[](size_t __unused);   \
811 	void operator delete[](void *ptr);       \
812 	__IOAddTypedArrayOperatorsSentinel(type)
813 
814 
815 #define __IODefineTypedOperators(type)                          \
816 	void *type::operator new(size_t size __unused)              \
817 	{                                                           \
818 	        return IOMallocType(type);                                \
819 	}                                                           \
820 	void type::operator delete(void *mem, size_t size __unused) \
821 	{                                                           \
822 	        IOFreeType(mem, type);                                    \
823 	}
824 
825 
826 extern "C++" {
827 template<typename T>
828 struct __IOTypedOperatorsArrayHeader {
829 	size_t alloc_size;
830 	_Alignas(T) char array[];
831 };
832 
833 #define __IOTypedOperatorNewArrayImpl(type, count)                        \
834 	{                                                                  \
835 	        typedef __IOTypedOperatorsArrayHeader<type> hdr_ty;        \
836 	        static KALLOC_TYPE_VAR_DEFINE(kt_view_var,                 \
837 	            hdr_ty, type, KT_SHARED_ACCT);                         \
838 	        hdr_ty *hdr;                                               \
839 	        const size_t __s = sizeof(hdr_ty) + count;                 \
840 	        hdr = reinterpret_cast<hdr_ty *>(                          \
841 	            IOMallocTypeVarImpl(kt_view_var, __s));                \
842 	        if (hdr) {                                                 \
843 	                hdr->alloc_size = __s;                             \
844 	                return reinterpret_cast<void *>(&hdr->array);      \
845 	        }                                                          \
846 	        _Pragma("clang diagnostic push")                           \
847 	        _Pragma("clang diagnostic ignored \"-Wnew-returns-null\"") \
848 	        return NULL;                                               \
849 	        _Pragma("clang diagnostic pop")                            \
850 	}
851 
852 #define __IOTypedOperatorDeleteArrayImpl(type, ptr)                  \
853 	{                                                             \
854 	        typedef __IOTypedOperatorsArrayHeader<type> hdr_ty;   \
855 	        static KALLOC_TYPE_VAR_DEFINE(kt_view_var,            \
856 	            hdr_ty, type, KT_SHARED_ACCT);                    \
857 	        hdr_ty *hdr = reinterpret_cast<hdr_ty *>(             \
858 	            reinterpret_cast<uintptr_t>(ptr) - sizeof(*hdr)); \
859 	        IOFreeTypeVarImpl(kt_view_var,                        \
860 	        reinterpret_cast<void *>(hdr), hdr->alloc_size);  \
861 	}
862 
863 #define __IODefineTypedArrayOperators(type)        \
864 	void *type::operator new[](size_t count)       \
865 	__IOTypedOperatorNewArrayImpl(type, count)  \
866 	void type::operator delete[](void *ptr)        \
867 	__IOTypedOperatorDeleteArrayImpl(type, ptr)
868 
869 
870 #define __IOOverrideTypedOperators(type)                  \
871 	void *operator new(size_t size __unused)              \
872 	{                                                     \
873 	        return IOMallocType(type);                        \
874 	}                                                     \
875 	void operator delete(void *mem, size_t size __unused) \
876 	{                                                     \
877 	        IOFreeType(mem, type);                            \
878 	} \
879 	__IOAddTypedOperatorsSentinel(type)
880 
881 #define __IOOverrideTypedArrayOperators(type)       \
882 	void *operator new[](size_t count)              \
883 	__IOTypedOperatorNewArrayImpl(type, count)   \
884 	void operator delete[](void *ptr)               \
885 	__IOTypedOperatorDeleteArrayImpl(type, ptr)  \
886 	__IOAddTypedArrayOperatorsSentinel(type)
887 
888 /*!
889  * @macro IODeclareTypedOperators
890  *
891  * @abstract
892  * Declare operator new/delete to adopt the typed allocator
893  * API for a given class/struct. It must be paired with
894  * @c IODefineTypedOperators.
895  *
896  * @discussion
897  * Use this macro within a class/struct declaration to declare
898  * @c operator new and @c operator delete to use the typed
899  * allocator API as the backing storage for this type.
900  *
901  * @note The default variant deletes the declaration of the
902  * array operators. Please see doc/allocators/api-basics.md for
903  * more details regarding their usage.
904  *
905  * @param type The type which the declarations are being provided for.
906  */
907 #define IODeclareTypedOperatorsSupportingArrayOperators(type) \
908 	__IODeclareTypedArrayOperators(type);                     \
909 	__IODeclareTypedOperators(type)
910 #define IODeclareTypedOperators(type) \
911 	__IODeleteArrayOperators()        \
912 	__IODeclareTypedOperators(type)
913 
914 /*!
915  * @macro IODefineTypedOperators
916  *
917  * @abstract
918  * Define (out of line) operator new/delete to adopt the typed
919  * allocator API for a given class/struct. It must be paired
920  * with @c IODeclareTypedOperators.
921  *
922  * @discussion
923  * Use this macro to provide an out of line definition of
924  * @c operator new and @c operator delete for a given type
925  * to use the typed allocator API as its backing storage.
926  *
927  * @param type The type which the overrides are being provided for.
928  */
929 #define IODefineTypedOperatorsSupportingArrayOperators(type) \
930 	__IODefineTypedOperators(type)                           \
931 	__IODefineTypedArrayOperators(type)
932 #define IODefineTypedOperators(type) \
933 	__IODefineTypedOperators(type)
934 
935 /*!
936  * @macro IOOverrideTypedOperators
937  *
938  * @abstract
939  * Override operator new/delete to use @c kalloc_type.
940  *
941  * @discussion
942  * Use this macro within a class/struct declaration to override
943  * @c operator new and @c operator delete to use the typed
944  * allocator API as the backing storage for this type.
945  *
946  * @note The default variant deletes the implementation of the
947  * array operators. Please see doc/allocators/api-basics.md for
948  * more details regarding their usage.
949  *
950  * @param type The type which the overrides are being provided for.
951  */
952 #define IOOverrideTypedOperators(type) \
953 	__IODeleteArrayOperators()         \
954 	__IOOverrideTypedOperators(type)
955 
956 #define IOOverrideTypedOperatorsSupportingArrayOperators(type) \
957 	__IOOverrideTypedArrayOperators(type);                     \
958 	__IOOverrideTypedOperators(type)
959 
960 
961 /*!
962  * @template IOTypedOperatorsMixin
963  *
964  * @abstract
965  * Mixin that implements @c operator new and @c operator delete
966  * using the typed allocator API.
967  *
968  * @discussion
969  * Inherit from this struct in order to adopt the typed allocator
970  * API on a struct/class for @c operator new and @c operator delete.
971  *
972  * The type passed as as a template parameter must be the type
973  * which is inheriting from the struct itself.
974  *
975  * @note See doc/allocators/api-basics.md for more details
976  * regarding the usage of the mixin.
977  *
978  * @example
979  *
980  *     class C : public IOTypedOperatorsMixin<C> {
981  *         ...
982  *     }
983  *     C *obj = new C;
984  *
985  */
986 template<class T>
987 struct IOTypedOperatorsMixin {
988 	IOOverrideTypedOperators(T);
989 };
990 
991 template<class T>
992 struct IOTypedOperatorsMixinSupportingArrayOperators {
993 	IOOverrideTypedOperatorsSupportingArrayOperators(T);
994 };
995 } // extern "C++"
996 
997 
998 #endif /* __cplusplus */
999 #endif /* KERNEL_PRIVATE */
1000 
1001 __END_DECLS
1002 
1003 #endif /* !__IOKIT_IOLIB_H */
1004