1/*
2 * Copyright (c) 2013-2016 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#ifndef __FIREHOSE_ACTIVITY__
22#define __FIREHOSE_ACTIVITY__
23
24#include <machine/cpu_capabilities.h>
25#include <mach/mach_time.h>
26#include <os/base.h>
27#include <stdbool.h>
28#if KERNEL
29#include <atm/atm_internal.h>
30#endif
31#if __has_include(<os/atomic_private.h>)
32#include <os/atomic_private.h>
33#else
34#include <os/internal/internal_shared.h>
35#endif
36#include "firehose_types_private.h"
37
38OS_ASSUME_NONNULL_BEGIN
39
40/*!
41 * @typedef firehose_tracepoint_id_u
42 *
43 * @abstract
44 * Broken down tracepoint identifier.
45 */
46typedef union {
47 struct {
48 firehose_tracepoint_namespace_t _namespace;
49 firehose_tracepoint_type_t _type;
50 firehose_tracepoint_flags_t _flags;
51 uint32_t _code;
52 } ftid;
53 firehose_tracepoint_id_t ftid_value;
54 os_atomic(firehose_tracepoint_id_t) ftid_atomic_value;
55} firehose_tracepoint_id_u;
56
57#define FIREHOSE_STAMP_SLOP (1ULL << 36) // ~1minute
58
59/*!
60 * @typedef firehose_trace_uuid_info_t
61 *
62 * @abstract
63 * Info needed by logd when kexts are loaded or unloaded
64 *
65 */
66typedef struct firehose_trace_uuid_info_s {
67 uuid_t ftui_uuid; /* uuid of binary */
68 uint64_t ftui_address; /* load address */
69 uint64_t ftui_size; /* load size */
70 char ftui_path[]; /* full path of binary - Unused in the kernel*/
71} *firehose_trace_uuid_info_t;
72
73/*!
74 * @typedef firehose_tracepoint_t
75 */
76typedef struct firehose_tracepoint_s {
77 firehose_tracepoint_id_u ft_id;
78 uint64_t ft_thread;
79 union {
80 struct {
81 uint64_t ft_timestamp_delta : 48;
82 uint64_t ft_length : 16;
83 };
84 uint64_t ft_stamp_and_length;
85 os_atomic(uint64_t) ft_atomic_stamp_and_length;
86 };
87 uint8_t ft_data[];
88} *firehose_tracepoint_t;
89
90#define FIREHOSE_TRACE_ID_MAKE(ns, type, flags, code) \
91 (((firehose_tracepoint_id_u){ .ftid = { \
92 ._namespace = ns, \
93 ._type = type, \
94 ._flags = flags, \
95 ._code = code, \
96 } }).ftid_value)
97
98#define FIREHOSE_TRACE_ID_SET_NS(tid, ns) \
99 ((tid).ftid._namespace = firehose_tracepoint_namespace_##ns)
100
101#define FIREHOSE_TRACE_ID_SET_TYPE(tid, ns, type) \
102 ((tid).ftid._type = _firehose_tracepoint_type_##ns##_##type)
103
104#define FIREHOSE_TRACE_ID_PC_STYLE(tid) \
105 ((tid).ftid._flags & _firehose_tracepoint_flags_pc_style_mask)
106
107#define FIREHOSE_TRACE_ID_SET_PC_STYLE(tid, flag) ({ \
108 firehose_tracepoint_id_u _tmp_tid = (tid); \
109 _tmp_tid.ftid._flags &= ~_firehose_tracepoint_flags_pc_style_mask; \
110 _tmp_tid.ftid._flags |= _firehose_tracepoint_flags_pc_style_##flag; \
111})
112
113#define FIREHOSE_TRACE_ID_HAS_FLAG(tid, ns, flag) \
114 ((tid).ftid._flags & _firehose_tracepoint_flags_##ns##_##flag)
115#define FIREHOSE_TRACE_ID_SET_FLAG(tid, ns, flag) \
116 ((void)((tid).ftid._flags |= _firehose_tracepoint_flags_##ns##_##flag))
117#define FIREHOSE_TRACE_ID_CLEAR_FLAG(tid, ns, flag) \
118 ((void)((tid).ftid._flags &= ~_firehose_tracepoint_flags_##ns##_##flag))
119
120#define FIREHOSE_TRACE_ID_SET_CODE(tid, code) \
121 ((tid).ftid._code = code)
122
123/*!
124 * @typedef firehose_loss_payload_s
125 *
126 * @abstract
127 * The payload for tracepoints in the loss namespace, generated by the firehose
128 * itself when unreliable tracepoints are lost.
129 */
130typedef struct firehose_loss_payload_s {
131 uint64_t start_stamp; /* may (rarely!) disagree with the tracepoint stamp */
132 uint64_t end_stamp;
133#define FIREHOSE_LOSS_COUNT_WIDTH 6 /* as many bits as can be spared */
134#define FIREHOSE_LOSS_COUNT_MAX ((1u << FIREHOSE_LOSS_COUNT_WIDTH) - 1)
135 uint32_t count;
136} firehose_loss_payload_s, *firehose_loss_payload_t;
137
138__BEGIN_DECLS
139
140#if __has_feature(address_sanitizer)
141__attribute__((no_sanitize("address")))
142#endif
143__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0)
144__TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
145OS_ALWAYS_INLINE
146static inline bool
147firehose_precise_timestamps_enabled(void)
148{
149#if KERNEL
150 return (atm_get_diagnostic_config() & 0x80) == 0;
151#else
152 return (*((volatile uint32_t *)_COMM_PAGE_ATM_DIAGNOSTIC_CONFIG) & 0x80) == 0;
153#endif
154}
155
156#if __has_feature(address_sanitizer)
157__attribute__((no_sanitize("address")))
158#endif
159__OSX_AVAILABLE(10.12) __IOS_AVAILABLE(10.0)
160__TVOS_AVAILABLE(10.0) __WATCHOS_AVAILABLE(3.0)
161OS_ALWAYS_INLINE
162static inline uint64_t
163firehose_tracepoint_time(firehose_activity_flags_t flags)
164{
165 if (firehose_precise_timestamps_enabled() ||
166 (flags & firehose_activity_flags_precise_timestamp)) {
167 return mach_continuous_time();
168 } else {
169 return mach_continuous_approximate_time();
170 }
171}
172
173#ifdef KERNEL
174bool
175os_log_encoded_metadata(firehose_tracepoint_id_u ftid, uint64_t stamp,
176 const void *pubdata, size_t publen);
177#endif
178__END_DECLS
179
180 OS_ASSUME_NONNULL_END
181
182#endif // __FIREHOSE_FIREHOSE__
183