trace_custom_events.h (7228B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * This is similar to the trace_events.h file, but is to only 4 * create custom trace events to be attached to existing tracepoints. 5 * Where as the TRACE_EVENT() macro (from trace_events.h) will create 6 * both the trace event and the tracepoint it will attach the event to, 7 * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing 8 * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will 9 * be placed in the "custom" system. 10 */ 11 12#include <linux/trace_events.h> 13 14/* All custom events are placed in the custom group */ 15#undef TRACE_SYSTEM 16#define TRACE_SYSTEM custom 17 18#ifndef TRACE_SYSTEM_VAR 19#define TRACE_SYSTEM_VAR TRACE_SYSTEM 20#endif 21 22/* The init stage creates the system string and enum mappings */ 23 24#include "stages/init.h" 25 26#undef TRACE_CUSTOM_EVENT 27#define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \ 28 DECLARE_CUSTOM_EVENT_CLASS(name, \ 29 PARAMS(proto), \ 30 PARAMS(args), \ 31 PARAMS(tstruct), \ 32 PARAMS(assign), \ 33 PARAMS(print)); \ 34 DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args)); 35 36/* Stage 1 creates the structure of the recorded event layout */ 37 38#include "stages/stage1_struct_define.h" 39 40#undef DECLARE_CUSTOM_EVENT_CLASS 41#define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \ 42 struct trace_custom_event_raw_##name { \ 43 struct trace_entry ent; \ 44 tstruct \ 45 char __data[]; \ 46 }; \ 47 \ 48 static struct trace_event_class custom_event_class_##name; 49 50#undef DEFINE_CUSTOM_EVENT 51#define DEFINE_CUSTOM_EVENT(template, name, proto, args) \ 52 static struct trace_event_call __used \ 53 __attribute__((__aligned__(4))) custom_event_##name 54 55#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 56 57/* Stage 2 creates the custom class */ 58 59#include "stages/stage2_data_offsets.h" 60 61#undef DECLARE_CUSTOM_EVENT_CLASS 62#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 63 struct trace_custom_event_data_offsets_##call { \ 64 tstruct; \ 65 }; 66 67#undef DEFINE_CUSTOM_EVENT 68#define DEFINE_CUSTOM_EVENT(template, name, proto, args) 69 70#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 71 72/* Stage 3 create the way to print the custom event */ 73 74#include "stages/stage3_trace_output.h" 75 76#undef DECLARE_CUSTOM_EVENT_CLASS 77#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 78static notrace enum print_line_t \ 79trace_custom_raw_output_##call(struct trace_iterator *iter, int flags, \ 80 struct trace_event *trace_event) \ 81{ \ 82 struct trace_seq *s = &iter->seq; \ 83 struct trace_seq __maybe_unused *p = &iter->tmp_seq; \ 84 struct trace_custom_event_raw_##call *field; \ 85 int ret; \ 86 \ 87 field = (typeof(field))iter->ent; \ 88 \ 89 ret = trace_raw_output_prep(iter, trace_event); \ 90 if (ret != TRACE_TYPE_HANDLED) \ 91 return ret; \ 92 \ 93 trace_event_printf(iter, print); \ 94 \ 95 return trace_handle_return(s); \ 96} \ 97static struct trace_event_functions trace_custom_event_type_funcs_##call = { \ 98 .trace = trace_custom_raw_output_##call, \ 99}; 100 101#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 102 103/* Stage 4 creates the offset layout for the fields */ 104 105#include "stages/stage4_event_fields.h" 106 107#undef DECLARE_CUSTOM_EVENT_CLASS 108#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print) \ 109static struct trace_event_fields trace_custom_event_fields_##call[] = { \ 110 tstruct \ 111 {} }; 112 113#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 114 115/* Stage 5 creates the helper function for dynamic fields */ 116 117#include "stages/stage5_get_offsets.h" 118 119#undef DECLARE_CUSTOM_EVENT_CLASS 120#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 121static inline notrace int trace_custom_event_get_offsets_##call( \ 122 struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \ 123{ \ 124 int __data_size = 0; \ 125 int __maybe_unused __item_length; \ 126 struct trace_custom_event_raw_##call __maybe_unused *entry; \ 127 \ 128 tstruct; \ 129 \ 130 return __data_size; \ 131} 132 133#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 134 135/* Stage 6 creates the probe function that records the event */ 136 137#include "stages/stage6_event_callback.h" 138 139#undef DECLARE_CUSTOM_EVENT_CLASS 140#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 141 \ 142static notrace void \ 143trace_custom_event_raw_event_##call(void *__data, proto) \ 144{ \ 145 struct trace_event_file *trace_file = __data; \ 146 struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \ 147 struct trace_event_buffer fbuffer; \ 148 struct trace_custom_event_raw_##call *entry; \ 149 int __data_size; \ 150 \ 151 if (trace_trigger_soft_disabled(trace_file)) \ 152 return; \ 153 \ 154 __data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \ 155 \ 156 entry = trace_event_buffer_reserve(&fbuffer, trace_file, \ 157 sizeof(*entry) + __data_size); \ 158 \ 159 if (!entry) \ 160 return; \ 161 \ 162 tstruct \ 163 \ 164 { assign; } \ 165 \ 166 trace_event_buffer_commit(&fbuffer); \ 167} 168/* 169 * The ftrace_test_custom_probe is compiled out, it is only here as a build time check 170 * to make sure that if the tracepoint handling changes, the ftrace probe will 171 * fail to compile unless it too is updated. 172 */ 173 174#undef DEFINE_CUSTOM_EVENT 175#define DEFINE_CUSTOM_EVENT(template, call, proto, args) \ 176static inline void ftrace_test_custom_probe_##call(void) \ 177{ \ 178 check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \ 179} 180 181#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 182 183/* Stage 7 creates the actual class and event structure for the custom event */ 184 185#include "stages/stage7_class_define.h" 186 187#undef DECLARE_CUSTOM_EVENT_CLASS 188#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 189static char custom_print_fmt_##call[] = print; \ 190static struct trace_event_class __used __refdata custom_event_class_##call = { \ 191 .system = TRACE_SYSTEM_STRING, \ 192 .fields_array = trace_custom_event_fields_##call, \ 193 .fields = LIST_HEAD_INIT(custom_event_class_##call.fields),\ 194 .raw_init = trace_event_raw_init, \ 195 .probe = trace_custom_event_raw_event_##call, \ 196 .reg = trace_event_reg, \ 197}; 198 199#undef DEFINE_CUSTOM_EVENT 200#define DEFINE_CUSTOM_EVENT(template, call, proto, args) \ 201 \ 202static struct trace_event_call __used custom_event_##call = { \ 203 .name = #call, \ 204 .class = &custom_event_class_##template, \ 205 .event.funcs = &trace_custom_event_type_funcs_##template, \ 206 .print_fmt = custom_print_fmt_##template, \ 207 .flags = TRACE_EVENT_FL_CUSTOM, \ 208}; \ 209static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \ 210{ \ 211 if (tp->name && strcmp(tp->name, #call) == 0) { \ 212 custom_event_##call.tp = tp; \ 213 custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT; \ 214 return 1; \ 215 } \ 216 return 0; \ 217} \ 218static struct trace_event_call __used \ 219__section("_ftrace_events") *__custom_event_##call = &custom_event_##call 220 221#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)