#include "libkern/OSAtomic.h"
#include <libkern/c++/OSKext.h>
#include <IOKit/IOStatisticsPrivate.h>
+#include <os/log_private.h>
#include <sys/msgbuf.h>
+#include <console/serial_protos.h>
#if IOKITSTATS
extern void cons_putc_locked(char);
extern void bsd_log_lock(void);
extern void bsd_log_unlock(void);
-extern void logwakeup();
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#if IOTRACKING
IOTrackingInit();
- gIOMallocTracking = IOTrackingQueueAlloc(kIOMallocTrackingName, 0, 0, true);
- gIOWireTracking = IOTrackingQueueAlloc(kIOWireTrackingName, 0, page_size, false);
- gIOMapTracking = IOTrackingQueueAlloc(kIOMapTrackingName, 0, page_size, false);
+ gIOMallocTracking = IOTrackingQueueAlloc(kIOMallocTrackingName, 0, 0, 0,
+ kIOTrackingQueueTypeAlloc,
+ 37);
+ gIOWireTracking = IOTrackingQueueAlloc(kIOWireTrackingName, 0, 0, page_size, 0, 0);
+
+ size_t mapCaptureSize = (kIOTracking & gIOKitDebug) ? page_size : (1024*1024);
+ gIOMapTracking = IOTrackingQueueAlloc(kIOMapTrackingName, 0, 0, mapCaptureSize,
+ kIOTrackingQueueTypeDefaultOn
+ | kIOTrackingQueueTypeMap
+ | kIOTrackingQueueTypeUser,
+ 0);
#endif
gIOKitPageableSpace.maps[0].address = 0;
&gIOKitPageableSpace.maps[0].address,
kIOPageableMapSize,
TRUE,
- VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_KERN_MEMORY_IOKIT),
+ VM_FLAGS_ANYWHERE,
+ VM_MAP_KERNEL_FLAGS_NONE,
+ VM_KERN_MEMORY_IOKIT,
&gIOKitPageableSpace.maps[0].map);
if (ret != KERN_SUCCESS)
panic("failed to allocate iokit pageable map\n");
bzero(&hdr->tracking, sizeof(hdr->tracking));
hdr->tracking.address = ~(((uintptr_t) address) + sizeofIOLibMallocHeader);
hdr->tracking.size = size;
- IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true);
+ IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true, VM_KERN_MEMORY_NONE);
}
#endif
address = (typeof(address)) (((uintptr_t) address) + sizeofIOLibMallocHeader);
return address;
}
-void IOFree(void * address, vm_size_t size)
+void IOFree(void * inAddress, vm_size_t size)
{
- if (address) {
+ void * address;
+ if ((address = inAddress))
+ {
address = (typeof(address)) (((uintptr_t) address) - sizeofIOLibMallocHeader);
#if IOTRACKING
- if (TRACK_ALLOC) {
+ if (TRACK_ALLOC)
+ {
IOLibMallocHeader * hdr;
+ struct ptr_reference{ void * ptr; };
+ volatile struct ptr_reference ptr;
+
+ // we're about to block in IOTrackingRemove(), make sure the original pointer
+ // exists in memory or a register for leak scanning to find
+ ptr.ptr = inAddress;
+
hdr = (typeof(hdr)) address;
if (size != hdr->tracking.size)
{
size = hdr->tracking.size;
}
IOTrackingRemove(gIOMallocTracking, &hdr->tracking.tracking, size);
+ ptr.ptr = NULL;
}
#endif
bzero(&hdr->tracking, sizeof(hdr->tracking));
hdr->tracking.address = ~address;
hdr->tracking.size = size;
- IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true);
+ IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true, VM_KERN_MEMORY_NONE);
}
#endif
} else
#endif
}
+#if __arm__ || __arm64__
+extern unsigned long gPhysBase, gPhysSize;
+#endif
mach_vm_address_t
IOKernelAllocateWithPhysicalRestrict(mach_vm_size_t size, mach_vm_address_t maxPhys,
alignment = 1;
alignMask = alignment - 1;
- adjustedSize = (2 * size) + sizeofIOLibPageMallocHeader;
- if (adjustedSize < size) return (0);
+
+ if (os_mul_and_add_overflow(2, size, sizeofIOLibPageMallocHeader, &adjustedSize)) return (0);
contiguous = (contiguous && (adjustedSize > page_size))
|| (alignment > page_size);
if (!contiguous)
{
+#if __arm__ || __arm64__
+ if (maxPhys >= (mach_vm_address_t)(gPhysBase + gPhysSize))
+ {
+ maxPhys = 0;
+ }
+ else
+#endif
if (maxPhys <= 0xFFFFFFFF)
{
maxPhys = 0;
bzero(&hdr->tracking, sizeof(hdr->tracking));
hdr->tracking.address = ~address;
hdr->tracking.size = size;
- IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true);
+ IOTrackingAdd(gIOMallocTracking, &hdr->tracking.tracking, size, true, VM_KERN_MEMORY_NONE);
}
#endif
} else
else
index = gIOKitPageableSpace.count - 1;
}
- if( KERN_SUCCESS == kr)
+ if (KERN_NO_SPACE != kr)
break;
lck_mtx_lock( gIOKitPageableSpace.lock );
&min,
segSize,
TRUE,
- VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_KERN_MEMORY_IOKIT),
+ VM_FLAGS_ANYWHERE,
+ VM_MAP_KERNEL_FLAGS_NONE,
+ VM_KERN_MEMORY_IOKIT,
&map);
if( KERN_SUCCESS != kr) {
lck_mtx_unlock( gIOKitPageableSpace.lock );
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-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);
-}
+static void _IOLogv(const char *format, va_list ap, void *caller) __printflike(1,0);
+__attribute__((noinline,not_tail_called))
void IOLog(const char *format, ...)
{
+ void *caller = __builtin_return_address(0);
va_list ap;
va_start(ap, format);
- IOLogv(format, ap);
+ _IOLogv(format, ap, caller);
va_end(ap);
}
+__attribute__((noinline,not_tail_called))
void IOLogv(const char *format, va_list ap)
+{
+ void *caller = __builtin_return_address(0);
+ _IOLogv(format, ap, caller);
+}
+
+void _IOLogv(const char *format, va_list ap, void *caller)
{
va_list ap2;
+ struct console_printbuf_state info_data;
+ console_printbuf_state_init(&info_data, TRUE, TRUE);
va_copy(ap2, ap);
- bsd_log_lock();
- __doprnt(format, ap, _iolog_logputc, NULL, 16, TRUE);
- bsd_log_unlock();
- logwakeup();
+ os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, format, ap, caller);
- __doprnt(format, ap2, _iolog_consputc, NULL, 16, TRUE);
+ __doprnt(format, ap2, console_printbuf_putc, &info_data, 16, TRUE);
+ console_printbuf_clear(&info_data);
va_end(ap2);
+
+ assertf(ml_get_interrupts_enabled() || ml_is_quiescing() || debug_mode_active() || !gCPUsRunning, "IOLog called with interrupts disabled");
}
#if !__LP64__
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+void IOKitKernelLogBuffer(const char * title, const void * buffer, size_t size,
+ void (*output)(const char *format, ...))
+{
+ uint8_t c, chars[17];
+ size_t idx;
+
+ output("%s(0x%x):\n", title, size);
+ if (size > 4096) size = 4096;
+ chars[16] = idx = 0;
+ while (true) {
+ if (!(idx & 15)) {
+ if (idx) output(" |%s|\n", chars);
+ if (idx >= size) break;
+ output("%04x: ", idx);
+ }
+ else if (!(idx & 7)) output(" ");
+
+ c = ((char *)buffer)[idx];
+ output("%02x ", c);
+ chars[idx & 15] = ((c >= 0x20) && (c <= 0x7f)) ? c : ' ';
+
+ idx++;
+ if ((idx == size) && (idx & 15)) {
+ chars[idx & 15] = 0;
+ while (idx & 15) {
+ idx++;
+ output(" ");
+ }
+ }
+ }
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
/*
* Convert a integer constant (typically a #define or enum) to a string.
*/