13a73333fSSteven Rostedt (Google) /* SPDX-License-Identifier: GPL-2.0 */ 23a73333fSSteven Rostedt (Google) /* 33a73333fSSteven Rostedt (Google) * This is similar to the trace_events.h file, but is to only 43a73333fSSteven Rostedt (Google) * create custom trace events to be attached to existing tracepoints. 53a73333fSSteven Rostedt (Google) * Where as the TRACE_EVENT() macro (from trace_events.h) will create 63a73333fSSteven Rostedt (Google) * both the trace event and the tracepoint it will attach the event to, 73a73333fSSteven Rostedt (Google) * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing 83a73333fSSteven Rostedt (Google) * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will 93a73333fSSteven Rostedt (Google) * be placed in the "custom" system. 103a73333fSSteven Rostedt (Google) */ 113a73333fSSteven Rostedt (Google) 123a73333fSSteven Rostedt (Google) #include <linux/trace_events.h> 133a73333fSSteven Rostedt (Google) 143a73333fSSteven Rostedt (Google) /* All custom events are placed in the custom group */ 153a73333fSSteven Rostedt (Google) #undef TRACE_SYSTEM 163a73333fSSteven Rostedt (Google) #define TRACE_SYSTEM custom 173a73333fSSteven Rostedt (Google) 183a73333fSSteven Rostedt (Google) #ifndef TRACE_SYSTEM_VAR 193a73333fSSteven Rostedt (Google) #define TRACE_SYSTEM_VAR TRACE_SYSTEM 203a73333fSSteven Rostedt (Google) #endif 213a73333fSSteven Rostedt (Google) 223a73333fSSteven Rostedt (Google) /* The init stage creates the system string and enum mappings */ 233a73333fSSteven Rostedt (Google) 243a73333fSSteven Rostedt (Google) #include "stages/init.h" 253a73333fSSteven Rostedt (Google) 263a73333fSSteven Rostedt (Google) #undef TRACE_CUSTOM_EVENT 273a73333fSSteven Rostedt (Google) #define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \ 283a73333fSSteven Rostedt (Google) DECLARE_CUSTOM_EVENT_CLASS(name, \ 293a73333fSSteven Rostedt (Google) PARAMS(proto), \ 303a73333fSSteven Rostedt (Google) PARAMS(args), \ 313a73333fSSteven Rostedt (Google) PARAMS(tstruct), \ 323a73333fSSteven Rostedt (Google) PARAMS(assign), \ 333a73333fSSteven Rostedt (Google) PARAMS(print)); \ 343a73333fSSteven Rostedt (Google) DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args)); 353a73333fSSteven Rostedt (Google) 363a73333fSSteven Rostedt (Google) /* Stage 1 creates the structure of the recorded event layout */ 373a73333fSSteven Rostedt (Google) 38*84055411SSteven Rostedt (Google) #include "stages/stage1_struct_define.h" 393a73333fSSteven Rostedt (Google) 403a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS 413a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \ 423a73333fSSteven Rostedt (Google) struct trace_custom_event_raw_##name { \ 433a73333fSSteven Rostedt (Google) struct trace_entry ent; \ 443a73333fSSteven Rostedt (Google) tstruct \ 453a73333fSSteven Rostedt (Google) char __data[]; \ 463a73333fSSteven Rostedt (Google) }; \ 473a73333fSSteven Rostedt (Google) \ 483a73333fSSteven Rostedt (Google) static struct trace_event_class custom_event_class_##name; 493a73333fSSteven Rostedt (Google) 503a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT 513a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, name, proto, args) \ 523a73333fSSteven Rostedt (Google) static struct trace_event_call __used \ 533a73333fSSteven Rostedt (Google) __attribute__((__aligned__(4))) custom_event_##name 543a73333fSSteven Rostedt (Google) 553a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 563a73333fSSteven Rostedt (Google) 573a73333fSSteven Rostedt (Google) /* Stage 2 creates the custom class */ 583a73333fSSteven Rostedt (Google) 59*84055411SSteven Rostedt (Google) #include "stages/stage2_data_offsets.h" 603a73333fSSteven Rostedt (Google) 613a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS 623a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 633a73333fSSteven Rostedt (Google) struct trace_custom_event_data_offsets_##call { \ 643a73333fSSteven Rostedt (Google) tstruct; \ 653a73333fSSteven Rostedt (Google) }; 663a73333fSSteven Rostedt (Google) 673a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT 683a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, name, proto, args) 693a73333fSSteven Rostedt (Google) 703a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 713a73333fSSteven Rostedt (Google) 723a73333fSSteven Rostedt (Google) /* Stage 3 create the way to print the custom event */ 733a73333fSSteven Rostedt (Google) 74*84055411SSteven Rostedt (Google) #include "stages/stage3_trace_output.h" 753a73333fSSteven Rostedt (Google) 763a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS 773a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 783a73333fSSteven Rostedt (Google) static notrace enum print_line_t \ 793a73333fSSteven Rostedt (Google) trace_custom_raw_output_##call(struct trace_iterator *iter, int flags, \ 803a73333fSSteven Rostedt (Google) struct trace_event *trace_event) \ 813a73333fSSteven Rostedt (Google) { \ 823a73333fSSteven Rostedt (Google) struct trace_seq *s = &iter->seq; \ 833a73333fSSteven Rostedt (Google) struct trace_seq __maybe_unused *p = &iter->tmp_seq; \ 843a73333fSSteven Rostedt (Google) struct trace_custom_event_raw_##call *field; \ 853a73333fSSteven Rostedt (Google) int ret; \ 863a73333fSSteven Rostedt (Google) \ 873a73333fSSteven Rostedt (Google) field = (typeof(field))iter->ent; \ 883a73333fSSteven Rostedt (Google) \ 893a73333fSSteven Rostedt (Google) ret = trace_raw_output_prep(iter, trace_event); \ 903a73333fSSteven Rostedt (Google) if (ret != TRACE_TYPE_HANDLED) \ 913a73333fSSteven Rostedt (Google) return ret; \ 923a73333fSSteven Rostedt (Google) \ 933a73333fSSteven Rostedt (Google) trace_event_printf(iter, print); \ 943a73333fSSteven Rostedt (Google) \ 953a73333fSSteven Rostedt (Google) return trace_handle_return(s); \ 963a73333fSSteven Rostedt (Google) } \ 973a73333fSSteven Rostedt (Google) static struct trace_event_functions trace_custom_event_type_funcs_##call = { \ 983a73333fSSteven Rostedt (Google) .trace = trace_custom_raw_output_##call, \ 993a73333fSSteven Rostedt (Google) }; 1003a73333fSSteven Rostedt (Google) 1013a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 1023a73333fSSteven Rostedt (Google) 1033a73333fSSteven Rostedt (Google) /* Stage 4 creates the offset layout for the fields */ 1043a73333fSSteven Rostedt (Google) 105*84055411SSteven Rostedt (Google) #include "stages/stage4_event_fields.h" 1063a73333fSSteven Rostedt (Google) 1073a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS 1083a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print) \ 1093a73333fSSteven Rostedt (Google) static struct trace_event_fields trace_custom_event_fields_##call[] = { \ 1103a73333fSSteven Rostedt (Google) tstruct \ 1113a73333fSSteven Rostedt (Google) {} }; 1123a73333fSSteven Rostedt (Google) 1133a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 1143a73333fSSteven Rostedt (Google) 1153a73333fSSteven Rostedt (Google) /* Stage 5 creates the helper function for dynamic fields */ 1163a73333fSSteven Rostedt (Google) 117*84055411SSteven Rostedt (Google) #include "stages/stage5_get_offsets.h" 1183a73333fSSteven Rostedt (Google) 1193a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS 1203a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 1213a73333fSSteven Rostedt (Google) static inline notrace int trace_custom_event_get_offsets_##call( \ 1223a73333fSSteven Rostedt (Google) struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \ 1233a73333fSSteven Rostedt (Google) { \ 1243a73333fSSteven Rostedt (Google) int __data_size = 0; \ 1253a73333fSSteven Rostedt (Google) int __maybe_unused __item_length; \ 1263a73333fSSteven Rostedt (Google) struct trace_custom_event_raw_##call __maybe_unused *entry; \ 1273a73333fSSteven Rostedt (Google) \ 1283a73333fSSteven Rostedt (Google) tstruct; \ 1293a73333fSSteven Rostedt (Google) \ 1303a73333fSSteven Rostedt (Google) return __data_size; \ 1313a73333fSSteven Rostedt (Google) } 1323a73333fSSteven Rostedt (Google) 1333a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 1343a73333fSSteven Rostedt (Google) 1353a73333fSSteven Rostedt (Google) /* Stage 6 creates the probe function that records the event */ 1363a73333fSSteven Rostedt (Google) 137*84055411SSteven Rostedt (Google) #include "stages/stage6_event_callback.h" 1383a73333fSSteven Rostedt (Google) 1393a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS 1403a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 1413a73333fSSteven Rostedt (Google) \ 1423a73333fSSteven Rostedt (Google) static notrace void \ 1433a73333fSSteven Rostedt (Google) trace_custom_event_raw_event_##call(void *__data, proto) \ 1443a73333fSSteven Rostedt (Google) { \ 1453a73333fSSteven Rostedt (Google) struct trace_event_file *trace_file = __data; \ 1463a73333fSSteven Rostedt (Google) struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \ 1473a73333fSSteven Rostedt (Google) struct trace_event_buffer fbuffer; \ 1483a73333fSSteven Rostedt (Google) struct trace_custom_event_raw_##call *entry; \ 1493a73333fSSteven Rostedt (Google) int __data_size; \ 1503a73333fSSteven Rostedt (Google) \ 1513a73333fSSteven Rostedt (Google) if (trace_trigger_soft_disabled(trace_file)) \ 1523a73333fSSteven Rostedt (Google) return; \ 1533a73333fSSteven Rostedt (Google) \ 1543a73333fSSteven Rostedt (Google) __data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \ 1553a73333fSSteven Rostedt (Google) \ 1563a73333fSSteven Rostedt (Google) entry = trace_event_buffer_reserve(&fbuffer, trace_file, \ 1573a73333fSSteven Rostedt (Google) sizeof(*entry) + __data_size); \ 1583a73333fSSteven Rostedt (Google) \ 1593a73333fSSteven Rostedt (Google) if (!entry) \ 1603a73333fSSteven Rostedt (Google) return; \ 1613a73333fSSteven Rostedt (Google) \ 1623a73333fSSteven Rostedt (Google) tstruct \ 1633a73333fSSteven Rostedt (Google) \ 1643a73333fSSteven Rostedt (Google) { assign; } \ 1653a73333fSSteven Rostedt (Google) \ 1663a73333fSSteven Rostedt (Google) trace_event_buffer_commit(&fbuffer); \ 1673a73333fSSteven Rostedt (Google) } 1683a73333fSSteven Rostedt (Google) /* 1693a73333fSSteven Rostedt (Google) * The ftrace_test_custom_probe is compiled out, it is only here as a build time check 1703a73333fSSteven Rostedt (Google) * to make sure that if the tracepoint handling changes, the ftrace probe will 1713a73333fSSteven Rostedt (Google) * fail to compile unless it too is updated. 1723a73333fSSteven Rostedt (Google) */ 1733a73333fSSteven Rostedt (Google) 1743a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT 1753a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, call, proto, args) \ 1763a73333fSSteven Rostedt (Google) static inline void ftrace_test_custom_probe_##call(void) \ 1773a73333fSSteven Rostedt (Google) { \ 1783a73333fSSteven Rostedt (Google) check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \ 1793a73333fSSteven Rostedt (Google) } 1803a73333fSSteven Rostedt (Google) 1813a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 1823a73333fSSteven Rostedt (Google) 1833a73333fSSteven Rostedt (Google) /* Stage 7 creates the actual class and event structure for the custom event */ 1843a73333fSSteven Rostedt (Google) 185*84055411SSteven Rostedt (Google) #include "stages/stage7_class_define.h" 1863a73333fSSteven Rostedt (Google) 1873a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS 1883a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 1893a73333fSSteven Rostedt (Google) static char custom_print_fmt_##call[] = print; \ 1903a73333fSSteven Rostedt (Google) static struct trace_event_class __used __refdata custom_event_class_##call = { \ 1913a73333fSSteven Rostedt (Google) .system = TRACE_SYSTEM_STRING, \ 1923a73333fSSteven Rostedt (Google) .fields_array = trace_custom_event_fields_##call, \ 1933a73333fSSteven Rostedt (Google) .fields = LIST_HEAD_INIT(custom_event_class_##call.fields),\ 1943a73333fSSteven Rostedt (Google) .raw_init = trace_event_raw_init, \ 1953a73333fSSteven Rostedt (Google) .probe = trace_custom_event_raw_event_##call, \ 1963a73333fSSteven Rostedt (Google) .reg = trace_event_reg, \ 1973a73333fSSteven Rostedt (Google) }; 1983a73333fSSteven Rostedt (Google) 1993a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT 2003a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, call, proto, args) \ 2013a73333fSSteven Rostedt (Google) \ 2023a73333fSSteven Rostedt (Google) static struct trace_event_call __used custom_event_##call = { \ 2033a73333fSSteven Rostedt (Google) .name = #call, \ 2043a73333fSSteven Rostedt (Google) .class = &custom_event_class_##template, \ 2053a73333fSSteven Rostedt (Google) .event.funcs = &trace_custom_event_type_funcs_##template, \ 2063a73333fSSteven Rostedt (Google) .print_fmt = custom_print_fmt_##template, \ 2073a73333fSSteven Rostedt (Google) .flags = TRACE_EVENT_FL_CUSTOM, \ 2083a73333fSSteven Rostedt (Google) }; \ 2093a73333fSSteven Rostedt (Google) static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \ 2103a73333fSSteven Rostedt (Google) { \ 2113a73333fSSteven Rostedt (Google) if (tp->name && strcmp(tp->name, #call) == 0) { \ 2123a73333fSSteven Rostedt (Google) custom_event_##call.tp = tp; \ 2133a73333fSSteven Rostedt (Google) custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT; \ 2143a73333fSSteven Rostedt (Google) return 1; \ 2153a73333fSSteven Rostedt (Google) } \ 2163a73333fSSteven Rostedt (Google) return 0; \ 2173a73333fSSteven Rostedt (Google) } \ 2183a73333fSSteven Rostedt (Google) static struct trace_event_call __used \ 2193a73333fSSteven Rostedt (Google) __section("_ftrace_events") *__custom_event_##call = &custom_event_##call 2203a73333fSSteven Rostedt (Google) 2213a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 222