Commit | Line | Data |
---|---|---|
3a73333f SRG |
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 | ||
84055411 | 38 | #include "stages/stage1_struct_define.h" |
3a73333f SRG |
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 | ||
84055411 | 59 | #include "stages/stage2_data_offsets.h" |
3a73333f SRG |
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 | ||
84055411 | 74 | #include "stages/stage3_trace_output.h" |
3a73333f SRG |
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 | ||
84055411 | 105 | #include "stages/stage4_event_fields.h" |
3a73333f SRG |
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 | ||
84055411 | 117 | #include "stages/stage5_get_offsets.h" |
3a73333f SRG |
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 | ||
84055411 | 137 | #include "stages/stage6_event_callback.h" |
3a73333f SRG |
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 | ||
84055411 | 185 | #include "stages/stage7_class_define.h" |
3a73333f SRG |
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) |