/* * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef BSD_KDEBUG_PRIVATE_H #define BSD_KDEBUG_PRIVATE_H #include <stdint.h> #include <stdbool.h> #include <sys/cdefs.h> #include <sys/kdebug.h> __BEGIN_DECLS #if !KERNEL #include <Availability.h> #pragma mark - user space SPI /* * OS components can use the full precision of the "code" field * (Class, SubClass, Code) to inject events using kdebug_trace() by * using: * * kdebug_trace(KDBG_CODE(DBG_XPC, 15, 1) | DBG_FUNC_NONE, 1, 2, 3, 4); * * These trace points can be included in production code, since they * use reserved, non-overlapping ranges. The performance impact when * kernel tracing is not enabled is minimal. However, when tracing is enabled, * each tracepoint becomes a syscall. For this reason, os_signpost(3) is * recommended instead of kdebug_trace(2). * * Classes can be reserved by filing a Radar in xnu | ktrace. * * 64-bit arguments may be truncated if the system is using a 32-bit * kernel. * * On error, -1 will be returned and errno will indicate the error. */ int kdebug_trace(uint32_t code, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) __OSX_AVAILABLE(10.10) __IOS_AVAILABLE(8.2); /*! * @function kdebug_trace_string * * @discussion * This function emits strings to kdebug trace along with an ID and allows * for previously-traced strings to be overwritten and invalidated. * * To start tracing a string and generate an ID to use to refer to it: * * string_id = kdebug_trace_string(debugid, 0, "string"); * * To replace a string previously traced: * * string_id = kdebug_trace_string(debugid, string_id, "new string"); * * To invalidate a string ID: * * string_id = kdebug_trace_string(debugid, string_id, NULL); * * To check for errors: * * if ((int64_t)string_id == -1) { perror("string error") } * * @param debugid * The `debugid` to check if its enabled before tracing and include as * an argument in the event containing the string. * * Some classes or subclasses are reserved for specific uses and are not * allowed to be used with this function. No function qualifiers are * allowed on `debugid`. * * @param str_id * When 0, a new ID will be generated and returned if tracing is * enabled. * * Otherwise `str_id` must contain an ID that was previously generated * with this function. Clents should pass NULL in `str` if `str_id` * is no longer in use. Otherwise, the string previously mapped to * `str_id` will be overwritten with the contents of `str`. * * @param str * A NUL-terminated 'C' string containing the characters that should be * traced alongside `str_id`. * * If necessary, the string will be truncated at an * implementation-defined length. The string must not be the empty * string, but can be NULL if a valid `str_id` is provided. * * @return * 0 if tracing is disabled or `debugid` is being filtered out of trace. * It can also return (int64_t)-1 if an error occured. Otherwise, * it returns the ID to use to refer to the string in future * kdebug_trace(2) calls. * * The errors that can occur are: * * EINVAL * There are function qualifiers on `debugid`, `str` is empty, or * `str_id` was not generated by this function. * EPERM * The `debugid`'s class or subclass is reserved for internal use. * EFAULT * `str` is an invalid address or NULL when `str_id` is 0. */ extern uint64_t kdebug_trace_string(uint32_t debugid, uint64_t str_id, const char *str) __OSX_AVAILABLE(10.11) __IOS_AVAILABLE(9.0); /* * Although the performance impact of kdebug_trace() when kernel * tracing is not enabled is minimal, it may require the caller to * perform an expensive calculation/summarization. This cost can be * skipped by checking the kdebug_is_enabled() predicate: * * if (kdebug_is_enabled(KDBG_CODE(DBG_XPC, 15, 1))) { * uint64_t arg1 = ...; * uint64_t arg2 = ...; * kdebug_trace(KDBG_CODE(DBG_XPC, 15, 1) | DBG_FUNC_NONE, arg1, arg2, 0, 0); * } * * If tracing is enabled for the code at the time of the check, 1 * will be returned. Otherwise, 0 will be returned. */ extern bool kdebug_is_enabled(uint32_t code) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0); /* * Returns a pointer to the userspace typefilter, if one is available. * May return NULL. */ extern void *kdebug_typefilter(void) __OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0) __TVOS_AVAILABLE(10.0); /* * Returns true if kdebug is using continuous time for its events, and false * otherwise. */ extern bool kdebug_using_continuous_time(void) __API_AVAILABLE(macos(10.15), ios(13), tvos(13), watchos(6)); #endif /* !KERNEL */ #pragma mark - private debugids #define DBG_PPT 36 #define DBG_PERFCTRL 39 #define DBG_CLPC 50 #define DBG_MUSE 52 /* **** 128 to 139 are reserved for IOP tracing **** */ #define DBG_ANS 128 #define DBG_SIO 129 #define DBG_SEP 130 #define DBG_ISP 131 #define DBG_OSCAR 132 #define DBG_EMBEDDEDGFX 133 #define DBG_PMP 134 #define DBG_RTKIT 135 #define MACH_BRIDGE_RCV_TS 0x1 /* receive timestamp pair from interrupt handler */ #define MACH_BRIDGE_REMOTE_TIME 0x2 /* calculate remote timestamp */ #define MACH_BRIDGE_RESET_TS 0x3 /* reset timestamp conversion parameters */ #define MACH_BRIDGE_TS_PARAMS 0x4 /* recompute timestamp conversion parameters */ #define MACH_BRIDGE_SKIP_TS 0x5 /* skip timestamp */ #define MACH_BRIDGE_TS_MISMATCH 0x6 /* mismatch between predicted and received remote timestamp */ #define MACH_BRIDGE_OBSV_RATE 0x7 /* out of range observed rates */ /* DBG_SKYWALK has same toplevel code as DBG_DLIL, so don't reuse subcodes */ #define DBG_SKYWALK_ALWAYSON 0x10 #define DBG_SKYWALK_FLOWSWITCH 0x11 #define DBG_SKYWALK_NETIF 0x12 #define DBG_SKYWALK_CHANNEL 0x13 #define DBG_SKYWALK_PACKET 0x14 #define PPT_TEST 0x01 #define PPT_JETSAM_HIWAT 0x02 #define PPT_JETSAM_TOPPROC 0x03 #define SKYWALKDBG_CODE(SubClass, code) KDBG_CODE(DBG_DLIL, SubClass, code) #define PPTDBG_CODE(SubClass, code) KDBG_CODE(DBG_PPT, SubClass, code) #define PERFCTRL_CODE(SubClass, code) KDBG_CODE(DBG_PERFCTRL, SubClass, code) #if !defined(DRIVERKIT) extern unsigned int kdebug_enable; /* * Bits used by kdebug_enable. These control which events are traced at * runtime. */ #define KDEBUG_ENABLE_TRACE (1U << 0) #define KDEBUG_ENABLE_ENTROPY (1U << 1) /* obsolete */ #define KDEBUG_ENABLE_CHUD (1U << 2) /* obsolete */ #define KDEBUG_ENABLE_PPT (1U << 3) /* obsolete */ #define KDEBUG_ENABLE_SERIAL (1U << 4) /* obsolete */ /* * If set, the timestamps in events are expected to be continuous times. * Otherwise, the timestamps are absolute times. IOPs should observe this bit * in order to log events that can be merged cleanly with other event streams. */ #define KDEBUG_ENABLE_CONT_TIME 0x20 #define KDEBUG_TRACE (KDEBUG_ENABLE_TRACE) /* * Specify KDEBUG_PPT to indicate that the event belongs to the limited PPT set. * PPT is deprecated -- use a typefilter and the PPTDBG class instead. */ #define KDEBUG_PPT (KDEBUG_ENABLE_PPT) #define KDEBUG_COMMON (KDEBUG_ENABLE_TRACE | KDEBUG_ENABLE_PPT) /* * The kernel debug configuration level. These values control which events are * compiled in under different build configurations. * * Infer the supported kernel debug event level from config option. Use * (KDEBUG_LEVEL >= KDEBUG_LEVEL_STANDARD) as a guard to protect unaudited debug * code. */ #define KDEBUG_LEVEL_NONE 0 #define KDEBUG_LEVEL_IST 1 #define KDEBUG_LEVEL_STANDARD 2 #define KDEBUG_LEVEL_FULL 3 #if NO_KDEBUG #define KDEBUG_LEVEL KDEBUG_LEVEL_NONE #elif IST_KDEBUG #define KDEBUG_LEVEL KDEBUG_LEVEL_IST #elif KDEBUG #define KDEBUG_LEVEL KDEBUG_LEVEL_FULL #else #define KDEBUG_LEVEL KDEBUG_LEVEL_STANDARD /* * Currently, all other kernel configurations (development, etc) build with * KDEBUG_LEVEL_STANDARD. */ #endif /* * Some Apple internal clients try to use the kernel macros in user space. */ #ifndef KERNEL_DEBUG #define KERNEL_DEBUG(...) do { } while (0) #endif /* !defined(KERNEL_DEBUG) */ #pragma mark - private definitions /* * Ensure that both LP32 and LP64 variants of arm64 use the same kd_buf * structure. */ #if defined(__arm64__) typedef uint64_t kd_buf_argtype; #else typedef uintptr_t kd_buf_argtype; #endif typedef struct { uint64_t timestamp; kd_buf_argtype arg1; kd_buf_argtype arg2; kd_buf_argtype arg3; kd_buf_argtype arg4; kd_buf_argtype arg5; /* the thread ID */ uint32_t debugid; /* * Ensure that both LP32 and LP64 variants of arm64 use the same kd_buf * structure. */ #if defined(__LP64__) || defined(__arm64__) uint32_t cpuid; kd_buf_argtype unused; #endif } kd_buf; #if defined(__LP64__) || defined(__arm64__) #define KDBG_TIMESTAMP_MASK 0xffffffffffffffffULL static inline void kdbg_set_cpu(kd_buf *kp, int cpu) { kp->cpuid = (unsigned int)cpu; } static inline int kdbg_get_cpu(kd_buf *kp) { return (int)kp->cpuid; } static inline void kdbg_set_timestamp(kd_buf *kp, uint64_t thetime) { kp->timestamp = thetime; } static inline uint64_t kdbg_get_timestamp(kd_buf *kp) { return kp->timestamp; } static inline void kdbg_set_timestamp_and_cpu(kd_buf *kp, uint64_t thetime, int cpu) { kdbg_set_timestamp(kp, thetime); kdbg_set_cpu(kp, cpu); } #else #define KDBG_TIMESTAMP_MASK 0x00ffffffffffffffULL #define KDBG_CPU_MASK 0xff00000000000000ULL #define KDBG_CPU_SHIFT 56 static inline void kdbg_set_cpu(kd_buf *kp, int cpu) { kp->timestamp = (kp->timestamp & KDBG_TIMESTAMP_MASK) | (((uint64_t) cpu) << KDBG_CPU_SHIFT); } static inline int kdbg_get_cpu(kd_buf *kp) { return (int) (((kp)->timestamp & KDBG_CPU_MASK) >> KDBG_CPU_SHIFT); } static inline void kdbg_set_timestamp(kd_buf *kp, uint64_t thetime) { kp->timestamp = thetime & KDBG_TIMESTAMP_MASK; } static inline uint64_t kdbg_get_timestamp(kd_buf *kp) { return kp->timestamp & KDBG_TIMESTAMP_MASK; } static inline void kdbg_set_timestamp_and_cpu(kd_buf *kp, uint64_t thetime, int cpu) { kp->timestamp = (thetime & KDBG_TIMESTAMP_MASK) | (((uint64_t) cpu) << KDBG_CPU_SHIFT); } #endif /* * 2^16 bits (8 kilobytes), one for each possible class/subclass combination */ #define KDBG_TYPEFILTER_BITMAP_SIZE ((256 * 256) / 8) /* * Bits for kd_ctrl_page.flags, KERN_KD{D,E}FLAGS. */ #define KDBG_INIT (1U << 0) /* obsolete */ /* disable tracing when buffers are full */ #define KDBG_NOWRAP (1U << 1) #define KDBG_FREERUN (1U << 2) /* obsolete */ /* buffer has wrapped */ #define KDBG_WRAPPED (1U << 3) /* flags that are allowed to be set by user space */ #define KDBG_USERFLAGS (KDBG_FREERUN | KDBG_NOWRAP | KDBG_INIT) /* only include processes with kdebug bit set in proc */ #define KDBG_PIDCHECK (1U << 4) /* thread map is initialized */ #define KDBG_MAPINIT (1U << 5) /* exclude processes based on kdebug bit in proc */ #define KDBG_PIDEXCLUDE (1U << 6) /* whether the kdebug locks are intialized */ #define KDBG_LOCKINIT (1U << 7) /* word size of the kernel */ #define KDBG_LP64 (1U << 8) /* bits for kd_ctrl_page.flags and kbufinfo_t.flags */ /* only trace events within a range */ #define KDBG_RANGECHECK 0x00100000U /* only trace at most 4 types of events, at the code granularity */ #define KDBG_VALCHECK 0x00200000U /* check class and subclass against the typefilter */ #define KDBG_TYPEFILTER_CHECK 0x00400000U /* kdebug trace buffers are initialized */ #define KDBG_BUFINIT 0x80000000U /* bits for the type field of kd_regtype */ #define KDBG_CLASSTYPE 0x10000 #define KDBG_SUBCLSTYPE 0x20000 #define KDBG_RANGETYPE 0x40000 #define KDBG_TYPENONE 0x80000 #define KDBG_CKTYPES 0xF0000 typedef struct { unsigned int type; unsigned int value1; unsigned int value2; unsigned int value3; unsigned int value4; } kd_regtype; typedef struct { /* number of events that can fit in the buffers */ int nkdbufs; /* set if trace is disabled */ int nolog; /* kd_ctrl_page.flags */ unsigned int flags; /* number of threads in thread map */ int nkdthreads; /* the owning pid */ int bufid; } kbufinfo_t; typedef struct { /* the thread ID */ #if defined(__arm64__) uint64_t thread; #else uintptr_t thread; #endif /* 0 for invalid, otherwise the PID (or 1 for kernel_task) */ int valid; /* the name of the process owning the thread */ char command[20]; } kd_threadmap; typedef struct { uint32_t version_no; uint32_t cpu_count; } kd_cpumap_header; /* cpumap flags */ #define KDBG_CPUMAP_IS_IOP 0x1 typedef struct { uint32_t cpu_id; uint32_t flags; char name[8]; } kd_cpumap; typedef struct { int version_no; int thread_count; uint64_t TOD_secs; uint32_t TOD_usecs; } RAW_header; #define RAW_VERSION0 0x55aa0000 #define RAW_VERSION1 0x55aa0101 #define RAW_VERSION2 0x55aa0200 /* Only used by kperf and Instruments */ /* * Bits set in the comm page for kdebug. */ #define KDEBUG_COMMPAGE_ENABLE_TRACE 0x1 #define KDEBUG_COMMPAGE_ENABLE_TYPEFILTER 0x2 /* Forced to false if ENABLE_TRACE is 0 */ #pragma mark - EnergyTracing /* for EnergyTracing user space & clients */ #define kEnTrCompKernel 2 /* * EnergyTracing opcodes * * Activations use DBG_FUNC_START/END. * Events are DBG_FUNC_NONE. */ /* Socket reads and writes are uniquely identified by the (sanitized) * pointer to the socket struct in question. To associate this address * with the user space file descriptor, we have a socket activation with * the FD as its identifier and the socket struct pointer as its value. */ #define kEnTrActKernSocket 1 #define kEnTrActKernSockRead 2 #define kEnTrActKernSockWrite 3 #define kEnTrActKernPoll 10 #define kEnTrActKernSelect 11 #define kEnTrActKernKQWait 12 // events #define kEnTrEvUnblocked 256 // EnergyTracing flags (the low-order 16 bits of 'quality') #define kEnTrFlagNonBlocking 1 << 0 #define kEnTrFlagNoWork 1 << 1 /* * EnergyTracing macros. */ #if (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) // whether to bother calculating EnergyTracing inputs // could change in future to see if DBG_ENERGYTRACE is active #define ENTR_SHOULDTRACE kdebug_enable // encode logical EnergyTracing into 32/64 KDebug trace #define ENTR_KDTRACE(component, opcode, lifespan, id, quality, value) \ do { \ uint32_t kdcode__; \ uintptr_t highval__, lowval__, mask__ = 0xffffffff; \ kdcode__ = KDBG_CODE(DBG_ENERGYTRACE,component,opcode)|(lifespan); \ highval__ = ((value) >> 32) & mask__; \ lowval__ = (value) & mask__; \ ENTR_KDTRACEFUNC(kdcode__, id, quality, highval__, lowval__); \ } while(0) /* * Trace the association of two existing activations. * * An association is traced as a modification to the parent activation. * In order to fit the sub-activation's component, activation code, and * activation ID into a kdebug tracepoint, the arguments that would hold * the value are left separate, and one stores the component and opcode * of the sub-activation, while the other stores the pointer-sized * activation ID. * * arg2 arg3 arg4 +-----------------+ +~+----+----+--------+ +----------+ |kEnTrModAssociate| | | | | | | | +-----------------+ +~+----+----+--------+ +----------+ * 8-bits unused sub-activation ID * 8-bit sub-component * 16-bit sub-opcode * */ #define kEnTrModAssociate (1 << 28) #define ENTR_KDASSOCIATE(par_comp, par_opcode, par_act_id, \ sub_comp, sub_opcode, sub_act_id) \ do { \ unsigned sub_compcode = ((unsigned)sub_comp << 16) | sub_opcode; \ ENTR_KDTRACEFUNC(KDBG_CODE(DBG_ENERGYTRACE,par_comp,par_opcode), \ par_act_id, kEnTrModAssociate, sub_compcode, \ sub_act_id); \ } while(0) #else /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */ #define ENTR_SHOULDTRACE FALSE #define ENTR_KDTRACE(component, opcode, lifespan, id, quality, value) \ do {} while (0) #define ENTR_KDASSOCIATE(par_comp, par_opcode, par_act_id, \ sub_comp, sub_opcode, sub_act_id) \ do {} while (0) #endif /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */ #endif /* !defined(DRIVERKIT) */ __END_DECLS #endif /* !defined(BSD_KDEBUG_PRIVATE_H) */