X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/89b3af67bb32e691275bf6fa803d1834b2284115..6d2010ae8f7a6078e10b361c6962983bab233e0f:/iokit/Kernel/IOLib.cpp diff --git a/iokit/Kernel/IOLib.cpp b/iokit/Kernel/IOLib.cpp index 5ed1c4708..50000299d 100644 --- a/iokit/Kernel/IOLib.cpp +++ b/iokit/Kernel/IOLib.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,29 @@ #include "IOKitKernelInternal.h" +#ifdef IOALLOCDEBUG +#include +#include +#endif + +#include "libkern/OSAtomic.h" +#include +#include +#include + +#if IOKITSTATS + +#define IOStatisticsAlloc(type, size) \ +do { \ + IOStatistics::countAlloc(type, size); \ +} while (0) + +#else + +#define IOStatisticsAlloc(type, size) + +#endif /* IOKITSTATS */ + extern "C" { @@ -57,13 +81,18 @@ mach_timespec_t IOZeroTvalspec = { 0, 0 }; extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); -extern kern_return_t kmem_suballoc( - vm_map_t parent, - vm_offset_t *addr, - vm_size_t size, - boolean_t pageable, - boolean_t anywhere, - vm_map_t *new_map); +extern int +__doprnt( + const char *fmt, + va_list argp, + void (*putc)(int, void *), + void *arg, + int radix); + +extern void cons_putc_locked(char); +extern void bsd_log_lock(void); +extern void bsd_log_unlock(void); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -92,9 +121,8 @@ enum { kIOMaxPageableMaps = 16 }; enum { kIOPageableMapSize = 96 * 1024 * 1024 }; enum { kIOPageableMaxMapSize = 96 * 1024 * 1024 }; -/* LP64todo - these need to expand */ typedef struct { - vm_map_t map; + vm_map_t map; vm_offset_t address; vm_offset_t end; } IOMapData; @@ -170,20 +198,24 @@ void * IOMalloc(vm_size_t size) void * address; address = (void *)kalloc(size); + if ( address ) { #if IOALLOCDEBUG - if (address) - debug_iomalloc_size += size; + debug_iomalloc_size += size; #endif + IOStatisticsAlloc(kIOStatisticsMalloc, size); + } + return address; } void IOFree(void * address, vm_size_t size) { if (address) { - kfree(address, size); + kfree(address, size); #if IOALLOCDEBUG - debug_iomalloc_size -= size; + debug_iomalloc_size -= size; #endif + IOStatisticsAlloc(kIOStatisticsFree, size); } } @@ -192,10 +224,10 @@ void IOFree(void * address, vm_size_t size) void * IOMallocAligned(vm_size_t size, vm_size_t alignment) { kern_return_t kr; - vm_address_t address; - vm_address_t allocationAddress; + vm_offset_t address; + vm_offset_t allocationAddress; vm_size_t adjustedSize; - vm_offset_t alignMask; + uintptr_t alignMask; if (size == 0) return 0; @@ -231,8 +263,8 @@ void * IOMallocAligned(vm_size_t size, vm_size_t alignment) + (sizeof(vm_size_t) + sizeof(vm_address_t))) & (~alignMask); - *((vm_size_t *)(address - sizeof(vm_size_t) - - sizeof(vm_address_t))) = adjustedSize; + *((vm_size_t *)(address - sizeof(vm_size_t) - sizeof(vm_address_t))) + = adjustedSize; *((vm_address_t *)(address - sizeof(vm_address_t))) = allocationAddress; } else @@ -241,10 +273,12 @@ void * IOMallocAligned(vm_size_t size, vm_size_t alignment) assert(0 == (address & alignMask)); + if( address) { #if IOALLOCDEBUG - if( address) - debug_iomalloc_size += size; + debug_iomalloc_size += size; #endif + IOStatisticsAlloc(kIOStatisticsMallocAligned, size); + } return (void *) address; } @@ -252,7 +286,7 @@ void * IOMallocAligned(vm_size_t size, vm_size_t alignment) void IOFreeAligned(void * address, vm_size_t size) { vm_address_t allocationAddress; - vm_size_t adjustedSize; + vm_size_t adjustedSize; if( !address) return; @@ -262,10 +296,10 @@ void IOFreeAligned(void * address, vm_size_t size) adjustedSize = size + sizeof(vm_size_t) + sizeof(vm_address_t); if (adjustedSize >= page_size) { - kmem_free( kernel_map, (vm_address_t) address, size); + kmem_free( kernel_map, (vm_offset_t) address, size); } else { - adjustedSize = *((vm_size_t *)( (vm_address_t) address + adjustedSize = *((vm_size_t *)( (vm_address_t) address - sizeof(vm_address_t) - sizeof(vm_size_t))); allocationAddress = *((vm_address_t *)( (vm_address_t) address - sizeof(vm_address_t) )); @@ -279,12 +313,14 @@ void IOFreeAligned(void * address, vm_size_t size) #if IOALLOCDEBUG debug_iomalloc_size -= size; #endif + + IOStatisticsAlloc(kIOStatisticsFreeAligned, size); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void -IOKernelFreeContiguous(mach_vm_address_t address, mach_vm_size_t size) +IOKernelFreePhysical(mach_vm_address_t address, mach_vm_size_t size) { mach_vm_address_t allocationAddress; mach_vm_size_t adjustedSize; @@ -297,7 +333,7 @@ IOKernelFreeContiguous(mach_vm_address_t address, mach_vm_size_t size) adjustedSize = (2 * size) + sizeof(mach_vm_size_t) + sizeof(mach_vm_address_t); if (adjustedSize >= page_size) { - kmem_free( kernel_map, (vm_address_t) address, size); + kmem_free( kernel_map, (vm_offset_t) address, size); } else { @@ -314,7 +350,8 @@ IOKernelFreeContiguous(mach_vm_address_t address, mach_vm_size_t size) } mach_vm_address_t -IOKernelAllocateContiguous(mach_vm_size_t size, mach_vm_size_t alignment) +IOKernelAllocateWithPhysicalRestrict(mach_vm_size_t size, mach_vm_address_t maxPhys, + mach_vm_size_t alignment, bool contiguous) { kern_return_t kr; mach_vm_address_t address; @@ -330,19 +367,33 @@ IOKernelAllocateContiguous(mach_vm_size_t size, mach_vm_size_t alignment) alignMask = alignment - 1; adjustedSize = (2 * size) + sizeof(mach_vm_size_t) + sizeof(mach_vm_address_t); - if (adjustedSize >= page_size) + contiguous = (contiguous && (adjustedSize > page_size)) + || (alignment > page_size); + + if (contiguous || maxPhys) { + int options = 0; vm_offset_t virt; + adjustedSize = size; - if (adjustedSize > page_size) + contiguous = (contiguous && (adjustedSize > page_size)) + || (alignment > page_size); + + if ((!contiguous) && (maxPhys <= 0xFFFFFFFF)) + { + maxPhys = 0; + options |= KMA_LOMEM; + } + + if (contiguous || maxPhys) { kr = kmem_alloc_contig(kernel_map, &virt, size, - alignMask, 0); + alignMask, atop(maxPhys), atop(alignMask), 0); } else { kr = kernel_memory_allocate(kernel_map, &virt, - size, alignMask, 0); + size, alignMask, options); } if (KERN_SUCCESS == kr) address = virt; @@ -361,7 +412,7 @@ IOKernelAllocateContiguous(mach_vm_size_t size, mach_vm_size_t alignment) & (~alignMask); if (atop_32(address) != atop_32(address + size - 1)) - address = round_page_32(address); + address = round_page(address); *((mach_vm_size_t *)(address - sizeof(mach_vm_size_t) - sizeof(mach_vm_address_t))) = adjustedSize; @@ -372,13 +423,15 @@ IOKernelAllocateContiguous(mach_vm_size_t size, mach_vm_size_t alignment) } #if IOALLOCDEBUG - if (address) + if (address) { debug_iomalloc_size += size; + } #endif return (address); } + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ struct _IOMallocContiguousEntry @@ -402,16 +455,17 @@ void * IOMallocContiguous(vm_size_t size, vm_size_t alignment, /* Do we want a physical address? */ if (!physicalAddress) { - address = IOKernelAllocateContiguous(size, alignment); + address = IOKernelAllocateWithPhysicalRestrict(size, 0 /*maxPhys*/, alignment, true); } else do { IOBufferMemoryDescriptor * bmd; mach_vm_address_t physicalMask; - vm_offset_t alignMask; + vm_offset_t alignMask; alignMask = alignment - 1; - physicalMask = 0xFFFFFFFF ^ (alignMask & PAGE_MASK); + physicalMask = (0xFFFFFFFF ^ alignMask); + bmd = IOBufferMemoryDescriptor::inTaskWithPhysicalMask( kernel_task, kIOMemoryPhysicallyContiguous, size, physicalMask); if (!bmd) @@ -436,6 +490,10 @@ void * IOMallocContiguous(vm_size_t size, vm_size_t alignment, } while (false); + if (address) { + IOStatisticsAlloc(kIOStatisticsMallocContiguous, size); + } + return (void *) address; } @@ -471,8 +529,10 @@ void IOFreeContiguous(void * _address, vm_size_t size) } else { - IOKernelFreeContiguous((mach_vm_address_t) address, size); + IOKernelFreePhysical((mach_vm_address_t) address, size); } + + IOStatisticsAlloc(kIOStatisticsFreeContiguous, size); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -547,7 +607,7 @@ kern_return_t IOIteratePageableMaps(vm_size_t size, struct IOMallocPageableRef { - vm_address_t address; + vm_offset_t address; vm_size_t size; }; @@ -576,15 +636,17 @@ void * IOMallocPageable(vm_size_t size, vm_size_t alignment) if( kIOReturnSuccess != kr) ref.address = 0; + if( ref.address) { #if IOALLOCDEBUG - if( ref.address) - debug_iomallocpageable_size += round_page_32(size); + debug_iomallocpageable_size += round_page(size); #endif + IOStatisticsAlloc(kIOStatisticsMallocPageable, size); + } return( (void *) ref.address ); } -vm_map_t IOPageableMapForAddress( vm_address_t address ) +vm_map_t IOPageableMapForAddress( uintptr_t address ) { vm_map_t map = 0; UInt32 index; @@ -597,7 +659,7 @@ vm_map_t IOPageableMapForAddress( vm_address_t address ) } } if( !map) - IOPanic("IOPageableMapForAddress: null"); + panic("IOPageableMapForAddress: null"); return( map ); } @@ -611,10 +673,12 @@ void IOFreePageable(void * address, vm_size_t size) kmem_free( map, (vm_offset_t) address, size); #if IOALLOCDEBUG - debug_iomallocpageable_size -= round_page_32(size); + debug_iomallocpageable_size -= round_page(size); #endif -} + IOStatisticsAlloc(kIOStatisticsFreePageable, size); +} + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ IOReturn IOSetProcessorCacheMode( task_t task, IOVirtualAddress address, @@ -625,9 +689,13 @@ IOReturn IOSetProcessorCacheMode( task_t task, IOVirtualAddress address, if( task != kernel_task) return( kIOReturnUnsupported ); - - length = round_page_32(address + length) - trunc_page_32( address ); - address = trunc_page_32( address ); + if ((address | length) & PAGE_MASK) + { +// OSReportWithBacktrace("IOSetProcessorCacheMode(0x%x, 0x%x, 0x%x) fails\n", address, length, cacheMode); + return( kIOReturnUnsupported ); + } + length = round_page(address + length) - trunc_page( address ); + address = trunc_page( address ); // make map mode cacheMode = (cacheMode << kIOMapCacheShift) & kIOMapCacheMask; @@ -656,26 +724,23 @@ IOReturn IOFlushProcessorCache( task_t task, IOVirtualAddress address, if( task != kernel_task) return( kIOReturnUnsupported ); -#if __ppc__ flush_dcache64( (addr64_t) address, (unsigned) length, false ); -#endif return( kIOReturnSuccess ); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -SInt32 OSKernelStackRemaining( void ) +vm_offset_t OSKernelStackRemaining( void ) { - SInt32 stack; - - stack = (((SInt32) &stack) & (KERNEL_STACK_SIZE - 1)); - - return( stack ); + return (ml_stack_remaining()); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* + * Spin for indicated number of milliseconds. + */ void IOSleep(unsigned milliseconds) { delay_for_interval(milliseconds, kMillisecondScale); @@ -689,23 +754,54 @@ void IODelay(unsigned microseconds) delay_for_interval(microseconds, kMicrosecondScale); } +/* + * Spin for indicated number of nanoseconds. + */ +void IOPause(unsigned nanoseconds) +{ + delay_for_interval(nanoseconds, kNanosecondScale); +} + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +static void _iolog_consputc(int ch, void *arg __unused) +{ + cons_putc_locked(ch); +} + +static void _iolog_logputc(int ch, void *arg __unused) +{ + log_putc_locked(ch); +} + void IOLog(const char *format, ...) { - va_list ap; - extern void conslog_putc(char); - extern void logwakeup(void); + va_list ap; - va_start(ap, format); - _doprnt(format, &ap, conslog_putc, 16); - va_end(ap); + va_start(ap, format); + IOLogv(format, ap); + va_end(ap); } +void IOLogv(const char *format, va_list ap) +{ + va_list ap2; + + va_copy(ap2, ap); + + bsd_log_lock(); + __doprnt(format, ap, _iolog_logputc, NULL, 16); + bsd_log_unlock(); + + __doprnt(format, ap2, _iolog_consputc, NULL, 16); +} + +#if !__LP64__ void IOPanic(const char *reason) { - panic(reason); + panic("%s", reason); } +#endif /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -720,7 +816,7 @@ const char *IOFindNameForValue(int value, const IONamedValue *regValueArray) if(regValueArray->value == value) return(regValueArray->name); } - sprintf(noValue, "0x%x (UNDEFINED)", value); + snprintf(noValue, sizeof(noValue), "0x%x (UNDEFINED)", value); return((const char *)noValue); } @@ -737,6 +833,16 @@ IOReturn IOFindValueForName(const char *string, return kIOReturnBadArgument; } +OSString * IOCopyLogNameForPID(int pid) +{ + char buf[128]; + size_t len; + snprintf(buf, sizeof(buf), "pid %d, ", pid); + len = strlen(buf); + proc_name(pid, buf + len, sizeof(buf) - len); + return (OSString::withCString(buf)); +} + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ IOAlignment IOSizeToAlignment(unsigned int size) @@ -763,3 +869,6 @@ unsigned int IOAlignmentToSize(IOAlignment align) } } /* extern "C" */ + + +