123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- /* SPDX-License-Identifier: GPL-2.0 */
- /*
- * This is similar to the trace_events.h file, but is to only
- * create custom trace events to be attached to existing tracepoints.
- * Where as the TRACE_EVENT() macro (from trace_events.h) will create
- * both the trace event and the tracepoint it will attach the event to,
- * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing
- * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will
- * be placed in the "custom" system.
- */
- #include <linux/trace_events.h>
- /* All custom events are placed in the custom group */
- #undef TRACE_SYSTEM
- #define TRACE_SYSTEM custom
- #ifndef TRACE_SYSTEM_VAR
- #define TRACE_SYSTEM_VAR TRACE_SYSTEM
- #endif
- /* The init stage creates the system string and enum mappings */
- #include "stages/init.h"
- #undef TRACE_CUSTOM_EVENT
- #define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \
- DECLARE_CUSTOM_EVENT_CLASS(name, \
- PARAMS(proto), \
- PARAMS(args), \
- PARAMS(tstruct), \
- PARAMS(assign), \
- PARAMS(print)); \
- DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args));
- /* Stage 1 creates the structure of the recorded event layout */
- #include "stages/stage1_struct_define.h"
- #undef DECLARE_CUSTOM_EVENT_CLASS
- #define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
- struct trace_custom_event_raw_##name { \
- struct trace_entry ent; \
- tstruct \
- char __data[]; \
- }; \
- \
- static struct trace_event_class custom_event_class_##name;
- #undef DEFINE_CUSTOM_EVENT
- #define DEFINE_CUSTOM_EVENT(template, name, proto, args) \
- static struct trace_event_call __used \
- __attribute__((__aligned__(4))) custom_event_##name
- #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
- /* Stage 2 creates the custom class */
- #include "stages/stage2_data_offsets.h"
- #undef DECLARE_CUSTOM_EVENT_CLASS
- #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
- struct trace_custom_event_data_offsets_##call { \
- tstruct; \
- };
- #undef DEFINE_CUSTOM_EVENT
- #define DEFINE_CUSTOM_EVENT(template, name, proto, args)
- #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
- /* Stage 3 create the way to print the custom event */
- #include "stages/stage3_trace_output.h"
- #undef DECLARE_CUSTOM_EVENT_CLASS
- #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
- static notrace enum print_line_t \
- trace_custom_raw_output_##call(struct trace_iterator *iter, int flags, \
- struct trace_event *trace_event) \
- { \
- struct trace_seq *s = &iter->seq; \
- struct trace_seq __maybe_unused *p = &iter->tmp_seq; \
- struct trace_custom_event_raw_##call *field; \
- int ret; \
- \
- field = (typeof(field))iter->ent; \
- \
- ret = trace_raw_output_prep(iter, trace_event); \
- if (ret != TRACE_TYPE_HANDLED) \
- return ret; \
- \
- trace_event_printf(iter, print); \
- \
- return trace_handle_return(s); \
- } \
- static struct trace_event_functions trace_custom_event_type_funcs_##call = { \
- .trace = trace_custom_raw_output_##call, \
- };
- #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
- /* Stage 4 creates the offset layout for the fields */
- #include "stages/stage4_event_fields.h"
- #undef DECLARE_CUSTOM_EVENT_CLASS
- #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print) \
- static struct trace_event_fields trace_custom_event_fields_##call[] = { \
- tstruct \
- {} };
- #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
- /* Stage 5 creates the helper function for dynamic fields */
- #include "stages/stage5_get_offsets.h"
- #undef DECLARE_CUSTOM_EVENT_CLASS
- #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
- static inline notrace int trace_custom_event_get_offsets_##call( \
- struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \
- { \
- int __data_size = 0; \
- int __maybe_unused __item_length; \
- struct trace_custom_event_raw_##call __maybe_unused *entry; \
- \
- tstruct; \
- \
- return __data_size; \
- }
- #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
- /* Stage 6 creates the probe function that records the event */
- #include "stages/stage6_event_callback.h"
- #undef DECLARE_CUSTOM_EVENT_CLASS
- #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
- \
- static notrace void \
- trace_custom_event_raw_event_##call(void *__data, proto) \
- { \
- struct trace_event_file *trace_file = __data; \
- struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \
- struct trace_event_buffer fbuffer; \
- struct trace_custom_event_raw_##call *entry; \
- int __data_size; \
- \
- if (trace_trigger_soft_disabled(trace_file)) \
- return; \
- \
- __data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \
- \
- entry = trace_event_buffer_reserve(&fbuffer, trace_file, \
- sizeof(*entry) + __data_size); \
- \
- if (!entry) \
- return; \
- \
- tstruct \
- \
- { assign; } \
- \
- trace_event_buffer_commit(&fbuffer); \
- }
- /*
- * The ftrace_test_custom_probe is compiled out, it is only here as a build time check
- * to make sure that if the tracepoint handling changes, the ftrace probe will
- * fail to compile unless it too is updated.
- */
- #undef DEFINE_CUSTOM_EVENT
- #define DEFINE_CUSTOM_EVENT(template, call, proto, args) \
- static inline void ftrace_test_custom_probe_##call(void) \
- { \
- check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \
- }
- #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
- /* Stage 7 creates the actual class and event structure for the custom event */
- #include "stages/stage7_class_define.h"
- #undef DECLARE_CUSTOM_EVENT_CLASS
- #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
- static char custom_print_fmt_##call[] = print; \
- static struct trace_event_class __used __refdata custom_event_class_##call = { \
- .system = TRACE_SYSTEM_STRING, \
- .fields_array = trace_custom_event_fields_##call, \
- .fields = LIST_HEAD_INIT(custom_event_class_##call.fields),\
- .raw_init = trace_event_raw_init, \
- .probe = trace_custom_event_raw_event_##call, \
- .reg = trace_event_reg, \
- };
- #undef DEFINE_CUSTOM_EVENT
- #define DEFINE_CUSTOM_EVENT(template, call, proto, args) \
- \
- static struct trace_event_call __used custom_event_##call = { \
- .name = #call, \
- .class = &custom_event_class_##template, \
- .event.funcs = &trace_custom_event_type_funcs_##template, \
- .print_fmt = custom_print_fmt_##template, \
- .flags = TRACE_EVENT_FL_CUSTOM, \
- }; \
- static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \
- { \
- if (tp->name && strcmp(tp->name, #call) == 0) { \
- custom_event_##call.tp = tp; \
- custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT; \
- return 1; \
- } \
- return 0; \
- } \
- static struct trace_event_call __used \
- __section("_ftrace_events") *__custom_event_##call = &custom_event_##call
- #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
|