1/*
2 * Copyright (c) 2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29/* socd_client_kern.h: machine-independent API for interfacing with soc diagnostics data pipeline, kernel mode specific logic */
30
31#ifndef _KERN_SOCD_CLIENT_KERN_H_
32#define _KERN_SOCD_CLIENT_KERN_H_
33
34#include <kern/socd_client.h>
35#include <kern/kern_types.h>
36#include <mach/vm_param.h>
37#include <sys/cdefs.h>
38
39__BEGIN_DECLS
40
41/*
42 * SOCD_TRACE
43 * Trace an event to debug kernel and hardware hangs. Traced on all build variants of kernel.
44 * x - kdebug debugid
45 * a, b, c, d - 64 bit data arguments
46 *
47 * Usage:
48 * SOCD_TRACE is an expensive operation and must not be used on performance critical paths.
49 * Each data argument must be wrapped with SOCD_ADDR or SOCD_VAL macro. To enforce this rule,
50 * SOCD_ is prepended to all data arguments passed to SOCD_TRACE.
51 * 1. Use ADDR when passing a kernel address. The macro verifies kernel address is slid, then it removes the slide.
52 * When kernel address is not slid, the macro returns 0.
53 * 2. Use VALUE when passing an argument that's not expected to be a kernel address. When the argument
54 * is a kernel address, the macro returns 0.
55 * 3. Use PACK_2X32 to pack two 32 bit values into one 64 bit argument. PACK_2X32 arguments must be wrapped with ADDR or VALUE macro as well.
56 * 4. Use PACK_LSB to overwrite the least significant bit of a 64 bit value. PACK_LSB arguments must be wrapped with ADDR or VALUE macro as well.
57 *
58 *
59 * Example:
60 * SOCD_TRACE(KDBG_EVENTID(DBG_DRIVERS, DBG_SOCDIAGS, SOCD_TRACE_EVENTID(SOCD_TRACE_CLASS_KERNEL, SOCD_TRACE_CODE_KERNEL_PANIC)),
61 * ADDR(caller_function_ptr), VALUE(panic_options))
62 */
63#define SOCD_TRACE(x, ...) SOCD_TRACE_(x, ## __VA_ARGS__, 4, 3, 2, 1, 0)
64#define SOCD_TRACE_(x, a, b, c, d, n, ...) SOCD_TRACE##n(x, a, b, c, d)
65#define SOCD_TRACE0(x, a, b, c, d) SOCD_TRACE_IMPL(x, 0, 0, 0, 0)
66#define SOCD_TRACE1(x, a, b, c, d) SOCD_TRACE_IMPL(x, SOCD_##a, 0, 0, 0)
67#define SOCD_TRACE2(x, a, b, c, d) SOCD_TRACE_IMPL(x, SOCD_##a, SOCD_##b, 0, 0)
68#define SOCD_TRACE3(x, a, b, c, d) SOCD_TRACE_IMPL(x, SOCD_##a, SOCD_##b, SOCD_##c, 0)
69#define SOCD_TRACE4(x, a, b, c, d) SOCD_TRACE_IMPL(x, SOCD_##a, SOCD_##b, SOCD_##c, SOCD_##d)
70
71#if defined(__arm64__)
72# define SOCD_TRACE_ENABLED 1
73#endif
74
75#if SOCD_TRACE_ENABLED
76#define SOCD_TRACE_IMPL(x, a, b, c, d) \
77do { \
78 socd_client_trace((x), (socd_client_trace_arg_t)(a), (socd_client_trace_arg_t)(b), \
79 (socd_client_trace_arg_t)(c), (socd_client_trace_arg_t)(d)); \
80} while (0)
81#else // SOCD_TRACE_ENABLED
82#define SOCD_TRACE_IMPL(x, a, b, c, d)
83#endif // !SOCD_TRACE_ENABLED
84
85#define SOCD_ADDR(_a) (VM_KERNEL_UNSLIDE((vm_offset_t)(_a)))
86#define SOCD_VALUE(_v) (VM_KERNEL_ADDRESS((vm_offset_t)(_v)) ? (socd_client_trace_arg_t)0 : (socd_client_trace_arg_t)(_v))
87#define SOCD_PACK_2X32(h, l) ((((uint64_t)(SOCD_##h) & 0xffffffff) << 32) | ((uint64_t)(SOCD_##l) & 0xffffffff))
88#define SOCD_PACK_LSB(h, lsb) ((((uint64_t)(SOCD_##h)) & 0xfffffffffffffffe) | ((uint64_t)(SOCD_##lsb) & 0x1))
89
90/* Test macros for proper functionality locally before nominating. */
91#if !defined(__arm64__)
92static_assert(SOCD_PACK_2X32(VALUE(0xffff1000), VALUE(0xffff1200)) == 0xffff1000ffff1200, "PACK_2X32 failed to return expected output.");
93static_assert(SOCD_PACK_LSB(VALUE(0xffff), VALUE(0x0)) == 0xfffe, "PACK_LSB failed to return expected output.");
94#endif // !defined(__arm64__)
95
96#define _SOCD_TRACE_XNU(c, x, ...) \
97 SOCD_TRACE(KDBG_EVENTID(DBG_DRIVERS, DBG_SOCDIAGS, SOCD_TRACE_EVENTID(SOCD_TRACE_CLASS_XNU, SOCD_TRACE_CODE_XNU_##c)) | (x), ## __VA_ARGS__)
98#define SOCD_TRACE_XNU(c, ...) _SOCD_TRACE_XNU(c, DBG_FUNC_NONE, ## __VA_ARGS__)
99#define SOCD_TRACE_XNU_START(c, ...) _SOCD_TRACE_XNU(c, DBG_FUNC_START, ## __VA_ARGS__)
100#define SOCD_TRACE_XNU_END(c, ...) _SOCD_TRACE_XNU(c, DBG_FUNC_END, ## __VA_ARGS__)
101
102extern void socd_client_trace(uint32_t debugid, socd_client_trace_arg_t arg1,
103 socd_client_trace_arg_t arg2, socd_client_trace_arg_t arg3, socd_client_trace_arg_t arg4);
104
105__END_DECLS
106
107#endif /* !defined(_KERN_SOCD_CLIENT_KERN_H_) */
108