| 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 | |
| 38 | OS_ASSUME_NONNULL_BEGIN |
| 39 | |
| 40 | /*! |
| 41 | * @typedef firehose_tracepoint_id_u |
| 42 | * |
| 43 | * @abstract |
| 44 | * Broken down tracepoint identifier. |
| 45 | */ |
| 46 | typedef 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 | */ |
| 66 | typedef 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 | */ |
| 76 | typedef 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 | */ |
| 130 | typedef 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) |
| 145 | OS_ALWAYS_INLINE |
| 146 | static inline bool |
| 147 | firehose_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) |
| 161 | OS_ALWAYS_INLINE |
| 162 | static inline uint64_t |
| 163 | firehose_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 |
| 174 | bool |
| 175 | os_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 | |