This is xnu-11215.1.10. See this file in:
/*
 * Copyright (c) 2000-2021 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 <os/base.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/cdefs.h>
#include <sys/kdebug.h>

#if !KERNEL

#include <Availability.h>

__BEGIN_DECLS

#pragma mark - User space SPI

// Internal software can trace events into kdebug, but the os_signpost(3)
// interfaces in `<os/signpost.h>` are recommended.
//
//     kdebug_trace(KDBG_EVENTID(DBG_XPC, 15, 1), 1, 2, 3, 4);
//
// The performance impact when kernel tracing is not enabled is minimal.
// However, when tracing is enabled, each event requires a syscall.
//
// 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 debugid, uint64_t arg1, uint64_t arg2, uint64_t arg3,
    uint64_t arg4)
__API_AVAILABLE(macos(10.0), ios(8), tvos(8), watchos(1));

// Although the performance impact of kdebug_trace() when tracing is disabled is
// minimal, it may require the caller to perform an expensive calculation or
// 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_EVENTID(DBG_XPC, 15, 1), arg1, arg2, 0, 0);
//     }
//
// true is returned iff tracing is enabled for the debug ID at the time of the
// check.
extern bool kdebug_is_enabled(uint32_t debugid)
__API_AVAILABLE(macos(10.12), ios(10), watchos(3), tvos(10));

// 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));

// Convert an absolute time to a kdebug timestamp.
extern uint64_t kdebug_timestamp_from_absolute(uint64_t abstime)
__API_AVAILABLE(macos(12), ios(15), tvos(15), watchos(8));

// Convert a continuous time to a kdebug timestamp.
extern uint64_t kdebug_timestamp_from_continuous(uint64_t conttime)
__API_AVAILABLE(macos(12), ios(15), tvos(15), watchos(8));

// Capture a kdebug timestamp for the current time.
extern uint64_t kdebug_timestamp(void)
__API_AVAILABLE(macos(12), ios(15), tvos(15), watchos(8));

/// @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 of at least PATH_MAX characters.  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)
__API_AVAILABLE(macos(10.11), ios(9), watchos(2), tvos(9));

// Returns a pointer to the userspace typefilter, if one is available.
// May return NULL.
extern void *kdebug_typefilter(void)
__API_AVAILABLE(macos(10.12), ios(10), watchos(3), tvos(10));

#else
__BEGIN_DECLS
#endif /* !KERNEL */

#pragma mark - Private debug IDs

#define DBG_PPT      36
#define DBG_PERFCTRL 39
#define DBG_CLPC     50
#define DBG_MUSE     52

#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 DBG_DCP         136
#define DBG_KMP         137

// DBG_SKYWALK is the same as DBG_DLIL, so don't reuse subclasses
#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

// DBG_AQM is the same as DBG_DLIL and DBG_SKYWALK, so don't reuse subclasses
#define DBG_AQM_ALWAYSON       0x30
#define DBG_AQM_STATS          0x31

#define PPT_TEST           0x01
#define PPT_JETSAM_HIWAT   0x02
#define PPT_JETSAM_TOPPROC 0x03

// DBG_SECURITY private subclasses
#define DBG_SEC_SSMA 0x02

#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)
#define AQMDBG_CODE(SubClass, code) KDBG_CODE(DBG_DLIL, SubClass, code)

#if !defined(DRIVERKIT)

extern unsigned int kdebug_enable;

// Options for `kdebug_enable`.

// Enable tracing.
#define KDEBUG_ENABLE_TRACE     0x001U
// Whether timestamps are continuous times or absolute times.
#define KDEBUG_ENABLE_CONT_TIME 0x020U

#define KDEBUG_TRACE (KDEBUG_ENABLE_TRACE)

// Control which kernel events are compiled in under different build
// configurations.

// No kdebug events are emitted with the macros.
#define KDEBUG_LEVEL_NONE     0
// In-System Tracing exposes a limited set of events for release kernels.
#define KDEBUG_LEVEL_IST      1
// The default for development kernels.
#define KDEBUG_LEVEL_STANDARD 2
// Truly verbose, debug-level logging, only set manually.
#define KDEBUG_LEVEL_FULL     3

// Use configuration options to set the kdebug level.
#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 // !NO_KDEBUG && !IST_KDEBUG && !KDEBUG
#define KDEBUG_LEVEL KDEBUG_LEVEL_STANDARD
#endif // !NO_KDEBUG && !IST_KDEBUG && !KDEBUG

#pragma mark - Implementation details

// Ensure that LP32 and LP64 variants of arm64 use the same kd_buf structure.
#if defined(__arm64__)
typedef uint64_t kd_buf_argtype;
#else // defined(__arm64__)
typedef uintptr_t kd_buf_argtype;
#endif // !defined(__arm64__)

// The main event ABI as recorded in the kernel.

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; // Always the thread ID.
	uint32_t debugid;
// Ensure that 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 // defined(__LP64__) || defined(__arm64__)
} 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 // defined(__LP64__) || defined(__arm64__)
#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 // !defined(__LP64__) && !defined(__arm64__)

// 8KB, one bit for each possible class/subclass combination.
#define KDBG_TYPEFILTER_BITMAP_SIZE ((256 * 256) / 8)

// Settings that may need to be changed while tracing, protected by the storage
// lock or the ktrace lock if tracing is disabled.
//
// These flags must not overlap with `kdebug_flags_t`.
__options_decl(kdebug_live_flags_t, uint32_t, {
	// Disable tracing when events wrap.  Set while reading events.
	KDBG_NOWRAP = 0x0002,
	// Events have wrapped.
	KDBG_WRAPPED = 0x0008,
});

