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