6e492dba96bfcbf03039ba51b9becf08ae9c6c10
[linux-modified.git] / trace_custom_events.h
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) \
78 static notrace enum print_line_t                                        \
79 trace_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 }                                                                       \
97 static 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)     \
109 static 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) \
121 static 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                                                                         \
142 static notrace void                                                     \
143 trace_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)                \
176 static 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) \
189 static char custom_print_fmt_##call[] = print;                                  \
190 static 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                                                                         \
202 static 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 };                                                                      \
209 static 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 }                                                                       \
218 static struct trace_event_call __used                                   \
219 __section("_ftrace_events") *__custom_event_##call = &custom_event_##call
220
221 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)