// Mostly configuration options, protected by the ktrace lock.
__options_decl(kdebug_flags_t, uint32_t, {
	// Only trace processes with the kdebug bit set.
	KDBG_PIDCHECK = 0x0010,
	// Thread map pointer is valid.
	KDBG_MAPINIT = 0x0020,
	// Exclude events from processes with the kdebug bit set.
	KDBG_PIDEXCLUDE = 0x0040,
	// Events are 64-bit, only for `kbufinfo_t`.
	KDBG_LP64 = 0x0100,
	// Timestamps are continuous time, instead of absolute time.
	KDBG_CONTINUOUS_TIME = 0x0200,
	// Exclude events from coprocessors (IOPs).
	KDBG_DISABLE_COPROCS = 0x0400,
	// Disable tracing on event match.
	KDBG_MATCH_DISABLE = 0x0800,
	// Check the typefilter.
	KDBG_TYPEFILTER_CHECK = 0x00400000,
	// 64-bit debug ID present in arg4 (triage-only).
	KDBG_DEBUGID_64 = 0x00800000,
	// Event storage buffers are initialized.
	KDBG_BUFINIT = 0x80000000U,
});

// Obsolete flags.
#define KDBG_INIT    0x01
#define KDBG_FREERUN 0x04

// Flags in `kdebug_live_flags_t` and `kdebug_flags_t` that can be modified by
// user space.
#define KDBG_USERFLAGS (KDBG_NOWRAP | KDBG_CONTINUOUS_TIME | \
    KDBG_DISABLE_COPROCS | KDBG_MATCH_DISABLE)

// Information about kdebug for user space consumption.
typedef struct {
	// Size of buffers in number of events (kd_bufs).
	int nkdbufs;
	// True is tracing is disabled, false otherwise.
	int nolog;
	// Combined `kdebug_live_flags_t` and `kdebug_state_t`.
	unsigned int flags;
	// Number of threads in the thread map.
	int nkdthreads;
	// Owning process PID.
	int bufid;
} kbufinfo_t;

// Header for CPU mapping list.
typedef struct {
	uint32_t version_no;
	uint32_t cpu_count;
} kd_cpumap_header;

// CPU map entry flags.
#define KDBG_CPUMAP_IS_IOP 0x1

// CPU map entries to map `cpuid` from events to names.
typedef struct {
	uint32_t cpu_id;
	uint32_t flags;
	char name[32];
} kd_cpumap_ext;

// Match structured data from events.
typedef struct {
	uint32_t kem_debugid;
	uint32_t kem_padding;
	uint64_t kem_args[4];
} kd_event_matcher;

// Options for `kdebug_enable` in the comm-page.
#define KDEBUG_COMMPAGE_ENABLE_TRACE      0x1
#define KDEBUG_COMMPAGE_ENABLE_TYPEFILTER 0x2
#define KDEBUG_COMMPAGE_CONTINUOUS        0x4

#pragma mark - Tests

// Test scenarios.
__enum_decl(kdebug_test_t, uint32_t, {
	KDTEST_KERNEL_MACROS = 1,
	KDTEST_OLD_TIMESTAMP,
	KDTEST_FUTURE_TIMESTAMP,
	KDTEST_SETUP_IOP,
	KDTEST_SETUP_COPROCESSOR,
	KDTEST_CONTINUOUS_TIMESTAMP,
	KDTEST_ABSOLUTE_TIMESTAMP,
	KDTEST_PAST_EVENT,
});

#pragma mark - Obsolete interfaces

// 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)

// Obsolete options for `kdebug_enable`.
#define KDEBUG_ENABLE_ENTROPY   0x002U
#define KDEBUG_ENABLE_CHUD      0x004U
#define KDEBUG_ENABLE_PPT       0x008U
#define KDEBUG_ENABLE_SERIAL    0x010U
#define KDEBUG_PPT    (KDEBUG_ENABLE_PPT)
#define KDEBUG_COMMON (KDEBUG_ENABLE_TRACE | KDEBUG_ENABLE_PPT)

// Obsolete flags.
#define KDBG_LOCKINIT   0x0080
#define KDBG_RANGECHECK 0x00100000U
#define KDBG_VALCHECK   0x00200000U

// Type values for `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;

// Entry for the legacy thread map system (replaced by stackshot).
typedef struct {
	// A thread's unique ID.
#if defined(__arm64__)
	uint64_t thread;
#else
	uintptr_t thread __kernel_data_semantics;
#endif
	// The process ID (or 1 for `kernproc`).
	int valid;
	// The name of the process owning this thread.
	char command[20];
} kd_threadmap;

// Legacy CPU map entry.
typedef struct {
	uint32_t cpu_id;
	uint32_t flags;
	char name[8];
} kd_cpumap;

// File header for legacy trace files.
typedef struct {
	int version_no;
	int thread_count;
	uint64_t TOD_secs;
	uint32_t TOD_usecs;
} RAW_header;

// Obsolete `version_no` for legacy trace files.
#define RAW_VERSION0 0x55aa0000
#define RAW_VERSION1 0x55aa0101
#define RAW_VERSION2 0x55aa0200

// Obsolete EnergyTracing definitions.

#define kEnTrCompKernel 2
#define kEnTrActKernSocket 1
#define kEnTrActKernSockRead 2
#define kEnTrActKernSockWrite 3
#define kEnTrActKernPoll 10
#define kEnTrActKernSelect 11
#define kEnTrActKernKQWait 12
#define kEnTrEvUnblocked 256
#define kEnTrFlagNonBlocking 0x1
#define kEnTrFlagNoWork 0x2

#if (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST)
#define ENTR_SHOULDTRACE kdebug_enable
#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)

#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 0
#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)