Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * This is similar to the trace_events.h file, but is to only
0004  * create custom trace events to be attached to existing tracepoints.
0005  * Where as the TRACE_EVENT() macro (from trace_events.h) will create
0006  * both the trace event and the tracepoint it will attach the event to,
0007  * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing
0008  * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will
0009  * be placed in the "custom" system.
0010  */
0011 
0012 #include <linux/trace_events.h>
0013 
0014 /* All custom events are placed in the custom group */
0015 #undef TRACE_SYSTEM
0016 #define TRACE_SYSTEM custom
0017 
0018 #ifndef TRACE_SYSTEM_VAR
0019 #define TRACE_SYSTEM_VAR TRACE_SYSTEM
0020 #endif
0021 
0022 /* The init stage creates the system string and enum mappings */
0023 
0024 #include "stages/init.h"
0025 
0026 #undef TRACE_CUSTOM_EVENT
0027 #define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \
0028     DECLARE_CUSTOM_EVENT_CLASS(name,                  \
0029                  PARAMS(proto),            \
0030                  PARAMS(args),             \
0031                  PARAMS(tstruct),              \
0032                  PARAMS(assign),               \
0033                  PARAMS(print));               \
0034     DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args));
0035 
0036 /* Stage 1 creates the structure of the recorded event layout */
0037 
0038 #include "stages/stage1_struct_define.h"
0039 
0040 #undef DECLARE_CUSTOM_EVENT_CLASS
0041 #define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
0042     struct trace_custom_event_raw_##name {              \
0043         struct trace_entry  ent;                \
0044         tstruct                         \
0045         char            __data[];           \
0046     };                              \
0047                                     \
0048     static struct trace_event_class custom_event_class_##name;
0049 
0050 #undef DEFINE_CUSTOM_EVENT
0051 #define DEFINE_CUSTOM_EVENT(template, name, proto, args)    \
0052     static struct trace_event_call  __used          \
0053     __attribute__((__aligned__(4))) custom_event_##name
0054 
0055 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
0056 
0057 /* Stage 2 creates the custom class */
0058 
0059 #include "stages/stage2_data_offsets.h"
0060 
0061 #undef DECLARE_CUSTOM_EVENT_CLASS
0062 #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print)   \
0063     struct trace_custom_event_data_offsets_##call {         \
0064         tstruct;                        \
0065     };
0066 
0067 #undef DEFINE_CUSTOM_EVENT
0068 #define DEFINE_CUSTOM_EVENT(template, name, proto, args)
0069 
0070 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
0071 
0072 /* Stage 3 create the way to print the custom event */
0073 
0074 #include "stages/stage3_trace_output.h"
0075 
0076 #undef DECLARE_CUSTOM_EVENT_CLASS
0077 #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
0078 static notrace enum print_line_t                    \
0079 trace_custom_raw_output_##call(struct trace_iterator *iter, int flags,  \
0080             struct trace_event *trace_event)        \
0081 {                                   \
0082     struct trace_seq *s = &iter->seq;               \
0083     struct trace_seq __maybe_unused *p = &iter->tmp_seq;        \
0084     struct trace_custom_event_raw_##call *field;            \
0085     int ret;                            \
0086                                     \
0087     field = (typeof(field))iter->ent;               \
0088                                     \
0089     ret = trace_raw_output_prep(iter, trace_event);         \
0090     if (ret != TRACE_TYPE_HANDLED)                  \
0091         return ret;                     \
0092                                     \
0093     trace_event_printf(iter, print);                \
0094                                     \
0095     return trace_handle_return(s);                  \
0096 }                                   \
0097 static struct trace_event_functions trace_custom_event_type_funcs_##call = { \
0098     .trace          = trace_custom_raw_output_##call,   \
0099 };
0100 
0101 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
0102 
0103 /* Stage 4 creates the offset layout for the fields */
0104 
0105 #include "stages/stage4_event_fields.h"
0106 
0107 #undef DECLARE_CUSTOM_EVENT_CLASS
0108 #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print) \
0109 static struct trace_event_fields trace_custom_event_fields_##call[] = { \
0110     tstruct                             \
0111     {} };
0112 
0113 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
0114 
0115 /* Stage 5 creates the helper function for dynamic fields */
0116 
0117 #include "stages/stage5_get_offsets.h"
0118 
0119 #undef DECLARE_CUSTOM_EVENT_CLASS
0120 #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
0121 static inline notrace int trace_custom_event_get_offsets_##call(    \
0122     struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \
0123 {                                   \
0124     int __data_size = 0;                        \
0125     int __maybe_unused __item_length;               \
0126     struct trace_custom_event_raw_##call __maybe_unused *entry; \
0127                                     \
0128     tstruct;                            \
0129                                     \
0130     return __data_size;                     \
0131 }
0132 
0133 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
0134 
0135 /* Stage 6 creates the probe function that records the event */
0136 
0137 #include "stages/stage6_event_callback.h"
0138 
0139 #undef DECLARE_CUSTOM_EVENT_CLASS
0140 #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
0141                                     \
0142 static notrace void                         \
0143 trace_custom_event_raw_event_##call(void *__data, proto)        \
0144 {                                   \
0145     struct trace_event_file *trace_file = __data;           \
0146     struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \
0147     struct trace_event_buffer fbuffer;              \
0148     struct trace_custom_event_raw_##call *entry;            \
0149     int __data_size;                        \
0150                                     \
0151     if (trace_trigger_soft_disabled(trace_file))            \
0152         return;                         \
0153                                     \
0154     __data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \
0155                                     \
0156     entry = trace_event_buffer_reserve(&fbuffer, trace_file,    \
0157                  sizeof(*entry) + __data_size);     \
0158                                     \
0159     if (!entry)                         \
0160         return;                         \
0161                                     \
0162     tstruct                             \
0163                                     \
0164     { assign; }                         \
0165                                     \
0166     trace_event_buffer_commit(&fbuffer);                \
0167 }
0168 /*
0169  * The ftrace_test_custom_probe is compiled out, it is only here as a build time check
0170  * to make sure that if the tracepoint handling changes, the ftrace probe will
0171  * fail to compile unless it too is updated.
0172  */
0173 
0174 #undef DEFINE_CUSTOM_EVENT
0175 #define DEFINE_CUSTOM_EVENT(template, call, proto, args)        \
0176 static inline void ftrace_test_custom_probe_##call(void)        \
0177 {                                   \
0178     check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \
0179 }
0180 
0181 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
0182 
0183 /* Stage 7 creates the actual class and event structure for the custom event */
0184 
0185 #include "stages/stage7_class_define.h"
0186 
0187 #undef DECLARE_CUSTOM_EVENT_CLASS
0188 #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
0189 static char custom_print_fmt_##call[] = print;                  \
0190 static struct trace_event_class __used __refdata custom_event_class_##call = { \
0191     .system         = TRACE_SYSTEM_STRING,          \
0192     .fields_array       = trace_custom_event_fields_##call,     \
0193     .fields         = LIST_HEAD_INIT(custom_event_class_##call.fields),\
0194     .raw_init       = trace_event_raw_init,         \
0195     .probe          = trace_custom_event_raw_event_##call,  \
0196     .reg            = trace_event_reg,          \
0197 };
0198 
0199 #undef DEFINE_CUSTOM_EVENT
0200 #define DEFINE_CUSTOM_EVENT(template, call, proto, args)        \
0201                                     \
0202 static struct trace_event_call __used custom_event_##call = {       \
0203     .name           = #call,                \
0204     .class          = &custom_event_class_##template,   \
0205     .event.funcs        = &trace_custom_event_type_funcs_##template, \
0206     .print_fmt      = custom_print_fmt_##template,      \
0207     .flags          = TRACE_EVENT_FL_CUSTOM,        \
0208 };                                  \
0209 static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \
0210 {                                   \
0211     if (tp->name && strcmp(tp->name, #call) == 0) {         \
0212         custom_event_##call.tp = tp;                \
0213         custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT;  \
0214         return 1;                       \
0215     }                               \
0216     return 0;                           \
0217 }                                   \
0218 static struct trace_event_call __used                   \
0219 __section("_ftrace_events") *__custom_event_##call = &custom_event_##call
0220 
0221 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)