1e13b1fa5SApple OSS Distributions /*
2e13b1fa5SApple OSS Distributions * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
3e13b1fa5SApple OSS Distributions *
4e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5e13b1fa5SApple OSS Distributions *
6e13b1fa5SApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7e13b1fa5SApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8e13b1fa5SApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9e13b1fa5SApple OSS Distributions * compliance with the License. The rights granted to you under the License
10e13b1fa5SApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11e13b1fa5SApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12e13b1fa5SApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13e13b1fa5SApple OSS Distributions * terms of an Apple operating system software license agreement.
14e13b1fa5SApple OSS Distributions *
15e13b1fa5SApple OSS Distributions * Please obtain a copy of the License at
16e13b1fa5SApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17e13b1fa5SApple OSS Distributions *
18e13b1fa5SApple OSS Distributions * The Original Code and all software distributed under the License are
19e13b1fa5SApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20e13b1fa5SApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21e13b1fa5SApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22e13b1fa5SApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23e13b1fa5SApple OSS Distributions * Please see the License for the specific language governing rights and
24e13b1fa5SApple OSS Distributions * limitations under the License.
25e13b1fa5SApple OSS Distributions *
26e13b1fa5SApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27e13b1fa5SApple OSS Distributions */
28e13b1fa5SApple OSS Distributions /*
29e13b1fa5SApple OSS Distributions * HISTORY
30e13b1fa5SApple OSS Distributions *
31e13b1fa5SApple OSS Distributions * 17-Apr-91 Portions from libIO.m, Doug Mitchell at NeXT.
32e13b1fa5SApple OSS Distributions * 17-Nov-98 cpp
33e13b1fa5SApple OSS Distributions *
34e13b1fa5SApple OSS Distributions */
35e13b1fa5SApple OSS Distributions
36e13b1fa5SApple OSS Distributions #include <IOKit/system.h>
37e13b1fa5SApple OSS Distributions #include <mach/sync_policy.h>
38e13b1fa5SApple OSS Distributions #include <machine/machine_routines.h>
398d741a5dSApple OSS Distributions #include <vm/vm_kern_xnu.h>
408d741a5dSApple OSS Distributions #include <vm/vm_map_xnu.h>
41e13b1fa5SApple OSS Distributions #include <libkern/c++/OSCPPDebug.h>
42e13b1fa5SApple OSS Distributions
43e13b1fa5SApple OSS Distributions #include <IOKit/assert.h>
44e13b1fa5SApple OSS Distributions
45e13b1fa5SApple OSS Distributions #include <IOKit/IOReturn.h>
46e13b1fa5SApple OSS Distributions #include <IOKit/IOLib.h>
47e13b1fa5SApple OSS Distributions #include <IOKit/IOLocks.h>
48e13b1fa5SApple OSS Distributions #include <IOKit/IOMapper.h>
49e13b1fa5SApple OSS Distributions #include <IOKit/IOBufferMemoryDescriptor.h>
50e13b1fa5SApple OSS Distributions #include <IOKit/IOKitDebug.h>
51e13b1fa5SApple OSS Distributions
52e13b1fa5SApple OSS Distributions #include "IOKitKernelInternal.h"
53e13b1fa5SApple OSS Distributions
54e13b1fa5SApple OSS Distributions #ifdef IOALLOCDEBUG
55e13b1fa5SApple OSS Distributions #include <libkern/OSDebug.h>
56e13b1fa5SApple OSS Distributions #include <sys/sysctl.h>
57e13b1fa5SApple OSS Distributions #endif
58e13b1fa5SApple OSS Distributions
59855239e5SApple OSS Distributions #include "libkern/OSAtomic.h"
60855239e5SApple OSS Distributions #include <libkern/c++/OSKext.h>
61855239e5SApple OSS Distributions #include <IOKit/IOStatisticsPrivate.h>
6288cc0b97SApple OSS Distributions #include <os/log_private.h>
63855239e5SApple OSS Distributions #include <sys/msgbuf.h>
6476e12aa3SApple OSS Distributions #include <console/serial_protos.h>
65855239e5SApple OSS Distributions
66855239e5SApple OSS Distributions #if IOKITSTATS
67855239e5SApple OSS Distributions
68855239e5SApple OSS Distributions #define IOStatisticsAlloc(type, size) \
69855239e5SApple OSS Distributions do { \
70855239e5SApple OSS Distributions IOStatistics::countAlloc(type, size); \
71855239e5SApple OSS Distributions } while (0)
72855239e5SApple OSS Distributions
73855239e5SApple OSS Distributions #else
74855239e5SApple OSS Distributions
75855239e5SApple OSS Distributions #define IOStatisticsAlloc(type, size)
76855239e5SApple OSS Distributions
77855239e5SApple OSS Distributions #endif /* IOKITSTATS */
78855239e5SApple OSS Distributions
790f3703acSApple OSS Distributions
800f3703acSApple OSS Distributions #define TRACK_ALLOC (IOTRACKING && (kIOTracking & gIOKitDebug))
810f3703acSApple OSS Distributions
820f3703acSApple OSS Distributions
83e13b1fa5SApple OSS Distributions extern "C"
84e13b1fa5SApple OSS Distributions {
85e13b1fa5SApple OSS Distributions mach_timespec_t IOZeroTvalspec = { 0, 0 };
86e13b1fa5SApple OSS Distributions
87e13b1fa5SApple OSS Distributions extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va);
88e13b1fa5SApple OSS Distributions
89855239e5SApple OSS Distributions extern int
903ca3bd55SApple OSS Distributions __doprnt(
913ca3bd55SApple OSS Distributions const char *fmt,
923ca3bd55SApple OSS Distributions va_list argp,
933ca3bd55SApple OSS Distributions void (*putc)(int, void *),
943ca3bd55SApple OSS Distributions void *arg,
950f3703acSApple OSS Distributions int radix,
960f3703acSApple OSS Distributions int is_log);
973ca3bd55SApple OSS Distributions
98bb611c8fSApple OSS Distributions extern bool bsd_log_lock(bool);
99855239e5SApple OSS Distributions extern void bsd_log_unlock(void);
1003ca3bd55SApple OSS Distributions
101e13b1fa5SApple OSS Distributions
102e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
103e13b1fa5SApple OSS Distributions
104*d4514f0bSApple OSS Distributions lck_grp_t io_lck_grp;
105e13b1fa5SApple OSS Distributions lck_grp_t *IOLockGroup;
106e13b1fa5SApple OSS Distributions
107e13b1fa5SApple OSS Distributions /*
108e13b1fa5SApple OSS Distributions * Global variables for use by iLogger
109e13b1fa5SApple OSS Distributions * These symbols are for use only by Apple diagnostic code.
110e13b1fa5SApple OSS Distributions * Binary compatibility is not guaranteed for kexts that reference these symbols.
111e13b1fa5SApple OSS Distributions */
112e13b1fa5SApple OSS Distributions
113e13b1fa5SApple OSS Distributions void *_giDebugLogInternal = NULL;
114e13b1fa5SApple OSS Distributions void *_giDebugLogDataInternal = NULL;
115e13b1fa5SApple OSS Distributions void *_giDebugReserved1 = NULL;
116e13b1fa5SApple OSS Distributions void *_giDebugReserved2 = NULL;
117e13b1fa5SApple OSS Distributions
118e7776783SApple OSS Distributions #if defined(__x86_64__)
119186b8fceSApple OSS Distributions iopa_t gIOBMDPageAllocator;
120e7776783SApple OSS Distributions #endif /* defined(__x86_64__) */
121e13b1fa5SApple OSS Distributions
122e13b1fa5SApple OSS Distributions /*
123e13b1fa5SApple OSS Distributions * Static variables for this module.
124e13b1fa5SApple OSS Distributions */
125e13b1fa5SApple OSS Distributions
126e13b1fa5SApple OSS Distributions static queue_head_t gIOMallocContiguousEntries;
127e13b1fa5SApple OSS Distributions static lck_mtx_t * gIOMallocContiguousEntriesLock;
128e13b1fa5SApple OSS Distributions
129a3bb9fccSApple OSS Distributions #if __x86_64__
130a3bb9fccSApple OSS Distributions enum { kIOMaxPageableMaps = 8 };
1315c2921b0SApple OSS Distributions enum { kIOMaxFixedRanges = 4 };
132a3bb9fccSApple OSS Distributions enum { kIOPageableMapSize = 512 * 1024 * 1024 };
133a3bb9fccSApple OSS Distributions enum { kIOPageableMaxMapSize = 512 * 1024 * 1024 };
134a3bb9fccSApple OSS Distributions #else
135e13b1fa5SApple OSS Distributions enum { kIOMaxPageableMaps = 16 };
1365c2921b0SApple OSS Distributions enum { kIOMaxFixedRanges = 4 };
137e13b1fa5SApple OSS Distributions enum { kIOPageableMapSize = 96 * 1024 * 1024 };
138e13b1fa5SApple OSS Distributions enum { kIOPageableMaxMapSize = 96 * 1024 * 1024 };
139a3bb9fccSApple OSS Distributions #endif
140e13b1fa5SApple OSS Distributions
141e13b1fa5SApple OSS Distributions typedef struct {
142e13b1fa5SApple OSS Distributions vm_map_t map;
143e13b1fa5SApple OSS Distributions vm_offset_t address;
144e13b1fa5SApple OSS Distributions vm_offset_t end;
145e13b1fa5SApple OSS Distributions } IOMapData;
146e13b1fa5SApple OSS Distributions
1475c2921b0SApple OSS Distributions static SECURITY_READ_ONLY_LATE(struct mach_vm_range)
1485c2921b0SApple OSS Distributions gIOKitPageableFixedRanges[kIOMaxFixedRanges];
1495c2921b0SApple OSS Distributions
150e13b1fa5SApple OSS Distributions static struct {
151e13b1fa5SApple OSS Distributions UInt32 count;
152e13b1fa5SApple OSS Distributions UInt32 hint;
153e13b1fa5SApple OSS Distributions IOMapData maps[kIOMaxPageableMaps];
154e13b1fa5SApple OSS Distributions lck_mtx_t * lock;
155e13b1fa5SApple OSS Distributions } gIOKitPageableSpace;
156e13b1fa5SApple OSS Distributions
157e7776783SApple OSS Distributions #if defined(__x86_64__)
158186b8fceSApple OSS Distributions static iopa_t gIOPageablePageAllocator;
159186b8fceSApple OSS Distributions
160a3bb9fccSApple OSS Distributions uint32_t gIOPageAllocChunkBytes;
161e7776783SApple OSS Distributions #endif /* defined(__x86_64__) */
162a3bb9fccSApple OSS Distributions
1630f3703acSApple OSS Distributions #if IOTRACKING
1640f3703acSApple OSS Distributions IOTrackingQueue * gIOMallocTracking;
1650f3703acSApple OSS Distributions IOTrackingQueue * gIOWireTracking;
1660f3703acSApple OSS Distributions IOTrackingQueue * gIOMapTracking;
1670f3703acSApple OSS Distributions #endif /* IOTRACKING */
1680f3703acSApple OSS Distributions
169e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
170e13b1fa5SApple OSS Distributions
1715c2921b0SApple OSS Distributions KMEM_RANGE_REGISTER_STATIC(gIOKitPageableFixed0,
1725c2921b0SApple OSS Distributions &gIOKitPageableFixedRanges[0], kIOPageableMapSize);
1735c2921b0SApple OSS Distributions KMEM_RANGE_REGISTER_STATIC(gIOKitPageableFixed1,
1745c2921b0SApple OSS Distributions &gIOKitPageableFixedRanges[1], kIOPageableMapSize);
1755c2921b0SApple OSS Distributions KMEM_RANGE_REGISTER_STATIC(gIOKitPageableFixed2,
1765c2921b0SApple OSS Distributions &gIOKitPageableFixedRanges[2], kIOPageableMapSize);
1775c2921b0SApple OSS Distributions KMEM_RANGE_REGISTER_STATIC(gIOKitPageableFixed3,
1785c2921b0SApple OSS Distributions &gIOKitPageableFixedRanges[3], kIOPageableMapSize);
179a5e72196SApple OSS Distributions void
IOLibInit(void)180a5e72196SApple OSS Distributions IOLibInit(void)
181e13b1fa5SApple OSS Distributions {
182e13b1fa5SApple OSS Distributions static bool libInitialized;
183e13b1fa5SApple OSS Distributions
184a5e72196SApple OSS Distributions if (libInitialized) {
185e13b1fa5SApple OSS Distributions return;
186a5e72196SApple OSS Distributions }
187e13b1fa5SApple OSS Distributions
188*d4514f0bSApple OSS Distributions lck_grp_init(&io_lck_grp, "IOKit", LCK_GRP_ATTR_NULL);
189*d4514f0bSApple OSS Distributions IOLockGroup = &io_lck_grp;
1900f3703acSApple OSS Distributions
1910f3703acSApple OSS Distributions #if IOTRACKING
1920f3703acSApple OSS Distributions IOTrackingInit();
19388cc0b97SApple OSS Distributions gIOMallocTracking = IOTrackingQueueAlloc(kIOMallocTrackingName, 0, 0, 0,
19488cc0b97SApple OSS Distributions kIOTrackingQueueTypeAlloc,
19588cc0b97SApple OSS Distributions 37);
19688cc0b97SApple OSS Distributions gIOWireTracking = IOTrackingQueueAlloc(kIOWireTrackingName, 0, 0, page_size, 0, 0);
19788cc0b97SApple OSS Distributions
19888cc0b97SApple OSS Distributions size_t mapCaptureSize = (kIOTracking & gIOKitDebug) ? page_size : (1024 * 1024);
19988cc0b97SApple OSS Distributions gIOMapTracking = IOTrackingQueueAlloc(kIOMapTrackingName, 0, 0, mapCaptureSize,
20088cc0b97SApple OSS Distributions kIOTrackingQueueTypeDefaultOn
20188cc0b97SApple OSS Distributions | kIOTrackingQueueTypeMap
20288cc0b97SApple OSS Distributions | kIOTrackingQueueTypeUser,
20388cc0b97SApple OSS Distributions 0);
2040f3703acSApple OSS Distributions #endif
2050f3703acSApple OSS Distributions
2065c2921b0SApple OSS Distributions gIOKitPageableSpace.maps[0].map = kmem_suballoc(kernel_map,
2075c2921b0SApple OSS Distributions &gIOKitPageableFixedRanges[0].min_address,
208e13b1fa5SApple OSS Distributions kIOPageableMapSize,
209e7776783SApple OSS Distributions VM_MAP_CREATE_PAGEABLE,
210aca3beaaSApple OSS Distributions VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
2115c2921b0SApple OSS Distributions (kms_flags_t)(KMS_PERMANENT | KMS_DATA | KMS_NOFAIL),
2125c2921b0SApple OSS Distributions VM_KERN_MEMORY_IOKIT).kmr_submap;
213e13b1fa5SApple OSS Distributions
2145c2921b0SApple OSS Distributions gIOKitPageableSpace.maps[0].address = gIOKitPageableFixedRanges[0].min_address;
2155c2921b0SApple OSS Distributions gIOKitPageableSpace.maps[0].end = gIOKitPageableFixedRanges[0].max_address;
216e13b1fa5SApple OSS Distributions gIOKitPageableSpace.lock = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL);
217e13b1fa5SApple OSS Distributions gIOKitPageableSpace.hint = 0;
218e13b1fa5SApple OSS Distributions gIOKitPageableSpace.count = 1;
219e13b1fa5SApple OSS Distributions
220e13b1fa5SApple OSS Distributions gIOMallocContiguousEntriesLock = lck_mtx_alloc_init(IOLockGroup, LCK_ATTR_NULL);
221e13b1fa5SApple OSS Distributions queue_init( &gIOMallocContiguousEntries );
222e13b1fa5SApple OSS Distributions
223e7776783SApple OSS Distributions #if defined(__x86_64__)
224a3bb9fccSApple OSS Distributions gIOPageAllocChunkBytes = PAGE_SIZE / 64;
225e7776783SApple OSS Distributions
226a3bb9fccSApple OSS Distributions assert(sizeof(iopa_page_t) <= gIOPageAllocChunkBytes);
227186b8fceSApple OSS Distributions iopa_init(&gIOBMDPageAllocator);
228186b8fceSApple OSS Distributions iopa_init(&gIOPageablePageAllocator);
229e7776783SApple OSS Distributions #endif /* defined(__x86_64__) */
230186b8fceSApple OSS Distributions
2310f3703acSApple OSS Distributions
232e13b1fa5SApple OSS Distributions libInitialized = true;
233e13b1fa5SApple OSS Distributions }
234e13b1fa5SApple OSS Distributions
235e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
236e13b1fa5SApple OSS Distributions
237e6231be0SApple OSS Distributions vm_size_t
log2up(vm_size_t size)238bb611c8fSApple OSS Distributions log2up(vm_size_t size)
2390f3703acSApple OSS Distributions {
240a5e72196SApple OSS Distributions if (size <= 1) {
241a5e72196SApple OSS Distributions size = 0;
242a5e72196SApple OSS Distributions } else {
243bb611c8fSApple OSS Distributions #if __LP64__
244bb611c8fSApple OSS Distributions size = 64 - __builtin_clzl(size - 1);
245bb611c8fSApple OSS Distributions #else
246bb611c8fSApple OSS Distributions size = 32 - __builtin_clzl(size - 1);
247bb611c8fSApple OSS Distributions #endif
248a5e72196SApple OSS Distributions }
249a5e72196SApple OSS Distributions return size;
2500f3703acSApple OSS Distributions }
2510f3703acSApple OSS Distributions
2520f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2530f3703acSApple OSS Distributions
254a5e72196SApple OSS Distributions IOThread
IOCreateThread(IOThreadFunc fcn,void * arg)255a5e72196SApple OSS Distributions IOCreateThread(IOThreadFunc fcn, void *arg)
256e13b1fa5SApple OSS Distributions {
257e13b1fa5SApple OSS Distributions kern_return_t result;
258e13b1fa5SApple OSS Distributions thread_t thread;
259e13b1fa5SApple OSS Distributions
2605c2921b0SApple OSS Distributions result = kernel_thread_start((thread_continue_t)(void (*)(void))fcn, arg, &thread);
261a5e72196SApple OSS Distributions if (result != KERN_SUCCESS) {
262a5e72196SApple OSS Distributions return NULL;
263a5e72196SApple OSS Distributions }
264e13b1fa5SApple OSS Distributions
265e13b1fa5SApple OSS Distributions thread_deallocate(thread);
266e13b1fa5SApple OSS Distributions
267a5e72196SApple OSS Distributions return thread;
268e13b1fa5SApple OSS Distributions }
269e13b1fa5SApple OSS Distributions
270e13b1fa5SApple OSS Distributions
271a5e72196SApple OSS Distributions void
IOExitThread(void)272a5e72196SApple OSS Distributions IOExitThread(void)
273e13b1fa5SApple OSS Distributions {
274e13b1fa5SApple OSS Distributions (void) thread_terminate(current_thread());
275e13b1fa5SApple OSS Distributions }
276e13b1fa5SApple OSS Distributions
277a5e72196SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
278a5e72196SApple OSS Distributions
279a5e72196SApple OSS Distributions #if IOTRACKING
280a5e72196SApple OSS Distributions struct IOLibMallocHeader {
2810f3703acSApple OSS Distributions IOTrackingAddress tracking;
2820f3703acSApple OSS Distributions };
2830f3703acSApple OSS Distributions #endif
2840f3703acSApple OSS Distributions
2850f3703acSApple OSS Distributions #if IOTRACKING
2860f3703acSApple OSS Distributions #define sizeofIOLibMallocHeader (sizeof(IOLibMallocHeader) - (TRACK_ALLOC ? 0 : sizeof(IOTrackingAddress)))
2870f3703acSApple OSS Distributions #else
2880f3703acSApple OSS Distributions #define sizeofIOLibMallocHeader (0)
2890f3703acSApple OSS Distributions #endif
2900f3703acSApple OSS Distributions
2910f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
292e13b1fa5SApple OSS Distributions
2935c2921b0SApple OSS Distributions __typed_allocators_ignore_push // allocator implementation
2945c2921b0SApple OSS Distributions
295a5e72196SApple OSS Distributions void *
2965c2921b0SApple OSS Distributions (IOMalloc_internal)(struct kalloc_heap *kheap, vm_size_t size,
2975c2921b0SApple OSS Distributions zalloc_flags_t flags)
298e13b1fa5SApple OSS Distributions {
299e13b1fa5SApple OSS Distributions void * address;
3000f3703acSApple OSS Distributions vm_size_t allocSize;
301e13b1fa5SApple OSS Distributions
3020f3703acSApple OSS Distributions allocSize = size + sizeofIOLibMallocHeader;
3030f3703acSApple OSS Distributions #if IOTRACKING
304a5e72196SApple OSS Distributions if (sizeofIOLibMallocHeader && (allocSize <= size)) {
305a5e72196SApple OSS Distributions return NULL; // overflow
306a5e72196SApple OSS Distributions }
3070f3703acSApple OSS Distributions #endif
308e7776783SApple OSS Distributions address = kheap_alloc(kheap, allocSize,
3095c2921b0SApple OSS Distributions Z_VM_TAG(Z_WAITOK | flags, VM_KERN_MEMORY_IOKIT));
3100f3703acSApple OSS Distributions
311e13b1fa5SApple OSS Distributions if (address) {
3120f3703acSApple OSS Distributions #if IOTRACKING
3130f3703acSApple OSS Distributions if (TRACK_ALLOC) {
3140f3703acSApple OSS Distributions IOLibMallocHeader * hdr;
3150f3703acSApple OSS Distributions hdr = (typeof(hdr))address;
3160f3703acSApple OSS Distributions bzero(&hdr->tracking, sizeof(hdr->tracking));
3170f3703acSApple OSS Distributions hdr->tracking.address = ~(((uintptr_t) address) + sizeofIOLibMallocHeader);
3180f3703acSApple OSS Distributions hdr->tracking.size = size;
31976e12aa3SApple OSS Distributions IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true, VM_KERN_MEMORY_NONE);
3200f3703acSApple OSS Distributions }
3210f3703acSApple OSS Distributions #endif
3220f3703acSApple OSS Distributions address = (typeof(address))(((uintptr_t) address) + sizeofIOLibMallocHeader);
3230f3703acSApple OSS Distributions
324855239e5SApple OSS Distributions #if IOALLOCDEBUG
325bb611c8fSApple OSS Distributions OSAddAtomicLong(size, &debug_iomalloc_size);
326e13b1fa5SApple OSS Distributions #endif
327855239e5SApple OSS Distributions IOStatisticsAlloc(kIOStatisticsMalloc, size);
328855239e5SApple OSS Distributions }
329855239e5SApple OSS Distributions
330e13b1fa5SApple OSS Distributions return address;
331e13b1fa5SApple OSS Distributions }
332e13b1fa5SApple OSS Distributions
333a5e72196SApple OSS Distributions void
IOFree_internal(struct kalloc_heap * kheap,void * inAddress,vm_size_t size)334e6231be0SApple OSS Distributions IOFree_internal(struct kalloc_heap *kheap, void * inAddress, vm_size_t size)
335e13b1fa5SApple OSS Distributions {
33676e12aa3SApple OSS Distributions void * address;
3370f3703acSApple OSS Distributions
338a5e72196SApple OSS Distributions if ((address = inAddress)) {
3390f3703acSApple OSS Distributions address = (typeof(address))(((uintptr_t) address) - sizeofIOLibMallocHeader);
3400f3703acSApple OSS Distributions
3410f3703acSApple OSS Distributions #if IOTRACKING
342a5e72196SApple OSS Distributions if (TRACK_ALLOC) {
3430f3703acSApple OSS Distributions IOLibMallocHeader * hdr;
34476e12aa3SApple OSS Distributions struct ptr_reference { void * ptr; };
34576e12aa3SApple OSS Distributions volatile struct ptr_reference ptr;
34676e12aa3SApple OSS Distributions
34776e12aa3SApple OSS Distributions // we're about to block in IOTrackingRemove(), make sure the original pointer
34876e12aa3SApple OSS Distributions // exists in memory or a register for leak scanning to find
34976e12aa3SApple OSS Distributions ptr.ptr = inAddress;
35076e12aa3SApple OSS Distributions
3510f3703acSApple OSS Distributions hdr = (typeof(hdr))address;
352a5e72196SApple OSS Distributions if (size != hdr->tracking.size) {
353e7776783SApple OSS Distributions OSReportWithBacktrace("bad IOFree size 0x%zx should be 0x%zx",
354e7776783SApple OSS Distributions (size_t)size, (size_t)hdr->tracking.size);
3550f3703acSApple OSS Distributions size = hdr->tracking.size;
3560f3703acSApple OSS Distributions }
3575c2921b0SApple OSS Distributions IOTrackingRemoveAddress(gIOMallocTracking, &hdr->tracking, size);
35876e12aa3SApple OSS Distributions ptr.ptr = NULL;
3590f3703acSApple OSS Distributions }
3600f3703acSApple OSS Distributions #endif
3610f3703acSApple OSS Distributions
362e6231be0SApple OSS Distributions kheap_free(kheap, address, size + sizeofIOLibMallocHeader);
363e13b1fa5SApple OSS Distributions #if IOALLOCDEBUG
364bb611c8fSApple OSS Distributions OSAddAtomicLong(-size, &debug_iomalloc_size);
365e13b1fa5SApple OSS Distributions #endif
366855239e5SApple OSS Distributions IOStatisticsAlloc(kIOStatisticsFree, size);
367e13b1fa5SApple OSS Distributions }
368e13b1fa5SApple OSS Distributions }
369e13b1fa5SApple OSS Distributions
3705c2921b0SApple OSS Distributions void *
3715c2921b0SApple OSS Distributions IOMalloc_external(
3725c2921b0SApple OSS Distributions vm_size_t size);
3735c2921b0SApple OSS Distributions void *
IOMalloc_external(vm_size_t size)3745c2921b0SApple OSS Distributions IOMalloc_external(
3755c2921b0SApple OSS Distributions vm_size_t size)
3765c2921b0SApple OSS Distributions {
3775c2921b0SApple OSS Distributions return IOMalloc_internal(KHEAP_DEFAULT, size, Z_VM_TAG_BT_BIT);
3785c2921b0SApple OSS Distributions }
3795c2921b0SApple OSS Distributions
380e6231be0SApple OSS Distributions void
IOFree(void * inAddress,vm_size_t size)381e6231be0SApple OSS Distributions IOFree(void * inAddress, vm_size_t size)
382e6231be0SApple OSS Distributions {
3831031c584SApple OSS Distributions IOFree_internal(KHEAP_DEFAULT, inAddress, size);
384e6231be0SApple OSS Distributions }
385e6231be0SApple OSS Distributions
386e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
387e13b1fa5SApple OSS Distributions
3885c2921b0SApple OSS Distributions void *
3895c2921b0SApple OSS Distributions IOMallocZero_external(
3905c2921b0SApple OSS Distributions vm_size_t size);
3915c2921b0SApple OSS Distributions void *
IOMallocZero_external(vm_size_t size)3925c2921b0SApple OSS Distributions IOMallocZero_external(
3935c2921b0SApple OSS Distributions vm_size_t size)
3945c2921b0SApple OSS Distributions {
3955c2921b0SApple OSS Distributions return IOMalloc_internal(KHEAP_DEFAULT, size, Z_ZERO_VM_TAG_BT_BIT);
3965c2921b0SApple OSS Distributions }
3975c2921b0SApple OSS Distributions
3985c2921b0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3995c2921b0SApple OSS Distributions
4000f3703acSApple OSS Distributions vm_tag_t
IOMemoryTag(vm_map_t map)4010f3703acSApple OSS Distributions IOMemoryTag(vm_map_t map)
4020f3703acSApple OSS Distributions {
4030f3703acSApple OSS Distributions vm_tag_t tag;
4040f3703acSApple OSS Distributions
405a5e72196SApple OSS Distributions if (!vm_kernel_map_is_kernel(map)) {
406a5e72196SApple OSS Distributions return VM_MEMORY_IOKIT;
407a5e72196SApple OSS Distributions }
4080f3703acSApple OSS Distributions
4090f3703acSApple OSS Distributions tag = vm_tag_bt();
410a5e72196SApple OSS Distributions if (tag == VM_KERN_MEMORY_NONE) {
411a5e72196SApple OSS Distributions tag = VM_KERN_MEMORY_IOKIT;
412a5e72196SApple OSS Distributions }
4130f3703acSApple OSS Distributions
414a5e72196SApple OSS Distributions return tag;
4150f3703acSApple OSS Distributions }
4160f3703acSApple OSS Distributions
4170f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4180f3703acSApple OSS Distributions
419a5e72196SApple OSS Distributions struct IOLibPageMallocHeader {
4205c2921b0SApple OSS Distributions mach_vm_size_t alignMask;
4215c2921b0SApple OSS Distributions mach_vm_offset_t allocationOffset;
4220f3703acSApple OSS Distributions #if IOTRACKING
4230f3703acSApple OSS Distributions IOTrackingAddress tracking;
4240f3703acSApple OSS Distributions #endif
4250f3703acSApple OSS Distributions };
4260f3703acSApple OSS Distributions
4270f3703acSApple OSS Distributions #if IOTRACKING
4280f3703acSApple OSS Distributions #define sizeofIOLibPageMallocHeader (sizeof(IOLibPageMallocHeader) - (TRACK_ALLOC ? 0 : sizeof(IOTrackingAddress)))
4290f3703acSApple OSS Distributions #else
4300f3703acSApple OSS Distributions #define sizeofIOLibPageMallocHeader (sizeof(IOLibPageMallocHeader))
4310f3703acSApple OSS Distributions #endif
4320f3703acSApple OSS Distributions
4330f3703acSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
4345c2921b0SApple OSS Distributions
4355c2921b0SApple OSS Distributions static __header_always_inline void
IOMallocAlignedSetHdr(IOLibPageMallocHeader * hdr,mach_vm_size_t alignMask,mach_vm_address_t allocationStart,mach_vm_address_t alignedStart)4365c2921b0SApple OSS Distributions IOMallocAlignedSetHdr(
4375c2921b0SApple OSS Distributions IOLibPageMallocHeader *hdr,
4385c2921b0SApple OSS Distributions mach_vm_size_t alignMask,
4395c2921b0SApple OSS Distributions mach_vm_address_t allocationStart,
4405c2921b0SApple OSS Distributions mach_vm_address_t alignedStart)
441bb611c8fSApple OSS Distributions {
4425c2921b0SApple OSS Distributions mach_vm_offset_t offset = alignedStart - allocationStart;
4435c2921b0SApple OSS Distributions #if __has_feature(ptrauth_calls)
4445c2921b0SApple OSS Distributions offset = (mach_vm_offset_t) ptrauth_sign_unauthenticated((void *)offset,
4455c2921b0SApple OSS Distributions ptrauth_key_process_independent_data,
4465c2921b0SApple OSS Distributions ptrauth_blend_discriminator((void *)(alignedStart | alignMask),
4475c2921b0SApple OSS Distributions OS_PTRAUTH_DISCRIMINATOR("IOLibPageMallocHeader.allocationOffset")));
4485c2921b0SApple OSS Distributions #endif /* __has_feature(ptrauth_calls) */
4495c2921b0SApple OSS Distributions hdr->allocationOffset = offset;
4505c2921b0SApple OSS Distributions hdr->alignMask = alignMask;
4515c2921b0SApple OSS Distributions }
4525c2921b0SApple OSS Distributions
4535c2921b0SApple OSS Distributions __abortlike
4545c2921b0SApple OSS Distributions static void
IOMallocAlignedHdrCorruptionPanic(mach_vm_offset_t offset,mach_vm_size_t alignMask,mach_vm_address_t alignedStart,vm_size_t size)4555c2921b0SApple OSS Distributions IOMallocAlignedHdrCorruptionPanic(
4565c2921b0SApple OSS Distributions mach_vm_offset_t offset,
4575c2921b0SApple OSS Distributions mach_vm_size_t alignMask,
4585c2921b0SApple OSS Distributions mach_vm_address_t alignedStart,
4595c2921b0SApple OSS Distributions vm_size_t size)
4605c2921b0SApple OSS Distributions {
4615c2921b0SApple OSS Distributions mach_vm_address_t address = 0;
4625c2921b0SApple OSS Distributions mach_vm_address_t recalAlignedStart = 0;
4635c2921b0SApple OSS Distributions
4645c2921b0SApple OSS Distributions if (os_sub_overflow(alignedStart, offset, &address)) {
4655c2921b0SApple OSS Distributions panic("Invalid offset %p for aligned addr %p", (void *)offset,
4665c2921b0SApple OSS Distributions (void *)alignedStart);
4675c2921b0SApple OSS Distributions }
4685c2921b0SApple OSS Distributions if (os_add3_overflow(address, sizeofIOLibPageMallocHeader, alignMask,
4695c2921b0SApple OSS Distributions &recalAlignedStart)) {
4705c2921b0SApple OSS Distributions panic("alignMask 0x%llx overflows recalAlignedStart %p for provided addr "
4715c2921b0SApple OSS Distributions "%p", alignMask, (void *)recalAlignedStart, (void *)alignedStart);
4725c2921b0SApple OSS Distributions }
4735c2921b0SApple OSS Distributions if (((recalAlignedStart &= ~alignMask) != alignedStart) &&
4745c2921b0SApple OSS Distributions (round_page(recalAlignedStart) != alignedStart)) {
4755c2921b0SApple OSS Distributions panic("Recalculated aligned addr %p doesn't match provided addr %p",
4765c2921b0SApple OSS Distributions (void *)recalAlignedStart, (void *)alignedStart);
4775c2921b0SApple OSS Distributions }
4785c2921b0SApple OSS Distributions if (offset < sizeofIOLibPageMallocHeader) {
4795c2921b0SApple OSS Distributions panic("Offset %zd doesn't accomodate IOLibPageMallocHeader for aligned "
4805c2921b0SApple OSS Distributions "addr %p", (size_t)offset, (void *)alignedStart);
4815c2921b0SApple OSS Distributions }
4825c2921b0SApple OSS Distributions panic("alignMask 0x%llx overflows adjusted size %zd for aligned addr %p",
4835c2921b0SApple OSS Distributions alignMask, (size_t)size, (void *)alignedStart);
4845c2921b0SApple OSS Distributions }
4855c2921b0SApple OSS Distributions
4865c2921b0SApple OSS Distributions static __header_always_inline mach_vm_address_t
IOMallocAlignedGetAddress(IOLibPageMallocHeader * hdr,mach_vm_address_t alignedStart,vm_size_t * size)4875c2921b0SApple OSS Distributions IOMallocAlignedGetAddress(
4885c2921b0SApple OSS Distributions IOLibPageMallocHeader *hdr,
4895c2921b0SApple OSS Distributions mach_vm_address_t alignedStart,
4905c2921b0SApple OSS Distributions vm_size_t *size)
4915c2921b0SApple OSS Distributions {
4925c2921b0SApple OSS Distributions mach_vm_address_t address = 0;
4935c2921b0SApple OSS Distributions mach_vm_address_t recalAlignedStart = 0;
4945c2921b0SApple OSS Distributions mach_vm_offset_t offset = hdr->allocationOffset;
4955c2921b0SApple OSS Distributions mach_vm_size_t alignMask = hdr->alignMask;
4965c2921b0SApple OSS Distributions #if __has_feature(ptrauth_calls)
4975c2921b0SApple OSS Distributions offset = (mach_vm_offset_t) ptrauth_auth_data((void *)offset,
4985c2921b0SApple OSS Distributions ptrauth_key_process_independent_data,
4995c2921b0SApple OSS Distributions ptrauth_blend_discriminator((void *)(alignedStart | alignMask),
5005c2921b0SApple OSS Distributions OS_PTRAUTH_DISCRIMINATOR("IOLibPageMallocHeader.allocationOffset")));
5015c2921b0SApple OSS Distributions #endif /* __has_feature(ptrauth_calls) */
5025c2921b0SApple OSS Distributions if (os_sub_overflow(alignedStart, offset, &address) ||
5035c2921b0SApple OSS Distributions os_add3_overflow(address, sizeofIOLibPageMallocHeader, alignMask,
5045c2921b0SApple OSS Distributions &recalAlignedStart) ||
5055c2921b0SApple OSS Distributions (((recalAlignedStart &= ~alignMask) != alignedStart) &&
5065c2921b0SApple OSS Distributions (round_page(recalAlignedStart) != alignedStart)) ||
5075c2921b0SApple OSS Distributions (offset < sizeofIOLibPageMallocHeader) ||
5085c2921b0SApple OSS Distributions os_add_overflow(*size, alignMask, size)) {
5095c2921b0SApple OSS Distributions IOMallocAlignedHdrCorruptionPanic(offset, alignMask, alignedStart, *size);
5105c2921b0SApple OSS Distributions }
5115c2921b0SApple OSS Distributions return address;
512bb611c8fSApple OSS Distributions }
5130f3703acSApple OSS Distributions
514a5e72196SApple OSS Distributions void *
5155c2921b0SApple OSS Distributions (IOMallocAligned_internal)(struct kalloc_heap *kheap, vm_size_t size,
5165c2921b0SApple OSS Distributions vm_size_t alignment, zalloc_flags_t flags)
517e13b1fa5SApple OSS Distributions {
518e13b1fa5SApple OSS Distributions kern_return_t kr;
5193ca3bd55SApple OSS Distributions vm_offset_t address;
5203ca3bd55SApple OSS Distributions vm_offset_t allocationAddress;
521e13b1fa5SApple OSS Distributions vm_size_t adjustedSize;
5223ca3bd55SApple OSS Distributions uintptr_t alignMask;
5230f3703acSApple OSS Distributions IOLibPageMallocHeader * hdr;
5245c2921b0SApple OSS Distributions kma_flags_t kma_flags = KMA_NONE;
525e13b1fa5SApple OSS Distributions
526a5e72196SApple OSS Distributions if (size == 0) {
527a5e72196SApple OSS Distributions return NULL;
528a5e72196SApple OSS Distributions }
529bb611c8fSApple OSS Distributions if (((uint32_t) alignment) != alignment) {
530bb611c8fSApple OSS Distributions return NULL;
531bb611c8fSApple OSS Distributions }
532e13b1fa5SApple OSS Distributions
5335c2921b0SApple OSS Distributions if (flags & Z_ZERO) {
5345c2921b0SApple OSS Distributions kma_flags = KMA_ZERO;
5355c2921b0SApple OSS Distributions }
5365c2921b0SApple OSS Distributions
5375c2921b0SApple OSS Distributions if (kheap == KHEAP_DATA_BUFFERS) {
5385c2921b0SApple OSS Distributions kma_flags = (kma_flags_t) (kma_flags | KMA_DATA);
5395c2921b0SApple OSS Distributions }
5405c2921b0SApple OSS Distributions
541bb611c8fSApple OSS Distributions alignment = (1UL << log2up((uint32_t) alignment));
542e13b1fa5SApple OSS Distributions alignMask = alignment - 1;
5430f3703acSApple OSS Distributions adjustedSize = size + sizeofIOLibPageMallocHeader;
544e13b1fa5SApple OSS Distributions
545d0c1fef6SApple OSS Distributions if (size > adjustedSize) {
546d0c1fef6SApple OSS Distributions address = 0; /* overflow detected */
547a5e72196SApple OSS Distributions } else if (adjustedSize >= page_size) {
5485c2921b0SApple OSS Distributions kr = kernel_memory_allocate(kernel_map, &address,
5495c2921b0SApple OSS Distributions size, alignMask, kma_flags, IOMemoryTag(kernel_map));
550a5e72196SApple OSS Distributions if (KERN_SUCCESS != kr) {
551a5e72196SApple OSS Distributions address = 0;
552a5e72196SApple OSS Distributions }
5530f3703acSApple OSS Distributions #if IOTRACKING
554a5e72196SApple OSS Distributions else if (TRACK_ALLOC) {
555a5e72196SApple OSS Distributions IOTrackingAlloc(gIOMallocTracking, address, size);
556a5e72196SApple OSS Distributions }
5570f3703acSApple OSS Distributions #endif
558e13b1fa5SApple OSS Distributions } else {
559e13b1fa5SApple OSS Distributions adjustedSize += alignMask;
560e13b1fa5SApple OSS Distributions
561e13b1fa5SApple OSS Distributions if (adjustedSize >= page_size) {
5625c2921b0SApple OSS Distributions kr = kmem_alloc(kernel_map, &allocationAddress,
5635c2921b0SApple OSS Distributions adjustedSize, kma_flags, IOMemoryTag(kernel_map));
564a5e72196SApple OSS Distributions if (KERN_SUCCESS != kr) {
565a5e72196SApple OSS Distributions allocationAddress = 0;
566a5e72196SApple OSS Distributions }
567a5e72196SApple OSS Distributions } else {
568e7776783SApple OSS Distributions allocationAddress = (vm_address_t) kheap_alloc(kheap,
5695c2921b0SApple OSS Distributions adjustedSize, Z_VM_TAG(Z_WAITOK | flags, VM_KERN_MEMORY_IOKIT));
570a5e72196SApple OSS Distributions }
571e13b1fa5SApple OSS Distributions
572e13b1fa5SApple OSS Distributions if (allocationAddress) {
5730f3703acSApple OSS Distributions address = (allocationAddress + alignMask + sizeofIOLibPageMallocHeader)
574e13b1fa5SApple OSS Distributions & (~alignMask);
575e13b1fa5SApple OSS Distributions
5760f3703acSApple OSS Distributions hdr = (typeof(hdr))(address - sizeofIOLibPageMallocHeader);
5775c2921b0SApple OSS Distributions IOMallocAlignedSetHdr(hdr, alignMask, allocationAddress, address);
5780f3703acSApple OSS Distributions #if IOTRACKING
5790f3703acSApple OSS Distributions if (TRACK_ALLOC) {
5800f3703acSApple OSS Distributions bzero(&hdr->tracking, sizeof(hdr->tracking));
5810f3703acSApple OSS Distributions hdr->tracking.address = ~address;
5820f3703acSApple OSS Distributions hdr->tracking.size = size;
58376e12aa3SApple OSS Distributions IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true, VM_KERN_MEMORY_NONE);
5840f3703acSApple OSS Distributions }
5850f3703acSApple OSS Distributions #endif
586a5e72196SApple OSS Distributions } else {
587e13b1fa5SApple OSS Distributions address = 0;
588e13b1fa5SApple OSS Distributions }
589a5e72196SApple OSS Distributions }
590e13b1fa5SApple OSS Distributions
591e13b1fa5SApple OSS Distributions assert(0 == (address & alignMask));
592e13b1fa5SApple OSS Distributions
593e13b1fa5SApple OSS Distributions if (address) {
594855239e5SApple OSS Distributions #if IOALLOCDEBUG
595bb611c8fSApple OSS Distributions OSAddAtomicLong(size, &debug_iomalloc_size);
596e13b1fa5SApple OSS Distributions #endif
597855239e5SApple OSS Distributions IOStatisticsAlloc(kIOStatisticsMallocAligned, size);
598855239e5SApple OSS Distributions }
599e13b1fa5SApple OSS Distributions
600e13b1fa5SApple OSS Distributions return (void *) address;
601e13b1fa5SApple OSS Distributions }
602e13b1fa5SApple OSS Distributions
603a5e72196SApple OSS Distributions void
IOFreeAligned_internal(kalloc_heap_t kheap,void * address,vm_size_t size)604e6231be0SApple OSS Distributions IOFreeAligned_internal(kalloc_heap_t kheap, void * address, vm_size_t size)
605e13b1fa5SApple OSS Distributions {
606e13b1fa5SApple OSS Distributions vm_address_t allocationAddress;
607e13b1fa5SApple OSS Distributions vm_size_t adjustedSize;
6080f3703acSApple OSS Distributions IOLibPageMallocHeader * hdr;
609e13b1fa5SApple OSS Distributions
610a5e72196SApple OSS Distributions if (!address) {
611e13b1fa5SApple OSS Distributions return;
612a5e72196SApple OSS Distributions }
613e13b1fa5SApple OSS Distributions
614e13b1fa5SApple OSS Distributions assert(size);
615e13b1fa5SApple OSS Distributions
6160f3703acSApple OSS Distributions adjustedSize = size + sizeofIOLibPageMallocHeader;
617e13b1fa5SApple OSS Distributions if (adjustedSize >= page_size) {
6180f3703acSApple OSS Distributions #if IOTRACKING
619a5e72196SApple OSS Distributions if (TRACK_ALLOC) {
620a5e72196SApple OSS Distributions IOTrackingFree(gIOMallocTracking, (uintptr_t) address, size);
621a5e72196SApple OSS Distributions }
6220f3703acSApple OSS Distributions #endif
6235c2921b0SApple OSS Distributions kmem_free(kernel_map, (vm_offset_t) address, size);
624e13b1fa5SApple OSS Distributions } else {
6250f3703acSApple OSS Distributions hdr = (typeof(hdr))(((uintptr_t)address) - sizeofIOLibPageMallocHeader);
6265c2921b0SApple OSS Distributions allocationAddress = IOMallocAlignedGetAddress(hdr,
6275c2921b0SApple OSS Distributions (mach_vm_address_t)address, &adjustedSize);
628e13b1fa5SApple OSS Distributions
6290f3703acSApple OSS Distributions #if IOTRACKING
630a5e72196SApple OSS Distributions if (TRACK_ALLOC) {
631a5e72196SApple OSS Distributions if (size != hdr->tracking.size) {
632e7776783SApple OSS Distributions OSReportWithBacktrace("bad IOFreeAligned size 0x%zx should be 0x%zx",
633e7776783SApple OSS Distributions (size_t)size, (size_t)hdr->tracking.size);
6340f3703acSApple OSS Distributions size = hdr->tracking.size;
6350f3703acSApple OSS Distributions }
6365c2921b0SApple OSS Distributions IOTrackingRemoveAddress(gIOMallocTracking, &hdr->tracking, size);
6370f3703acSApple OSS Distributions }
6380f3703acSApple OSS Distributions #endif
6390f3703acSApple OSS Distributions if (adjustedSize >= page_size) {
6405c2921b0SApple OSS Distributions kmem_free(kernel_map, allocationAddress, adjustedSize);
6410f3703acSApple OSS Distributions } else {
642e6231be0SApple OSS Distributions kheap_free(kheap, allocationAddress, adjustedSize);
643e13b1fa5SApple OSS Distributions }
6440f3703acSApple OSS Distributions }
645e13b1fa5SApple OSS Distributions
646e13b1fa5SApple OSS Distributions #if IOALLOCDEBUG
647bb611c8fSApple OSS Distributions OSAddAtomicLong(-size, &debug_iomalloc_size);
648e13b1fa5SApple OSS Distributions #endif
649855239e5SApple OSS Distributions
650855239e5SApple OSS Distributions IOStatisticsAlloc(kIOStatisticsFreeAligned, size);
651e13b1fa5SApple OSS Distributions }
652e13b1fa5SApple OSS Distributions
6535c2921b0SApple OSS Distributions void *
6545c2921b0SApple OSS Distributions IOMallocAligned_external(
6555c2921b0SApple OSS Distributions vm_size_t size, vm_size_t alignment);
6565c2921b0SApple OSS Distributions void *
IOMallocAligned_external(vm_size_t size,vm_size_t alignment)6575c2921b0SApple OSS Distributions IOMallocAligned_external(
6585c2921b0SApple OSS Distributions vm_size_t size, vm_size_t alignment)
6595c2921b0SApple OSS Distributions {
6605c2921b0SApple OSS Distributions return IOMallocAligned_internal(KHEAP_DATA_BUFFERS, size, alignment,
6615c2921b0SApple OSS Distributions Z_VM_TAG_BT_BIT);
6625c2921b0SApple OSS Distributions }
6635c2921b0SApple OSS Distributions
6645c2921b0SApple OSS Distributions void
IOFreeAligned(void * address,vm_size_t size)6655c2921b0SApple OSS Distributions IOFreeAligned(
6665c2921b0SApple OSS Distributions void * address,
6675c2921b0SApple OSS Distributions vm_size_t size)
6685c2921b0SApple OSS Distributions {
6695c2921b0SApple OSS Distributions IOFreeAligned_internal(KHEAP_DATA_BUFFERS, address, size);
6705c2921b0SApple OSS Distributions }
6715c2921b0SApple OSS Distributions
6725c2921b0SApple OSS Distributions __typed_allocators_ignore_pop
6735c2921b0SApple OSS Distributions
674e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
675e13b1fa5SApple OSS Distributions
676e13b1fa5SApple OSS Distributions void
IOKernelFreePhysical(kalloc_heap_t kheap,mach_vm_address_t address,mach_vm_size_t size)677e6231be0SApple OSS Distributions IOKernelFreePhysical(
678e6231be0SApple OSS Distributions kalloc_heap_t kheap,
679e6231be0SApple OSS Distributions mach_vm_address_t address,
680e6231be0SApple OSS Distributions mach_vm_size_t size)
681e13b1fa5SApple OSS Distributions {
682bb611c8fSApple OSS Distributions vm_address_t allocationAddress;
683bb611c8fSApple OSS Distributions vm_size_t adjustedSize;
6840f3703acSApple OSS Distributions IOLibPageMallocHeader * hdr;
685e13b1fa5SApple OSS Distributions
686a5e72196SApple OSS Distributions if (!address) {
687e13b1fa5SApple OSS Distributions return;
688a5e72196SApple OSS Distributions }
689e13b1fa5SApple OSS Distributions
690e13b1fa5SApple OSS Distributions assert(size);
691e13b1fa5SApple OSS Distributions
6920f3703acSApple OSS Distributions adjustedSize = (2 * size) + sizeofIOLibPageMallocHeader;
693e13b1fa5SApple OSS Distributions if (adjustedSize >= page_size) {
6940f3703acSApple OSS Distributions #if IOTRACKING
695a5e72196SApple OSS Distributions if (TRACK_ALLOC) {
696a5e72196SApple OSS Distributions IOTrackingFree(gIOMallocTracking, address, size);
697a5e72196SApple OSS Distributions }
6980f3703acSApple OSS Distributions #endif
6995c2921b0SApple OSS Distributions kmem_free(kernel_map, (vm_offset_t) address, size);
700e13b1fa5SApple OSS Distributions } else {
7010f3703acSApple OSS Distributions hdr = (typeof(hdr))(((uintptr_t)address) - sizeofIOLibPageMallocHeader);
7025c2921b0SApple OSS Distributions allocationAddress = IOMallocAlignedGetAddress(hdr, address, &adjustedSize);
7030f3703acSApple OSS Distributions #if IOTRACKING
704a5e72196SApple OSS Distributions if (TRACK_ALLOC) {
7055c2921b0SApple OSS Distributions IOTrackingRemoveAddress(gIOMallocTracking, &hdr->tracking, size);
706a5e72196SApple OSS Distributions }
7070f3703acSApple OSS Distributions #endif
7085c2921b0SApple OSS Distributions __typed_allocators_ignore(kheap_free(kheap, allocationAddress, adjustedSize));
709e13b1fa5SApple OSS Distributions }
710e13b1fa5SApple OSS Distributions
711d0c1fef6SApple OSS Distributions IOStatisticsAlloc(kIOStatisticsFreeContiguous, size);
712e13b1fa5SApple OSS Distributions #if IOALLOCDEBUG
713bb611c8fSApple OSS Distributions OSAddAtomicLong(-size, &debug_iomalloc_size);
714e13b1fa5SApple OSS Distributions #endif
715e13b1fa5SApple OSS Distributions }
716e13b1fa5SApple OSS Distributions
7175c2921b0SApple OSS Distributions #if __arm64__
71876e12aa3SApple OSS Distributions extern unsigned long gPhysBase, gPhysSize;
71976e12aa3SApple OSS Distributions #endif
720a3bb9fccSApple OSS Distributions
721e13b1fa5SApple OSS Distributions mach_vm_address_t
IOKernelAllocateWithPhysicalRestrict(kalloc_heap_t kheap,mach_vm_size_t size,mach_vm_address_t maxPhys,mach_vm_size_t alignment,bool contiguous)722e6231be0SApple OSS Distributions IOKernelAllocateWithPhysicalRestrict(
723e6231be0SApple OSS Distributions kalloc_heap_t kheap,
724e6231be0SApple OSS Distributions mach_vm_size_t size,
725e6231be0SApple OSS Distributions mach_vm_address_t maxPhys,
726e6231be0SApple OSS Distributions mach_vm_size_t alignment,
727e6231be0SApple OSS Distributions bool contiguous)
728e13b1fa5SApple OSS Distributions {
729e13b1fa5SApple OSS Distributions kern_return_t kr;
730e13b1fa5SApple OSS Distributions mach_vm_address_t address;
731e13b1fa5SApple OSS Distributions mach_vm_address_t allocationAddress;
732e13b1fa5SApple OSS Distributions mach_vm_size_t adjustedSize;
733e13b1fa5SApple OSS Distributions mach_vm_address_t alignMask;
7340f3703acSApple OSS Distributions IOLibPageMallocHeader * hdr;
735e13b1fa5SApple OSS Distributions
736a5e72196SApple OSS Distributions if (size == 0) {
737a5e72196SApple OSS Distributions return 0;
738a5e72196SApple OSS Distributions }
739a5e72196SApple OSS Distributions if (alignment == 0) {
740e13b1fa5SApple OSS Distributions alignment = 1;
741a5e72196SApple OSS Distributions }
742e13b1fa5SApple OSS Distributions
743e13b1fa5SApple OSS Distributions alignMask = alignment - 1;
744cc9a6355SApple OSS Distributions
745a5e72196SApple OSS Distributions if (os_mul_and_add_overflow(2, size, sizeofIOLibPageMallocHeader, &adjustedSize)) {
746a5e72196SApple OSS Distributions return 0;
747a5e72196SApple OSS Distributions }
748e13b1fa5SApple OSS Distributions
749855239e5SApple OSS Distributions contiguous = (contiguous && (adjustedSize > page_size))
750855239e5SApple OSS Distributions || (alignment > page_size);
751855239e5SApple OSS Distributions
752a5e72196SApple OSS Distributions if (contiguous || maxPhys) {
7535c2921b0SApple OSS Distributions kma_flags_t options = KMA_ZERO;
754e13b1fa5SApple OSS Distributions vm_offset_t virt;
755855239e5SApple OSS Distributions
7565c2921b0SApple OSS Distributions if (kheap == KHEAP_DATA_BUFFERS) {
7575c2921b0SApple OSS Distributions options = (kma_flags_t) (options | KMA_DATA);
7585c2921b0SApple OSS Distributions }
7595c2921b0SApple OSS Distributions
760e13b1fa5SApple OSS Distributions adjustedSize = size;
761855239e5SApple OSS Distributions contiguous = (contiguous && (adjustedSize > page_size))
762855239e5SApple OSS Distributions || (alignment > page_size);
763855239e5SApple OSS Distributions
764a5e72196SApple OSS Distributions if (!contiguous) {
7655c2921b0SApple OSS Distributions #if __arm64__
766a5e72196SApple OSS Distributions if (maxPhys >= (mach_vm_address_t)(gPhysBase + gPhysSize)) {
76776e12aa3SApple OSS Distributions maxPhys = 0;
768a5e72196SApple OSS Distributions } else
76976e12aa3SApple OSS Distributions #endif
770a5e72196SApple OSS Distributions if (maxPhys <= 0xFFFFFFFF) {
771855239e5SApple OSS Distributions maxPhys = 0;
772e6231be0SApple OSS Distributions options = (kma_flags_t)(options | KMA_LOMEM);
773a5e72196SApple OSS Distributions } else if (gIOLastPage && (atop_64(maxPhys) > gIOLastPage)) {
774d0c1fef6SApple OSS Distributions maxPhys = 0;
775d0c1fef6SApple OSS Distributions }
776d0c1fef6SApple OSS Distributions }
777a5e72196SApple OSS Distributions if (contiguous || maxPhys) {
7785c2921b0SApple OSS Distributions kr = kmem_alloc_contig(kernel_map, &virt, size,
779e6231be0SApple OSS Distributions alignMask, (ppnum_t) atop(maxPhys), (ppnum_t) atop(alignMask),
7805c2921b0SApple OSS Distributions options, IOMemoryTag(kernel_map));
781a5e72196SApple OSS Distributions } else {
7825c2921b0SApple OSS Distributions kr = kernel_memory_allocate(kernel_map, &virt,
7830f3703acSApple OSS Distributions size, alignMask, options, IOMemoryTag(kernel_map));
784e13b1fa5SApple OSS Distributions }
785a5e72196SApple OSS Distributions if (KERN_SUCCESS == kr) {
786e13b1fa5SApple OSS Distributions address = virt;
7870f3703acSApple OSS Distributions #if IOTRACKING
788a5e72196SApple OSS Distributions if (TRACK_ALLOC) {
789a5e72196SApple OSS Distributions IOTrackingAlloc(gIOMallocTracking, address, size);
7900f3703acSApple OSS Distributions }
791a5e72196SApple OSS Distributions #endif
792a5e72196SApple OSS Distributions } else {
793e13b1fa5SApple OSS Distributions address = 0;
794e13b1fa5SApple OSS Distributions }
795a5e72196SApple OSS Distributions } else {
796e13b1fa5SApple OSS Distributions adjustedSize += alignMask;
797a5e72196SApple OSS Distributions if (adjustedSize < size) {
798a5e72196SApple OSS Distributions return 0;
799a5e72196SApple OSS Distributions }
8005c2921b0SApple OSS Distributions /* BEGIN IGNORE CODESTYLE */
8015c2921b0SApple OSS Distributions __typed_allocators_ignore_push // allocator implementation
802e7776783SApple OSS Distributions allocationAddress = (mach_vm_address_t) kheap_alloc(kheap,
803e7776783SApple OSS Distributions adjustedSize, Z_VM_TAG_BT(Z_WAITOK, VM_KERN_MEMORY_IOKIT));
8045c2921b0SApple OSS Distributions __typed_allocators_ignore_pop
8055c2921b0SApple OSS Distributions /* END IGNORE CODESTYLE */
806e13b1fa5SApple OSS Distributions
807e13b1fa5SApple OSS Distributions if (allocationAddress) {
8080f3703acSApple OSS Distributions address = (allocationAddress + alignMask + sizeofIOLibPageMallocHeader)
809e13b1fa5SApple OSS Distributions & (~alignMask);
810e13b1fa5SApple OSS Distributions
811a5e72196SApple OSS Distributions if (atop_32(address) != atop_32(address + size - 1)) {
8123ca3bd55SApple OSS Distributions address = round_page(address);
813a5e72196SApple OSS Distributions }
814e13b1fa5SApple OSS Distributions
8150f3703acSApple OSS Distributions hdr = (typeof(hdr))(address - sizeofIOLibPageMallocHeader);
8165c2921b0SApple OSS Distributions IOMallocAlignedSetHdr(hdr, alignMask, allocationAddress, address);
8170f3703acSApple OSS Distributions #if IOTRACKING
8180f3703acSApple OSS Distributions if (TRACK_ALLOC) {
8190f3703acSApple OSS Distributions bzero(&hdr->tracking, sizeof(hdr->tracking));
8200f3703acSApple OSS Distributions hdr->tracking.address = ~address;
8210f3703acSApple OSS Distributions hdr->tracking.size = size;
82276e12aa3SApple OSS Distributions IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true, VM_KERN_MEMORY_NONE);
8230f3703acSApple OSS Distributions }
8240f3703acSApple OSS Distributions #endif
825a5e72196SApple OSS Distributions } else {
826e13b1fa5SApple OSS Distributions address = 0;
827e13b1fa5SApple OSS Distributions }
828a5e72196SApple OSS Distributions }
829e13b1fa5SApple OSS Distributions
830e13b1fa5SApple OSS Distributions if (address) {
831d0c1fef6SApple OSS Distributions IOStatisticsAlloc(kIOStatisticsMallocContiguous, size);
832d0c1fef6SApple OSS Distributions #if IOALLOCDEBUG
833bb611c8fSApple OSS Distributions OSAddAtomicLong(size, &debug_iomalloc_size);
834e13b1fa5SApple OSS Distributions #endif
835d0c1fef6SApple OSS Distributions }
836e13b1fa5SApple OSS Distributions
837a5e72196SApple OSS Distributions return address;
838e13b1fa5SApple OSS Distributions }
839e13b1fa5SApple OSS Distributions
840855239e5SApple OSS Distributions
841e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
842e13b1fa5SApple OSS Distributions
843a5e72196SApple OSS Distributions struct _IOMallocContiguousEntry {
844e13b1fa5SApple OSS Distributions mach_vm_address_t virtualAddr;
845e13b1fa5SApple OSS Distributions IOBufferMemoryDescriptor * md;
846e13b1fa5SApple OSS Distributions queue_chain_t link;
847e13b1fa5SApple OSS Distributions };
848e13b1fa5SApple OSS Distributions typedef struct _IOMallocContiguousEntry _IOMallocContiguousEntry;
849e13b1fa5SApple OSS Distributions
850a5e72196SApple OSS Distributions void *
IOMallocContiguous(vm_size_t size,vm_size_t alignment,IOPhysicalAddress * physicalAddress)851a5e72196SApple OSS Distributions IOMallocContiguous(vm_size_t size, vm_size_t alignment,
852e13b1fa5SApple OSS Distributions IOPhysicalAddress * physicalAddress)
853e13b1fa5SApple OSS Distributions {
854e13b1fa5SApple OSS Distributions mach_vm_address_t address = 0;
855e13b1fa5SApple OSS Distributions
856a5e72196SApple OSS Distributions if (size == 0) {
857a5e72196SApple OSS Distributions return NULL;
858a5e72196SApple OSS Distributions }
859a5e72196SApple OSS Distributions if (alignment == 0) {
860e13b1fa5SApple OSS Distributions alignment = 1;
861a5e72196SApple OSS Distributions }
862e13b1fa5SApple OSS Distributions
863e13b1fa5SApple OSS Distributions /* Do we want a physical address? */
864a5e72196SApple OSS Distributions if (!physicalAddress) {
8655c2921b0SApple OSS Distributions address = IOKernelAllocateWithPhysicalRestrict(KHEAP_DEFAULT,
866e6231be0SApple OSS Distributions size, 0 /*maxPhys*/, alignment, true);
867a5e72196SApple OSS Distributions } else {
868a5e72196SApple OSS Distributions do {
869e13b1fa5SApple OSS Distributions IOBufferMemoryDescriptor * bmd;
870e13b1fa5SApple OSS Distributions mach_vm_address_t physicalMask;
871e13b1fa5SApple OSS Distributions vm_offset_t alignMask;
872e13b1fa5SApple OSS Distributions
873e13b1fa5SApple OSS Distributions alignMask = alignment - 1;
8743ca3bd55SApple OSS Distributions physicalMask = (0xFFFFFFFF ^ alignMask);
8753ca3bd55SApple OSS Distributions
876e13b1fa5SApple OSS Distributions bmd = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(
877e13b1fa5SApple OSS Distributions kernel_task, kIOMemoryPhysicallyContiguous, size, physicalMask);
878a5e72196SApple OSS Distributions if (!bmd) {
879e13b1fa5SApple OSS Distributions break;
880a5e72196SApple OSS Distributions }
881e13b1fa5SApple OSS Distributions
882e13b1fa5SApple OSS Distributions _IOMallocContiguousEntry *
883e6231be0SApple OSS Distributions entry = IOMallocType(_IOMallocContiguousEntry);
884a5e72196SApple OSS Distributions if (!entry) {
885e13b1fa5SApple OSS Distributions bmd->release();
886e13b1fa5SApple OSS Distributions break;
887e13b1fa5SApple OSS Distributions }
888e13b1fa5SApple OSS Distributions entry->virtualAddr = (mach_vm_address_t) bmd->getBytesNoCopy();
889e13b1fa5SApple OSS Distributions entry->md = bmd;
890e13b1fa5SApple OSS Distributions lck_mtx_lock(gIOMallocContiguousEntriesLock);
891e13b1fa5SApple OSS Distributions queue_enter( &gIOMallocContiguousEntries, entry,
892e13b1fa5SApple OSS Distributions _IOMallocContiguousEntry *, link );
893e13b1fa5SApple OSS Distributions lck_mtx_unlock(gIOMallocContiguousEntriesLock);
894e13b1fa5SApple OSS Distributions
895e13b1fa5SApple OSS Distributions address = (mach_vm_address_t) entry->virtualAddr;
896e13b1fa5SApple OSS Distributions *physicalAddress = bmd->getPhysicalAddress();
897a5e72196SApple OSS Distributions }while (false);
898e13b1fa5SApple OSS Distributions }
899e13b1fa5SApple OSS Distributions
900e13b1fa5SApple OSS Distributions return (void *) address;
901e13b1fa5SApple OSS Distributions }
902e13b1fa5SApple OSS Distributions
903a5e72196SApple OSS Distributions void
IOFreeContiguous(void * _address,vm_size_t size)904a5e72196SApple OSS Distributions IOFreeContiguous(void * _address, vm_size_t size)
905e13b1fa5SApple OSS Distributions {
906e13b1fa5SApple OSS Distributions _IOMallocContiguousEntry * entry;
907e13b1fa5SApple OSS Distributions IOMemoryDescriptor * md = NULL;
908e13b1fa5SApple OSS Distributions
909e13b1fa5SApple OSS Distributions mach_vm_address_t address = (mach_vm_address_t) _address;
910e13b1fa5SApple OSS Distributions
911a5e72196SApple OSS Distributions if (!address) {
912e13b1fa5SApple OSS Distributions return;
913a5e72196SApple OSS Distributions }
914e13b1fa5SApple OSS Distributions
915e13b1fa5SApple OSS Distributions assert(size);
916e13b1fa5SApple OSS Distributions
917e13b1fa5SApple OSS Distributions lck_mtx_lock(gIOMallocContiguousEntriesLock);
918e13b1fa5SApple OSS Distributions queue_iterate( &gIOMallocContiguousEntries, entry,
919e13b1fa5SApple OSS Distributions _IOMallocContiguousEntry *, link )
920e13b1fa5SApple OSS Distributions {
921e13b1fa5SApple OSS Distributions if (entry->virtualAddr == address) {
922e13b1fa5SApple OSS Distributions md = entry->md;
923e13b1fa5SApple OSS Distributions queue_remove( &gIOMallocContiguousEntries, entry,
924e13b1fa5SApple OSS Distributions _IOMallocContiguousEntry *, link );
925e13b1fa5SApple OSS Distributions break;
926e13b1fa5SApple OSS Distributions }
927e13b1fa5SApple OSS Distributions }
928e13b1fa5SApple OSS Distributions lck_mtx_unlock(gIOMallocContiguousEntriesLock);
929e13b1fa5SApple OSS Distributions
930a5e72196SApple OSS Distributions if (md) {
931e13b1fa5SApple OSS Distributions md->release();
932e6231be0SApple OSS Distributions IOFreeType(entry, _IOMallocContiguousEntry);
933a5e72196SApple OSS Distributions } else {
9345c2921b0SApple OSS Distributions IOKernelFreePhysical(KHEAP_DEFAULT, (mach_vm_address_t) address, size);
935e13b1fa5SApple OSS Distributions }
936e13b1fa5SApple OSS Distributions }
937e13b1fa5SApple OSS Distributions
938e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
939e13b1fa5SApple OSS Distributions
940a5e72196SApple OSS Distributions kern_return_t
IOIteratePageableMaps(vm_size_t size,IOIteratePageableMapsCallback callback,void * ref)941a5e72196SApple OSS Distributions IOIteratePageableMaps(vm_size_t size,
942e13b1fa5SApple OSS Distributions IOIteratePageableMapsCallback callback, void * ref)
943e13b1fa5SApple OSS Distributions {
944e13b1fa5SApple OSS Distributions kern_return_t kr = kIOReturnNotReady;
9455c2921b0SApple OSS Distributions kmem_return_t kmr;
946e13b1fa5SApple OSS Distributions vm_size_t segSize;
947e13b1fa5SApple OSS Distributions UInt32 attempts;
948e13b1fa5SApple OSS Distributions UInt32 index;
9495c2921b0SApple OSS Distributions mach_vm_offset_t min;
9505c2921b0SApple OSS Distributions int flags;
951e13b1fa5SApple OSS Distributions
952a5e72196SApple OSS Distributions if (size > kIOPageableMaxMapSize) {
953a5e72196SApple OSS Distributions return kIOReturnBadArgument;
954a5e72196SApple OSS Distributions }
955e13b1fa5SApple OSS Distributions
956e13b1fa5SApple OSS Distributions do {
957e13b1fa5SApple OSS Distributions index = gIOKitPageableSpace.hint;
958e13b1fa5SApple OSS Distributions attempts = gIOKitPageableSpace.count;
959e13b1fa5SApple OSS Distributions while (attempts--) {
960e13b1fa5SApple OSS Distributions kr = (*callback)(gIOKitPageableSpace.maps[index].map, ref);
961e13b1fa5SApple OSS Distributions if (KERN_SUCCESS == kr) {
962e13b1fa5SApple OSS Distributions gIOKitPageableSpace.hint = index;
963e13b1fa5SApple OSS Distributions break;
964e13b1fa5SApple OSS Distributions }
965a5e72196SApple OSS Distributions if (index) {
966e13b1fa5SApple OSS Distributions index--;
967a5e72196SApple OSS Distributions } else {
968e13b1fa5SApple OSS Distributions index = gIOKitPageableSpace.count - 1;
969e13b1fa5SApple OSS Distributions }
970a5e72196SApple OSS Distributions }
971a5e72196SApple OSS Distributions if (KERN_NO_SPACE != kr) {
972e13b1fa5SApple OSS Distributions break;
973a5e72196SApple OSS Distributions }
974e13b1fa5SApple OSS Distributions
975e13b1fa5SApple OSS Distributions lck_mtx_lock( gIOKitPageableSpace.lock );
976e13b1fa5SApple OSS Distributions
977e13b1fa5SApple OSS Distributions index = gIOKitPageableSpace.count;
9788d741a5dSApple OSS Distributions if (index >= kIOMaxPageableMaps) {
979e13b1fa5SApple OSS Distributions lck_mtx_unlock( gIOKitPageableSpace.lock );
980e13b1fa5SApple OSS Distributions break;
981e13b1fa5SApple OSS Distributions }
982e13b1fa5SApple OSS Distributions
983a5e72196SApple OSS Distributions if (size < kIOPageableMapSize) {
984e13b1fa5SApple OSS Distributions segSize = kIOPageableMapSize;
985a5e72196SApple OSS Distributions } else {
986e13b1fa5SApple OSS Distributions segSize = size;
987a5e72196SApple OSS Distributions }
988e13b1fa5SApple OSS Distributions
9895c2921b0SApple OSS Distributions /*
9905c2921b0SApple OSS Distributions * Use the predefine ranges if available, else default to data
9915c2921b0SApple OSS Distributions */
9925c2921b0SApple OSS Distributions if (index < kIOMaxFixedRanges) {
9935c2921b0SApple OSS Distributions min = gIOKitPageableFixedRanges[index].min_address;
994aca3beaaSApple OSS Distributions flags = VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE;
9955c2921b0SApple OSS Distributions } else {
996e13b1fa5SApple OSS Distributions min = 0;
9975c2921b0SApple OSS Distributions flags = VM_FLAGS_ANYWHERE;
9985c2921b0SApple OSS Distributions }
9995c2921b0SApple OSS Distributions kmr = kmem_suballoc(kernel_map,
1000e13b1fa5SApple OSS Distributions &min,
1001e13b1fa5SApple OSS Distributions segSize,
1002e7776783SApple OSS Distributions VM_MAP_CREATE_PAGEABLE,
10035c2921b0SApple OSS Distributions flags,
10045c2921b0SApple OSS Distributions (kms_flags_t)(KMS_PERMANENT | KMS_DATA),
10055c2921b0SApple OSS Distributions VM_KERN_MEMORY_IOKIT);
10065c2921b0SApple OSS Distributions if (kmr.kmr_return != KERN_SUCCESS) {
10075c2921b0SApple OSS Distributions kr = kmr.kmr_return;
1008e13b1fa5SApple OSS Distributions lck_mtx_unlock( gIOKitPageableSpace.lock );
1009e13b1fa5SApple OSS Distributions break;
1010e13b1fa5SApple OSS Distributions }
1011e13b1fa5SApple OSS Distributions
10125c2921b0SApple OSS Distributions gIOKitPageableSpace.maps[index].map = kmr.kmr_submap;
1013e13b1fa5SApple OSS Distributions gIOKitPageableSpace.maps[index].address = min;
1014e13b1fa5SApple OSS Distributions gIOKitPageableSpace.maps[index].end = min + segSize;
1015e13b1fa5SApple OSS Distributions gIOKitPageableSpace.hint = index;
1016e13b1fa5SApple OSS Distributions gIOKitPageableSpace.count = index + 1;
1017e13b1fa5SApple OSS Distributions
1018e13b1fa5SApple OSS Distributions lck_mtx_unlock( gIOKitPageableSpace.lock );
1019e13b1fa5SApple OSS Distributions } while (true);
1020e13b1fa5SApple OSS Distributions
1021e13b1fa5SApple OSS Distributions return kr;
1022e13b1fa5SApple OSS Distributions }
1023e13b1fa5SApple OSS Distributions
1024a5e72196SApple OSS Distributions struct IOMallocPageableRef {
10253ca3bd55SApple OSS Distributions vm_offset_t address;
1026e13b1fa5SApple OSS Distributions vm_size_t size;
10270f3703acSApple OSS Distributions vm_tag_t tag;
1028e13b1fa5SApple OSS Distributions };
1029e13b1fa5SApple OSS Distributions
1030a5e72196SApple OSS Distributions static kern_return_t
IOMallocPageableCallback(vm_map_t map,void * _ref)1031a5e72196SApple OSS Distributions IOMallocPageableCallback(vm_map_t map, void * _ref)
1032e13b1fa5SApple OSS Distributions {
1033e13b1fa5SApple OSS Distributions struct IOMallocPageableRef * ref = (struct IOMallocPageableRef *) _ref;
10345c2921b0SApple OSS Distributions kma_flags_t flags = (kma_flags_t)(KMA_PAGEABLE | KMA_DATA);
1035e13b1fa5SApple OSS Distributions
10365c2921b0SApple OSS Distributions return kmem_alloc( map, &ref->address, ref->size, flags, ref->tag );
1037e13b1fa5SApple OSS Distributions }
1038e13b1fa5SApple OSS Distributions
1039a5e72196SApple OSS Distributions static void *
IOMallocPageablePages(vm_size_t size,vm_size_t alignment,vm_tag_t tag)1040a5e72196SApple OSS Distributions IOMallocPageablePages(vm_size_t size, vm_size_t alignment, vm_tag_t tag)
1041e13b1fa5SApple OSS Distributions {
1042e13b1fa5SApple OSS Distributions kern_return_t kr = kIOReturnNotReady;
1043e13b1fa5SApple OSS Distributions struct IOMallocPageableRef ref;
1044e13b1fa5SApple OSS Distributions
1045a5e72196SApple OSS Distributions if (alignment > page_size) {
1046a5e72196SApple OSS Distributions return NULL;
1047a5e72196SApple OSS Distributions }
1048a5e72196SApple OSS Distributions if (size > kIOPageableMaxMapSize) {
1049a5e72196SApple OSS Distributions return NULL;
1050a5e72196SApple OSS Distributions }
1051e13b1fa5SApple OSS Distributions
1052e13b1fa5SApple OSS Distributions ref.size = size;
10530f3703acSApple OSS Distributions ref.tag = tag;
1054e13b1fa5SApple OSS Distributions kr = IOIteratePageableMaps( size, &IOMallocPageableCallback, &ref );
1055a5e72196SApple OSS Distributions if (kIOReturnSuccess != kr) {
1056e13b1fa5SApple OSS Distributions ref.address = 0;
1057e13b1fa5SApple OSS Distributions }
1058e13b1fa5SApple OSS Distributions
1059a5e72196SApple OSS Distributions return (void *) ref.address;
1060a5e72196SApple OSS Distributions }
1061a5e72196SApple OSS Distributions
1062a5e72196SApple OSS Distributions vm_map_t
IOPageableMapForAddress(uintptr_t address)1063a5e72196SApple OSS Distributions IOPageableMapForAddress( uintptr_t address )
1064e13b1fa5SApple OSS Distributions {
1065a5e72196SApple OSS Distributions vm_map_t map = NULL;
1066e13b1fa5SApple OSS Distributions UInt32 index;
1067e13b1fa5SApple OSS Distributions
1068e13b1fa5SApple OSS Distributions for (index = 0; index < gIOKitPageableSpace.count; index++) {
1069e13b1fa5SApple OSS Distributions if ((address >= gIOKitPageableSpace.maps[index].address)
1070e13b1fa5SApple OSS Distributions && (address < gIOKitPageableSpace.maps[index].end)) {
1071e13b1fa5SApple OSS Distributions map = gIOKitPageableSpace.maps[index].map;
1072e13b1fa5SApple OSS Distributions break;
1073e13b1fa5SApple OSS Distributions }
1074e13b1fa5SApple OSS Distributions }
1075a5e72196SApple OSS Distributions if (!map) {
10763ca3bd55SApple OSS Distributions panic("IOPageableMapForAddress: null");
1077e13b1fa5SApple OSS Distributions }
1078e13b1fa5SApple OSS Distributions
1079a5e72196SApple OSS Distributions return map;
1080a5e72196SApple OSS Distributions }
1081a5e72196SApple OSS Distributions
1082a5e72196SApple OSS Distributions static void
IOFreePageablePages(void * address,vm_size_t size)1083a5e72196SApple OSS Distributions IOFreePageablePages(void * address, vm_size_t size)
1084e13b1fa5SApple OSS Distributions {
1085e13b1fa5SApple OSS Distributions vm_map_t map;
1086e13b1fa5SApple OSS Distributions
1087e13b1fa5SApple OSS Distributions map = IOPageableMapForAddress((vm_address_t) address);
1088a5e72196SApple OSS Distributions if (map) {
1089e13b1fa5SApple OSS Distributions kmem_free( map, (vm_offset_t) address, size);
1090186b8fceSApple OSS Distributions }
1091186b8fceSApple OSS Distributions }
1092186b8fceSApple OSS Distributions
1093e7776783SApple OSS Distributions #if defined(__x86_64__)
1094a5e72196SApple OSS Distributions static uintptr_t
IOMallocOnePageablePage(kalloc_heap_t kheap __unused,iopa_t * a)1095e6231be0SApple OSS Distributions IOMallocOnePageablePage(kalloc_heap_t kheap __unused, iopa_t * a)
1096a5e72196SApple OSS Distributions {
1097a5e72196SApple OSS Distributions return (uintptr_t) IOMallocPageablePages(page_size, page_size, VM_KERN_MEMORY_IOKIT);
1098a5e72196SApple OSS Distributions }
1099e7776783SApple OSS Distributions #endif /* defined(__x86_64__) */
1100a5e72196SApple OSS Distributions
1101bb611c8fSApple OSS Distributions static void *
IOMallocPageableInternal(vm_size_t size,vm_size_t alignment,bool zeroed)1102bb611c8fSApple OSS Distributions IOMallocPageableInternal(vm_size_t size, vm_size_t alignment, bool zeroed)
1103186b8fceSApple OSS Distributions {
1104186b8fceSApple OSS Distributions void * addr;
1105186b8fceSApple OSS Distributions
1106bb611c8fSApple OSS Distributions if (((uint32_t) alignment) != alignment) {
1107bb611c8fSApple OSS Distributions return NULL;
1108bb611c8fSApple OSS Distributions }
1109e7776783SApple OSS Distributions #if defined(__x86_64__)
1110bb611c8fSApple OSS Distributions if (size >= (page_size - 4 * gIOPageAllocChunkBytes) ||
1111bb611c8fSApple OSS Distributions alignment > page_size) {
1112a5e72196SApple OSS Distributions addr = IOMallocPageablePages(size, alignment, IOMemoryTag(kernel_map));
1113bb611c8fSApple OSS Distributions /* Memory allocated this way will already be zeroed. */
1114a5e72196SApple OSS Distributions } else {
1115e6231be0SApple OSS Distributions addr = ((void *) iopa_alloc(&gIOPageablePageAllocator,
11165c2921b0SApple OSS Distributions &IOMallocOnePageablePage, KHEAP_DEFAULT, size, (uint32_t) alignment));
1117e7776783SApple OSS Distributions if (addr && zeroed) {
1118bb611c8fSApple OSS Distributions bzero(addr, size);
1119bb611c8fSApple OSS Distributions }
1120a5e72196SApple OSS Distributions }
1121e7776783SApple OSS Distributions #else /* !defined(__x86_64__) */
1122e7776783SApple OSS Distributions vm_size_t allocSize = size;
1123e7776783SApple OSS Distributions if (allocSize == 0) {
1124e7776783SApple OSS Distributions allocSize = 1;
1125e7776783SApple OSS Distributions }
1126e7776783SApple OSS Distributions addr = IOMallocPageablePages(allocSize, alignment, IOMemoryTag(kernel_map));
1127e7776783SApple OSS Distributions /* already zeroed */
1128e7776783SApple OSS Distributions #endif /* defined(__x86_64__) */
1129186b8fceSApple OSS Distributions
1130186b8fceSApple OSS Distributions if (addr) {
1131e13b1fa5SApple OSS Distributions #if IOALLOCDEBUG
11320f3703acSApple OSS Distributions OSAddAtomicLong(size, &debug_iomallocpageable_size);
1133186b8fceSApple OSS Distributions #endif
1134186b8fceSApple OSS Distributions IOStatisticsAlloc(kIOStatisticsMallocPageable, size);
1135186b8fceSApple OSS Distributions }
1136186b8fceSApple OSS Distributions
1137a5e72196SApple OSS Distributions return addr;
1138186b8fceSApple OSS Distributions }
1139186b8fceSApple OSS Distributions
1140bb611c8fSApple OSS Distributions void *
IOMallocPageable(vm_size_t size,vm_size_t alignment)1141bb611c8fSApple OSS Distributions IOMallocPageable(vm_size_t size, vm_size_t alignment)
1142bb611c8fSApple OSS Distributions {
1143bb611c8fSApple OSS Distributions return IOMallocPageableInternal(size, alignment, /*zeroed*/ false);
1144bb611c8fSApple OSS Distributions }
1145bb611c8fSApple OSS Distributions
1146bb611c8fSApple OSS Distributions void *
IOMallocPageableZero(vm_size_t size,vm_size_t alignment)1147bb611c8fSApple OSS Distributions IOMallocPageableZero(vm_size_t size, vm_size_t alignment)
1148bb611c8fSApple OSS Distributions {
1149bb611c8fSApple OSS Distributions return IOMallocPageableInternal(size, alignment, /*zeroed*/ true);
1150bb611c8fSApple OSS Distributions }
1151bb611c8fSApple OSS Distributions
1152a5e72196SApple OSS Distributions void
IOFreePageable(void * address,vm_size_t size)1153a5e72196SApple OSS Distributions IOFreePageable(void * address, vm_size_t size)
1154186b8fceSApple OSS Distributions {
1155186b8fceSApple OSS Distributions #if IOALLOCDEBUG
11560f3703acSApple OSS Distributions OSAddAtomicLong(-size, &debug_iomallocpageable_size);
1157186b8fceSApple OSS Distributions #endif
1158186b8fceSApple OSS Distributions IOStatisticsAlloc(kIOStatisticsFreePageable, size);
1159186b8fceSApple OSS Distributions
1160e7776783SApple OSS Distributions #if defined(__x86_64__)
1161a5e72196SApple OSS Distributions if (size < (page_size - 4 * gIOPageAllocChunkBytes)) {
1162186b8fceSApple OSS Distributions address = (void *) iopa_free(&gIOPageablePageAllocator, (uintptr_t) address, size);
1163186b8fceSApple OSS Distributions size = page_size;
1164186b8fceSApple OSS Distributions }
1165a5e72196SApple OSS Distributions if (address) {
1166a5e72196SApple OSS Distributions IOFreePageablePages(address, size);
1167a5e72196SApple OSS Distributions }
1168e7776783SApple OSS Distributions #else /* !defined(__x86_64__) */
1169e7776783SApple OSS Distributions if (size == 0) {
1170e7776783SApple OSS Distributions size = 1;
1171e7776783SApple OSS Distributions }
1172e7776783SApple OSS Distributions if (address) {
1173e7776783SApple OSS Distributions IOFreePageablePages(address, size);
1174e7776783SApple OSS Distributions }
1175e7776783SApple OSS Distributions #endif /* defined(__x86_64__) */
1176186b8fceSApple OSS Distributions }
1177186b8fceSApple OSS Distributions
1178186b8fceSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1179186b8fceSApple OSS Distributions
1180e6231be0SApple OSS Distributions void *
11815c2921b0SApple OSS Distributions IOMallocData_external(
11825c2921b0SApple OSS Distributions vm_size_t size);
1183e6231be0SApple OSS Distributions void *
IOMallocData_external(vm_size_t size)11845c2921b0SApple OSS Distributions IOMallocData_external(vm_size_t size)
1185e6231be0SApple OSS Distributions {
11865c2921b0SApple OSS Distributions return IOMalloc_internal(KHEAP_DATA_BUFFERS, size, Z_VM_TAG_BT_BIT);
11875c2921b0SApple OSS Distributions }
11885c2921b0SApple OSS Distributions
11895c2921b0SApple OSS Distributions void *
11905c2921b0SApple OSS Distributions IOMallocZeroData_external(
11915c2921b0SApple OSS Distributions vm_size_t size);
11925c2921b0SApple OSS Distributions void *
IOMallocZeroData_external(vm_size_t size)11935c2921b0SApple OSS Distributions IOMallocZeroData_external(vm_size_t size)
11945c2921b0SApple OSS Distributions {
11955c2921b0SApple OSS Distributions return IOMalloc_internal(KHEAP_DATA_BUFFERS, size, Z_ZERO_VM_TAG_BT_BIT);
1196e6231be0SApple OSS Distributions }
1197e6231be0SApple OSS Distributions
1198e6231be0SApple OSS Distributions void
IOFreeData(void * address,vm_size_t size)1199e6231be0SApple OSS Distributions IOFreeData(void * address, vm_size_t size)
1200e6231be0SApple OSS Distributions {
1201e6231be0SApple OSS Distributions return IOFree_internal(KHEAP_DATA_BUFFERS, address, size);
1202e6231be0SApple OSS Distributions }
1203e6231be0SApple OSS Distributions
1204e6231be0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1205e6231be0SApple OSS Distributions
12065c2921b0SApple OSS Distributions __typed_allocators_ignore_push // allocator implementation
12075c2921b0SApple OSS Distributions
1208e6231be0SApple OSS Distributions void *
IOMallocTypeImpl(kalloc_type_view_t kt_view)1209e6231be0SApple OSS Distributions IOMallocTypeImpl(kalloc_type_view_t kt_view)
1210e6231be0SApple OSS Distributions {
1211e6231be0SApple OSS Distributions #if IOTRACKING
1212e6231be0SApple OSS Distributions /*
1213e6231be0SApple OSS Distributions * When leak detection is on default to using IOMalloc as kalloc
1214e6231be0SApple OSS Distributions * type infrastructure isn't aware of needing additional space for
1215e6231be0SApple OSS Distributions * the header.
1216e6231be0SApple OSS Distributions */
1217e6231be0SApple OSS Distributions if (TRACK_ALLOC) {
1218e7776783SApple OSS Distributions uint32_t kt_size = kalloc_type_get_size(kt_view->kt_size);
12195c2921b0SApple OSS Distributions void *mem = IOMalloc_internal(KHEAP_DEFAULT, kt_size, Z_ZERO);
1220e7776783SApple OSS Distributions if (!IOMallocType_from_vm(kt_view)) {
1221e6231be0SApple OSS Distributions assert(mem);
1222e6231be0SApple OSS Distributions }
1223e6231be0SApple OSS Distributions return mem;
1224e6231be0SApple OSS Distributions }
1225e6231be0SApple OSS Distributions #endif
1226e6231be0SApple OSS Distributions zalloc_flags_t kt_flags = (zalloc_flags_t) (Z_WAITOK | Z_ZERO);
1227e7776783SApple OSS Distributions if (!IOMallocType_from_vm(kt_view)) {
1228e6231be0SApple OSS Distributions kt_flags = (zalloc_flags_t) (kt_flags | Z_NOFAIL);
1229e6231be0SApple OSS Distributions }
1230e6231be0SApple OSS Distributions /*
1231e6231be0SApple OSS Distributions * Use external symbol for kalloc_type_impl as
1232e6231be0SApple OSS Distributions * kalloc_type_views generated at some external callsites
1233e6231be0SApple OSS Distributions * many not have been processed during boot.
1234e6231be0SApple OSS Distributions */
1235e6231be0SApple OSS Distributions return kalloc_type_impl_external(kt_view, kt_flags);
1236e6231be0SApple OSS Distributions }
1237e6231be0SApple OSS Distributions
1238e6231be0SApple OSS Distributions void
IOFreeTypeImpl(kalloc_type_view_t kt_view,void * address)1239e6231be0SApple OSS Distributions IOFreeTypeImpl(kalloc_type_view_t kt_view, void * address)
1240e6231be0SApple OSS Distributions {
1241e6231be0SApple OSS Distributions #if IOTRACKING
1242e6231be0SApple OSS Distributions if (TRACK_ALLOC) {
1243e6231be0SApple OSS Distributions return IOFree_internal(KHEAP_DEFAULT, address,
1244e6231be0SApple OSS Distributions kalloc_type_get_size(kt_view->kt_size));
1245e6231be0SApple OSS Distributions }
1246e6231be0SApple OSS Distributions #endif
1247e6231be0SApple OSS Distributions /*
1248e6231be0SApple OSS Distributions * Use external symbol for kalloc_type_impl as
1249e6231be0SApple OSS Distributions * kalloc_type_views generated at some external callsites
1250e6231be0SApple OSS Distributions * many not have been processed during boot.
1251e6231be0SApple OSS Distributions */
1252e6231be0SApple OSS Distributions return kfree_type_impl_external(kt_view, address);
1253e6231be0SApple OSS Distributions }
1254e6231be0SApple OSS Distributions
1255e7776783SApple OSS Distributions void *
IOMallocTypeVarImpl(kalloc_type_var_view_t kt_view,vm_size_t size)1256e7776783SApple OSS Distributions IOMallocTypeVarImpl(kalloc_type_var_view_t kt_view, vm_size_t size)
1257e7776783SApple OSS Distributions {
1258e7776783SApple OSS Distributions #if IOTRACKING
1259e7776783SApple OSS Distributions /*
1260e7776783SApple OSS Distributions * When leak detection is on default to using IOMalloc as kalloc
1261e7776783SApple OSS Distributions * type infrastructure isn't aware of needing additional space for
1262e7776783SApple OSS Distributions * the header.
1263e7776783SApple OSS Distributions */
1264e7776783SApple OSS Distributions if (TRACK_ALLOC) {
12655c2921b0SApple OSS Distributions return IOMalloc_internal(KHEAP_DEFAULT, size, Z_ZERO);
1266e7776783SApple OSS Distributions }
1267e7776783SApple OSS Distributions #endif
1268e7776783SApple OSS Distributions zalloc_flags_t kt_flags = (zalloc_flags_t) (Z_WAITOK | Z_ZERO);
1269e7776783SApple OSS Distributions
1270e7776783SApple OSS Distributions kt_flags = Z_VM_TAG_BT(kt_flags, VM_KERN_MEMORY_KALLOC_TYPE);
1271e7776783SApple OSS Distributions return kalloc_type_var_impl(kt_view, size, kt_flags, NULL);
1272e7776783SApple OSS Distributions }
1273e7776783SApple OSS Distributions
1274e7776783SApple OSS Distributions void
IOFreeTypeVarImpl(kalloc_type_var_view_t kt_view,void * address,vm_size_t size)1275e7776783SApple OSS Distributions IOFreeTypeVarImpl(kalloc_type_var_view_t kt_view, void * address,
1276e7776783SApple OSS Distributions vm_size_t size)
1277e7776783SApple OSS Distributions {
1278e7776783SApple OSS Distributions #if IOTRACKING
1279e7776783SApple OSS Distributions if (TRACK_ALLOC) {
1280e7776783SApple OSS Distributions return IOFree_internal(KHEAP_DEFAULT, address, size);
1281e7776783SApple OSS Distributions }
1282e7776783SApple OSS Distributions #endif
1283e7776783SApple OSS Distributions
1284e7776783SApple OSS Distributions return kfree_type_var_impl(kt_view, address, size);
1285e7776783SApple OSS Distributions }
1286e7776783SApple OSS Distributions
12875c2921b0SApple OSS Distributions __typed_allocators_ignore_pop
12885c2921b0SApple OSS Distributions
1289e6231be0SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1290e6231be0SApple OSS Distributions
1291e7776783SApple OSS Distributions #if defined(__x86_64__)
1292e7776783SApple OSS Distributions
1293e7776783SApple OSS Distributions
1294186b8fceSApple OSS Distributions extern "C" void
iopa_init(iopa_t * a)1295186b8fceSApple OSS Distributions iopa_init(iopa_t * a)
1296186b8fceSApple OSS Distributions {
1297186b8fceSApple OSS Distributions bzero(a, sizeof(*a));
1298186b8fceSApple OSS Distributions a->lock = IOLockAlloc();
1299186b8fceSApple OSS Distributions queue_init(&a->list);
1300186b8fceSApple OSS Distributions }
1301186b8fceSApple OSS Distributions
1302186b8fceSApple OSS Distributions static uintptr_t
iopa_allocinpage(iopa_page_t * pa,uint32_t count,uint64_t align)1303186b8fceSApple OSS Distributions iopa_allocinpage(iopa_page_t * pa, uint32_t count, uint64_t align)
1304186b8fceSApple OSS Distributions {
1305186b8fceSApple OSS Distributions uint32_t n, s;
1306186b8fceSApple OSS Distributions uint64_t avail = pa->avail;
1307186b8fceSApple OSS Distributions
1308186b8fceSApple OSS Distributions assert(avail);
1309186b8fceSApple OSS Distributions
1310186b8fceSApple OSS Distributions // find strings of count 1 bits in avail
1311a5e72196SApple OSS Distributions for (n = count; n > 1; n -= s) {
1312186b8fceSApple OSS Distributions s = n >> 1;
1313186b8fceSApple OSS Distributions avail = avail & (avail << s);
1314186b8fceSApple OSS Distributions }
1315186b8fceSApple OSS Distributions // and aligned
1316186b8fceSApple OSS Distributions avail &= align;
1317186b8fceSApple OSS Distributions
1318a5e72196SApple OSS Distributions if (avail) {
1319186b8fceSApple OSS Distributions n = __builtin_clzll(avail);
1320186b8fceSApple OSS Distributions pa->avail &= ~((-1ULL << (64 - count)) >> n);
1321a5e72196SApple OSS Distributions if (!pa->avail && pa->link.next) {
1322186b8fceSApple OSS Distributions remque(&pa->link);
1323a5e72196SApple OSS Distributions pa->link.next = NULL;
1324186b8fceSApple OSS Distributions }
1325a5e72196SApple OSS Distributions return n * gIOPageAllocChunkBytes + trunc_page((uintptr_t) pa);
1326186b8fceSApple OSS Distributions }
1327186b8fceSApple OSS Distributions
1328a5e72196SApple OSS Distributions return 0;
1329186b8fceSApple OSS Distributions }
1330186b8fceSApple OSS Distributions
1331186b8fceSApple OSS Distributions uintptr_t
iopa_alloc(iopa_t * a,iopa_proc_t alloc,kalloc_heap_t kheap,vm_size_t bytes,vm_size_t balign)1332e6231be0SApple OSS Distributions iopa_alloc(
1333e6231be0SApple OSS Distributions iopa_t * a,
1334e6231be0SApple OSS Distributions iopa_proc_t alloc,
1335e6231be0SApple OSS Distributions kalloc_heap_t kheap,
1336e6231be0SApple OSS Distributions vm_size_t bytes,
1337e6231be0SApple OSS Distributions vm_size_t balign)
1338186b8fceSApple OSS Distributions {
1339186b8fceSApple OSS Distributions static const uint64_t align_masks[] = {
1340186b8fceSApple OSS Distributions 0xFFFFFFFFFFFFFFFF,
1341186b8fceSApple OSS Distributions 0xAAAAAAAAAAAAAAAA,
1342186b8fceSApple OSS Distributions 0x8888888888888888,
1343186b8fceSApple OSS Distributions 0x8080808080808080,
1344186b8fceSApple OSS Distributions 0x8000800080008000,
1345186b8fceSApple OSS Distributions 0x8000000080000000,
1346186b8fceSApple OSS Distributions 0x8000000000000000,
1347186b8fceSApple OSS Distributions };
1348186b8fceSApple OSS Distributions iopa_page_t * pa;
1349186b8fceSApple OSS Distributions uintptr_t addr = 0;
1350186b8fceSApple OSS Distributions uint32_t count;
1351186b8fceSApple OSS Distributions uint64_t align;
1352bb611c8fSApple OSS Distributions vm_size_t align_masks_idx;
1353186b8fceSApple OSS Distributions
1354bb611c8fSApple OSS Distributions if (((uint32_t) bytes) != bytes) {
1355bb611c8fSApple OSS Distributions return 0;
1356bb611c8fSApple OSS Distributions }
1357a5e72196SApple OSS Distributions if (!bytes) {
1358a5e72196SApple OSS Distributions bytes = 1;
1359a5e72196SApple OSS Distributions }
1360bb611c8fSApple OSS Distributions count = (((uint32_t) bytes) + gIOPageAllocChunkBytes - 1) / gIOPageAllocChunkBytes;
1361bb611c8fSApple OSS Distributions
1362bb611c8fSApple OSS Distributions align_masks_idx = log2up((balign + gIOPageAllocChunkBytes - 1) / gIOPageAllocChunkBytes);
1363bb611c8fSApple OSS Distributions assert(align_masks_idx < sizeof(align_masks) / sizeof(*align_masks));
1364bb611c8fSApple OSS Distributions align = align_masks[align_masks_idx];
1365186b8fceSApple OSS Distributions
1366186b8fceSApple OSS Distributions IOLockLock(a->lock);
13670f3703acSApple OSS Distributions __IGNORE_WCASTALIGN(pa = (typeof(pa))queue_first(&a->list));
1368a5e72196SApple OSS Distributions while (!queue_end(&a->list, &pa->link)) {
1369186b8fceSApple OSS Distributions addr = iopa_allocinpage(pa, count, align);
1370a5e72196SApple OSS Distributions if (addr) {
1371186b8fceSApple OSS Distributions a->bytecount += bytes;
1372186b8fceSApple OSS Distributions break;
1373186b8fceSApple OSS Distributions }
13740f3703acSApple OSS Distributions __IGNORE_WCASTALIGN(pa = (typeof(pa))queue_next(&pa->link));
1375186b8fceSApple OSS Distributions }
1376186b8fceSApple OSS Distributions IOLockUnlock(a->lock);
1377186b8fceSApple OSS Distributions
1378a5e72196SApple OSS Distributions if (!addr) {
1379e6231be0SApple OSS Distributions addr = alloc(kheap, a);
1380a5e72196SApple OSS Distributions if (addr) {
1381a3bb9fccSApple OSS Distributions pa = (typeof(pa))(addr + page_size - gIOPageAllocChunkBytes);
1382186b8fceSApple OSS Distributions pa->signature = kIOPageAllocSignature;
1383186b8fceSApple OSS Distributions pa->avail = -2ULL;
1384186b8fceSApple OSS Distributions
1385186b8fceSApple OSS Distributions addr = iopa_allocinpage(pa, count, align);
1386186b8fceSApple OSS Distributions IOLockLock(a->lock);
1387a5e72196SApple OSS Distributions if (pa->avail) {
1388a5e72196SApple OSS Distributions enqueue_head(&a->list, &pa->link);
1389a5e72196SApple OSS Distributions }
1390186b8fceSApple OSS Distributions a->pagecount++;
1391a5e72196SApple OSS Distributions if (addr) {
1392a5e72196SApple OSS Distributions a->bytecount += bytes;
1393a5e72196SApple OSS Distributions }
1394186b8fceSApple OSS Distributions IOLockUnlock(a->lock);
1395186b8fceSApple OSS Distributions }
1396186b8fceSApple OSS Distributions }
1397186b8fceSApple OSS Distributions
1398186b8fceSApple OSS Distributions assert((addr & ((1 << log2up(balign)) - 1)) == 0);
1399a5e72196SApple OSS Distributions return addr;
1400186b8fceSApple OSS Distributions }
1401186b8fceSApple OSS Distributions
1402186b8fceSApple OSS Distributions uintptr_t
iopa_free(iopa_t * a,uintptr_t addr,vm_size_t bytes)1403186b8fceSApple OSS Distributions iopa_free(iopa_t * a, uintptr_t addr, vm_size_t bytes)
1404186b8fceSApple OSS Distributions {
1405186b8fceSApple OSS Distributions iopa_page_t * pa;
1406186b8fceSApple OSS Distributions uint32_t count;
1407186b8fceSApple OSS Distributions uintptr_t chunk;
1408186b8fceSApple OSS Distributions
1409bb611c8fSApple OSS Distributions if (((uint32_t) bytes) != bytes) {
1410bb611c8fSApple OSS Distributions return 0;
1411bb611c8fSApple OSS Distributions }
1412a5e72196SApple OSS Distributions if (!bytes) {
1413a5e72196SApple OSS Distributions bytes = 1;
1414a5e72196SApple OSS Distributions }
1415186b8fceSApple OSS Distributions
1416186b8fceSApple OSS Distributions chunk = (addr & page_mask);
1417a3bb9fccSApple OSS Distributions assert(0 == (chunk & (gIOPageAllocChunkBytes - 1)));
1418186b8fceSApple OSS Distributions
1419a3bb9fccSApple OSS Distributions pa = (typeof(pa))(addr | (page_size - gIOPageAllocChunkBytes));
1420186b8fceSApple OSS Distributions assert(kIOPageAllocSignature == pa->signature);
1421186b8fceSApple OSS Distributions
1422bb611c8fSApple OSS Distributions count = (((uint32_t) bytes) + gIOPageAllocChunkBytes - 1) / gIOPageAllocChunkBytes;
1423a3bb9fccSApple OSS Distributions chunk /= gIOPageAllocChunkBytes;
1424186b8fceSApple OSS Distributions
1425186b8fceSApple OSS Distributions IOLockLock(a->lock);
1426a5e72196SApple OSS Distributions if (!pa->avail) {
1427186b8fceSApple OSS Distributions assert(!pa->link.next);
1428186b8fceSApple OSS Distributions enqueue_tail(&a->list, &pa->link);
1429186b8fceSApple OSS Distributions }
1430186b8fceSApple OSS Distributions pa->avail |= ((-1ULL << (64 - count)) >> chunk);
1431a5e72196SApple OSS Distributions if (pa->avail != -2ULL) {
1432a5e72196SApple OSS Distributions pa = NULL;
1433a5e72196SApple OSS Distributions } else {
1434186b8fceSApple OSS Distributions remque(&pa->link);
1435a5e72196SApple OSS Distributions pa->link.next = NULL;
1436186b8fceSApple OSS Distributions pa->signature = 0;
1437186b8fceSApple OSS Distributions a->pagecount--;
1438186b8fceSApple OSS Distributions // page to free
1439186b8fceSApple OSS Distributions pa = (typeof(pa))trunc_page(pa);
1440186b8fceSApple OSS Distributions }
1441186b8fceSApple OSS Distributions a->bytecount -= bytes;
1442186b8fceSApple OSS Distributions IOLockUnlock(a->lock);
1443186b8fceSApple OSS Distributions
1444a5e72196SApple OSS Distributions return (uintptr_t) pa;
1445e13b1fa5SApple OSS Distributions }
1446e13b1fa5SApple OSS Distributions
1447e7776783SApple OSS Distributions #endif /* defined(__x86_64__) */
1448e7776783SApple OSS Distributions
1449e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1450e13b1fa5SApple OSS Distributions
1451a5e72196SApple OSS Distributions IOReturn
IOSetProcessorCacheMode(task_t task,IOVirtualAddress address,IOByteCount length,IOOptionBits cacheMode)1452a5e72196SApple OSS Distributions IOSetProcessorCacheMode( task_t task, IOVirtualAddress address,
1453e13b1fa5SApple OSS Distributions IOByteCount length, IOOptionBits cacheMode )
1454e13b1fa5SApple OSS Distributions {
1455e13b1fa5SApple OSS Distributions IOReturn ret = kIOReturnSuccess;
1456e13b1fa5SApple OSS Distributions ppnum_t pagenum;
1457e13b1fa5SApple OSS Distributions
1458a5e72196SApple OSS Distributions if (task != kernel_task) {
1459a5e72196SApple OSS Distributions return kIOReturnUnsupported;
1460a5e72196SApple OSS Distributions }
1461a5e72196SApple OSS Distributions if ((address | length) & PAGE_MASK) {
14623ca3bd55SApple OSS Distributions // OSReportWithBacktrace("IOSetProcessorCacheMode(0x%x, 0x%x, 0x%x) fails\n", address, length, cacheMode);
1463a5e72196SApple OSS Distributions return kIOReturnUnsupported;
14643ca3bd55SApple OSS Distributions }
14653ca3bd55SApple OSS Distributions length = round_page(address + length) - trunc_page( address );
14663ca3bd55SApple OSS Distributions address = trunc_page( address );
1467e13b1fa5SApple OSS Distributions
1468e13b1fa5SApple OSS Distributions // make map mode
1469e13b1fa5SApple OSS Distributions cacheMode = (cacheMode << kIOMapCacheShift) & kIOMapCacheMask;
1470e13b1fa5SApple OSS Distributions
1471e13b1fa5SApple OSS Distributions while ((kIOReturnSuccess == ret) && (length > 0)) {
1472e13b1fa5SApple OSS Distributions // Get the physical page number
1473e13b1fa5SApple OSS Distributions pagenum = pmap_find_phys(kernel_pmap, (addr64_t)address);
1474e13b1fa5SApple OSS Distributions if (pagenum) {
1475e13b1fa5SApple OSS Distributions ret = IOUnmapPages( get_task_map(task), address, page_size );
1476e13b1fa5SApple OSS Distributions ret = IOMapPages( get_task_map(task), address, ptoa_64(pagenum), page_size, cacheMode );
1477a5e72196SApple OSS Distributions } else {
1478e13b1fa5SApple OSS Distributions ret = kIOReturnVMError;
1479a5e72196SApple OSS Distributions }
1480e13b1fa5SApple OSS Distributions
1481e13b1fa5SApple OSS Distributions address += page_size;
1482e13b1fa5SApple OSS Distributions length -= page_size;
1483e13b1fa5SApple OSS Distributions }
1484e13b1fa5SApple OSS Distributions
1485a5e72196SApple OSS Distributions return ret;
1486e13b1fa5SApple OSS Distributions }
1487e13b1fa5SApple OSS Distributions
1488e13b1fa5SApple OSS Distributions
1489a5e72196SApple OSS Distributions IOReturn
IOFlushProcessorCache(task_t task,IOVirtualAddress address,IOByteCount length)1490a5e72196SApple OSS Distributions IOFlushProcessorCache( task_t task, IOVirtualAddress address,
1491e13b1fa5SApple OSS Distributions IOByteCount length )
1492e13b1fa5SApple OSS Distributions {
1493a5e72196SApple OSS Distributions if (task != kernel_task) {
1494a5e72196SApple OSS Distributions return kIOReturnUnsupported;
1495a5e72196SApple OSS Distributions }
1496e13b1fa5SApple OSS Distributions
1497e13b1fa5SApple OSS Distributions flush_dcache64((addr64_t) address, (unsigned) length, false );
1498e13b1fa5SApple OSS Distributions
1499a5e72196SApple OSS Distributions return kIOReturnSuccess;
1500e13b1fa5SApple OSS Distributions }
1501e13b1fa5SApple OSS Distributions
1502e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1503e13b1fa5SApple OSS Distributions
1504a5e72196SApple OSS Distributions vm_offset_t
OSKernelStackRemaining(void)1505a5e72196SApple OSS Distributions OSKernelStackRemaining( void )
1506e13b1fa5SApple OSS Distributions {
1507a5e72196SApple OSS Distributions return ml_stack_remaining();
1508e13b1fa5SApple OSS Distributions }
1509e13b1fa5SApple OSS Distributions
1510e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1511e13b1fa5SApple OSS Distributions
1512e13b1fa5SApple OSS Distributions /*
1513e13b1fa5SApple OSS Distributions * Spin for indicated number of milliseconds.
1514e13b1fa5SApple OSS Distributions */
1515a5e72196SApple OSS Distributions void
IOSleep(unsigned milliseconds)1516a5e72196SApple OSS Distributions IOSleep(unsigned milliseconds)
1517e13b1fa5SApple OSS Distributions {
1518e13b1fa5SApple OSS Distributions delay_for_interval(milliseconds, kMillisecondScale);
1519e13b1fa5SApple OSS Distributions }
1520e13b1fa5SApple OSS Distributions
1521e13b1fa5SApple OSS Distributions /*
15220f3703acSApple OSS Distributions * Spin for indicated number of milliseconds, and potentially an
15230f3703acSApple OSS Distributions * additional number of milliseconds up to the leeway values.
15240f3703acSApple OSS Distributions */
1525a5e72196SApple OSS Distributions void
IOSleepWithLeeway(unsigned intervalMilliseconds,unsigned leewayMilliseconds)1526a5e72196SApple OSS Distributions IOSleepWithLeeway(unsigned intervalMilliseconds, unsigned leewayMilliseconds)
15270f3703acSApple OSS Distributions {
15280f3703acSApple OSS Distributions delay_for_interval_with_leeway(intervalMilliseconds, leewayMilliseconds, kMillisecondScale);
15290f3703acSApple OSS Distributions }
15300f3703acSApple OSS Distributions
15310f3703acSApple OSS Distributions /*
1532e13b1fa5SApple OSS Distributions * Spin for indicated number of microseconds.
1533e13b1fa5SApple OSS Distributions */
1534a5e72196SApple OSS Distributions void
IODelay(unsigned microseconds)1535a5e72196SApple OSS Distributions IODelay(unsigned microseconds)
1536e13b1fa5SApple OSS Distributions {
1537e13b1fa5SApple OSS Distributions delay_for_interval(microseconds, kMicrosecondScale);
1538e13b1fa5SApple OSS Distributions }
1539e13b1fa5SApple OSS Distributions
1540e13b1fa5SApple OSS Distributions /*
1541e13b1fa5SApple OSS Distributions * Spin for indicated number of nanoseconds.
1542e13b1fa5SApple OSS Distributions */
1543a5e72196SApple OSS Distributions void
IOPause(unsigned nanoseconds)1544a5e72196SApple OSS Distributions IOPause(unsigned nanoseconds)
1545e13b1fa5SApple OSS Distributions {
1546e13b1fa5SApple OSS Distributions delay_for_interval(nanoseconds, kNanosecondScale);
1547e13b1fa5SApple OSS Distributions }
1548e13b1fa5SApple OSS Distributions
1549e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1550e13b1fa5SApple OSS Distributions
155176e12aa3SApple OSS Distributions static void _IOLogv(const char *format, va_list ap, void *caller) __printflike(1, 0);
15523ca3bd55SApple OSS Distributions
155388cc0b97SApple OSS Distributions __attribute__((noinline, not_tail_called))
1554a5e72196SApple OSS Distributions void
IOLog(const char * format,...)1555a5e72196SApple OSS Distributions IOLog(const char *format, ...)
1556e13b1fa5SApple OSS Distributions {
155788cc0b97SApple OSS Distributions void *caller = __builtin_return_address(0);
1558e13b1fa5SApple OSS Distributions va_list ap;
1559e13b1fa5SApple OSS Distributions
1560e13b1fa5SApple OSS Distributions va_start(ap, format);
156188cc0b97SApple OSS Distributions _IOLogv(format, ap, caller);
1562e13b1fa5SApple OSS Distributions va_end(ap);
1563e13b1fa5SApple OSS Distributions }
1564e13b1fa5SApple OSS Distributions
156588cc0b97SApple OSS Distributions __attribute__((noinline, not_tail_called))
1566a5e72196SApple OSS Distributions void
IOLogv(const char * format,va_list ap)1567a5e72196SApple OSS Distributions IOLogv(const char *format, va_list ap)
15683ca3bd55SApple OSS Distributions {
156988cc0b97SApple OSS Distributions void *caller = __builtin_return_address(0);
157088cc0b97SApple OSS Distributions _IOLogv(format, ap, caller);
157188cc0b97SApple OSS Distributions }
157288cc0b97SApple OSS Distributions
1573a5e72196SApple OSS Distributions void
_IOLogv(const char * format,va_list ap,void * caller)1574a5e72196SApple OSS Distributions _IOLogv(const char *format, va_list ap, void *caller)
157588cc0b97SApple OSS Distributions {
1576855239e5SApple OSS Distributions va_list ap2;
157776e12aa3SApple OSS Distributions struct console_printbuf_state info_data;
157876e12aa3SApple OSS Distributions console_printbuf_state_init(&info_data, TRUE, TRUE);
157988cc0b97SApple OSS Distributions
1580855239e5SApple OSS Distributions va_copy(ap2, ap);
1581855239e5SApple OSS Distributions
1582e7776783SApple OSS Distributions #pragma clang diagnostic push
1583e7776783SApple OSS Distributions #pragma clang diagnostic ignored "-Wformat-nonliteral"
158488cc0b97SApple OSS Distributions os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, format, ap, caller);
1585e7776783SApple OSS Distributions #pragma clang diagnostic pop
1586855239e5SApple OSS Distributions
1587e6231be0SApple OSS Distributions if (!disable_iolog_serial_output) {
158876e12aa3SApple OSS Distributions __doprnt(format, ap2, console_printbuf_putc, &info_data, 16, TRUE);
158976e12aa3SApple OSS Distributions console_printbuf_clear(&info_data);
1590e6231be0SApple OSS Distributions }
15910f3703acSApple OSS Distributions va_end(ap2);
159276e12aa3SApple OSS Distributions
1593e6231be0SApple OSS Distributions assertf(ml_get_interrupts_enabled() || ml_is_quiescing() ||
1594e6231be0SApple OSS Distributions debug_mode_active() || !gCPUsRunning,
1595e6231be0SApple OSS Distributions "IOLog called with interrupts disabled");
15963ca3bd55SApple OSS Distributions }
15973ca3bd55SApple OSS Distributions
15983ca3bd55SApple OSS Distributions #if !__LP64__
1599a5e72196SApple OSS Distributions void
IOPanic(const char * reason)1600a5e72196SApple OSS Distributions IOPanic(const char *reason)
1601e13b1fa5SApple OSS Distributions {
1602e13b1fa5SApple OSS Distributions panic("%s", reason);
1603e13b1fa5SApple OSS Distributions }
16043ca3bd55SApple OSS Distributions #endif
1605e13b1fa5SApple OSS Distributions
1606e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1607e13b1fa5SApple OSS Distributions
1608a5e72196SApple OSS Distributions void
IOKitKernelLogBuffer(const char * title,const void * buffer,size_t size,void (* output)(const char * format,...))1609a5e72196SApple OSS Distributions IOKitKernelLogBuffer(const char * title, const void * buffer, size_t size,
1610cc9a6355SApple OSS Distributions void (*output)(const char *format, ...))
1611cc9a6355SApple OSS Distributions {
1612a5e72196SApple OSS Distributions size_t idx, linestart;
1613a5e72196SApple OSS Distributions enum { bytelen = (sizeof("0xZZ, ") - 1) };
1614a5e72196SApple OSS Distributions char hex[(bytelen * 16) + 1];
1615cc9a6355SApple OSS Distributions uint8_t c, chars[17];
1616cc9a6355SApple OSS Distributions
1617a5e72196SApple OSS Distributions output("%s(0x%lx):\n", title, size);
1618a5e72196SApple OSS Distributions output(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
1619a5e72196SApple OSS Distributions if (size > 4096) {
1620a5e72196SApple OSS Distributions size = 4096;
1621cc9a6355SApple OSS Distributions }
1622a5e72196SApple OSS Distributions chars[16] = 0;
1623a5e72196SApple OSS Distributions for (idx = 0, linestart = 0; idx < size;) {
1624cc9a6355SApple OSS Distributions c = ((char *)buffer)[idx];
1625a5e72196SApple OSS Distributions snprintf(&hex[bytelen * (idx & 15)], bytelen + 1, "0x%02x, ", c);
1626cc9a6355SApple OSS Distributions chars[idx & 15] = ((c >= 0x20) && (c <= 0x7f)) ? c : ' ';
1627cc9a6355SApple OSS Distributions idx++;
1628a5e72196SApple OSS Distributions if ((idx == size) || !(idx & 15)) {
1629a5e72196SApple OSS Distributions if (idx & 15) {
1630cc9a6355SApple OSS Distributions chars[idx & 15] = 0;
1631cc9a6355SApple OSS Distributions }
1632a5e72196SApple OSS Distributions output("/* %04lx: */ %-96s /* |%-16s| */\n", linestart, hex, chars);
1633a5e72196SApple OSS Distributions linestart += 16;
1634cc9a6355SApple OSS Distributions }
1635cc9a6355SApple OSS Distributions }
1636cc9a6355SApple OSS Distributions }
1637cc9a6355SApple OSS Distributions
1638cc9a6355SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1639cc9a6355SApple OSS Distributions
1640e13b1fa5SApple OSS Distributions /*
1641e13b1fa5SApple OSS Distributions * Convert a integer constant (typically a #define or enum) to a string.
1642e13b1fa5SApple OSS Distributions */
1643e13b1fa5SApple OSS Distributions static char noValue[80]; // that's pretty
1644e13b1fa5SApple OSS Distributions
1645a5e72196SApple OSS Distributions const char *
IOFindNameForValue(int value,const IONamedValue * regValueArray)1646a5e72196SApple OSS Distributions IOFindNameForValue(int value, const IONamedValue *regValueArray)
1647e13b1fa5SApple OSS Distributions {
1648e13b1fa5SApple OSS Distributions for (; regValueArray->name; regValueArray++) {
1649a5e72196SApple OSS Distributions if (regValueArray->value == value) {
1650a5e72196SApple OSS Distributions return regValueArray->name;
1651a5e72196SApple OSS Distributions }
1652e13b1fa5SApple OSS Distributions }
1653e13b1fa5SApple OSS Distributions snprintf(noValue, sizeof(noValue), "0x%x (UNDEFINED)", value);
1654a5e72196SApple OSS Distributions return (const char *)noValue;
1655e13b1fa5SApple OSS Distributions }
1656e13b1fa5SApple OSS Distributions
1657a5e72196SApple OSS Distributions IOReturn
IOFindValueForName(const char * string,const IONamedValue * regValueArray,int * value)1658a5e72196SApple OSS Distributions IOFindValueForName(const char *string,
1659e13b1fa5SApple OSS Distributions const IONamedValue *regValueArray,
1660e13b1fa5SApple OSS Distributions int *value)
1661e13b1fa5SApple OSS Distributions {
1662e13b1fa5SApple OSS Distributions for (; regValueArray->name; regValueArray++) {
1663e13b1fa5SApple OSS Distributions if (!strcmp(regValueArray->name, string)) {
1664e13b1fa5SApple OSS Distributions *value = regValueArray->value;
1665e13b1fa5SApple OSS Distributions return kIOReturnSuccess;
1666e13b1fa5SApple OSS Distributions }
1667e13b1fa5SApple OSS Distributions }
1668e13b1fa5SApple OSS Distributions return kIOReturnBadArgument;
1669e13b1fa5SApple OSS Distributions }
1670e13b1fa5SApple OSS Distributions
1671a5e72196SApple OSS Distributions OSString *
IOCopyLogNameForPID(int pid)1672a5e72196SApple OSS Distributions IOCopyLogNameForPID(int pid)
1673e13b1fa5SApple OSS Distributions {
1674e13b1fa5SApple OSS Distributions char buf[128];
1675e13b1fa5SApple OSS Distributions size_t len;
1676e13b1fa5SApple OSS Distributions snprintf(buf, sizeof(buf), "pid %d, ", pid);
1677e13b1fa5SApple OSS Distributions len = strlen(buf);
1678bb611c8fSApple OSS Distributions proc_name(pid, buf + len, (int) (sizeof(buf) - len));
1679a5e72196SApple OSS Distributions return OSString::withCString(buf);
1680e13b1fa5SApple OSS Distributions }
1681e13b1fa5SApple OSS Distributions
1682e13b1fa5SApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1683e13b1fa5SApple OSS Distributions
1684a5e72196SApple OSS Distributions IOAlignment
IOSizeToAlignment(unsigned int size)1685a5e72196SApple OSS Distributions IOSizeToAlignment(unsigned int size)
1686e13b1fa5SApple OSS Distributions {
16870f3703acSApple OSS Distributions int shift;
1688e13b1fa5SApple OSS Distributions const int intsize = sizeof(unsigned int) * 8;
1689e13b1fa5SApple OSS Distributions
1690e13b1fa5SApple OSS Distributions for (shift = 1; shift < intsize; shift++) {
1691a5e72196SApple OSS Distributions if (size & 0x80000000) {
1692e13b1fa5SApple OSS Distributions return (IOAlignment)(intsize - shift);
1693a5e72196SApple OSS Distributions }
1694e13b1fa5SApple OSS Distributions size <<= 1;
1695e13b1fa5SApple OSS Distributions }
1696e13b1fa5SApple OSS Distributions return 0;
1697e13b1fa5SApple OSS Distributions }
1698e13b1fa5SApple OSS Distributions
1699a5e72196SApple OSS Distributions unsigned int
IOAlignmentToSize(IOAlignment align)1700a5e72196SApple OSS Distributions IOAlignmentToSize(IOAlignment align)
1701e13b1fa5SApple OSS Distributions {
1702e13b1fa5SApple OSS Distributions unsigned int size;
1703e13b1fa5SApple OSS Distributions
1704e13b1fa5SApple OSS Distributions for (size = 1; align; align--) {
1705e13b1fa5SApple OSS Distributions size <<= 1;
1706e13b1fa5SApple OSS Distributions }
1707e13b1fa5SApple OSS Distributions return size;
1708e13b1fa5SApple OSS Distributions }
1709e13b1fa5SApple OSS Distributions } /* extern "C" */
1710