blob: 5a7d18c4363497022e2b28cc115620ccf58fab0a [file] [log] [blame]
Steven Rostedtf42c85e2009-04-13 12:25:37 -04001/*
2 * Stage 1 of the trace events.
3 *
4 * Override the macros in <trace/trace_events.h> to include the following:
5 *
6 * struct ftrace_raw_<call> {
7 * struct trace_entry ent;
8 * <type> <item>;
9 * <type2> <item2>[<len>];
10 * [...]
11 * };
12 *
13 * The <type> <item> is created by the __field(type, item) macro or
14 * the __array(type2, item2, len) macro.
15 * We simply do "type item;", and that will create the fields
16 * in the structure.
17 */
18
19#include <linux/ftrace_event.h>
20
21#undef TRACE_FORMAT
22#define TRACE_FORMAT(call, proto, args, fmt)
23
24#undef __array
25#define __array(type, item, len) type item[len];
26
27#undef __field
28#define __field(type, item) type item;
29
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +020030#undef __string
31#define __string(item, src) int __str_loc_##item;
32
Steven Rostedtf42c85e2009-04-13 12:25:37 -040033#undef TP_STRUCT__entry
34#define TP_STRUCT__entry(args...) args
35
36#undef TRACE_EVENT
37#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \
38 struct ftrace_raw_##name { \
39 struct trace_entry ent; \
40 tstruct \
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +020041 char __str_data[0]; \
Steven Rostedtf42c85e2009-04-13 12:25:37 -040042 }; \
43 static struct ftrace_event_call event_##name
44
45#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
46
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +020047
Steven Rostedtf42c85e2009-04-13 12:25:37 -040048/*
49 * Stage 2 of the trace events.
50 *
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +020051 * Include the following:
52 *
53 * struct ftrace_str_offsets_<call> {
54 * int <str1>;
55 * int <str2>;
56 * [...]
57 * };
58 *
59 * The __string() macro will create each int <str>, this is to
60 * keep the offset of each string from the beggining of the event
61 * once we perform the strlen() of the src strings.
62 *
63 */
64
65#undef TRACE_FORMAT
66#define TRACE_FORMAT(call, proto, args, fmt)
67
68#undef __array
69#define __array(type, item, len)
70
71#undef __field
72#define __field(type, item);
73
74#undef __string
75#define __string(item, src) int item;
76
77#undef TRACE_EVENT
78#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
79 struct ftrace_str_offsets_##call { \
80 tstruct; \
81 };
82
83#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
84
85/*
86 * Stage 3 of the trace events.
87 *
Steven Rostedtf42c85e2009-04-13 12:25:37 -040088 * Override the macros in <trace/trace_events.h> to include the following:
89 *
90 * enum print_line_t
91 * ftrace_raw_output_<call>(struct trace_iterator *iter, int flags)
92 * {
93 * struct trace_seq *s = &iter->seq;
94 * struct ftrace_raw_<call> *field; <-- defined in stage 1
95 * struct trace_entry *entry;
96 * int ret;
97 *
98 * entry = iter->ent;
99 *
100 * if (entry->type != event_<call>.id) {
101 * WARN_ON_ONCE(1);
102 * return TRACE_TYPE_UNHANDLED;
103 * }
104 *
105 * field = (typeof(field))entry;
106 *
107 * ret = trace_seq_printf(s, <TP_printk> "\n");
108 * if (!ret)
109 * return TRACE_TYPE_PARTIAL_LINE;
110 *
111 * return TRACE_TYPE_HANDLED;
112 * }
113 *
114 * This is the method used to print the raw event to the trace
115 * output format. Note, this is not needed if the data is read
116 * in binary.
117 */
118
119#undef __entry
120#define __entry field
121
122#undef TP_printk
123#define TP_printk(fmt, args...) fmt "\n", args
124
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200125#undef __get_str
126#define __get_str(field) (char *)__entry + __entry->__str_loc_##field
127
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400128#undef TRACE_EVENT
129#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
130enum print_line_t \
131ftrace_raw_output_##call(struct trace_iterator *iter, int flags) \
132{ \
133 struct trace_seq *s = &iter->seq; \
134 struct ftrace_raw_##call *field; \
135 struct trace_entry *entry; \
136 int ret; \
137 \
138 entry = iter->ent; \
139 \
140 if (entry->type != event_##call.id) { \
141 WARN_ON_ONCE(1); \
142 return TRACE_TYPE_UNHANDLED; \
143 } \
144 \
145 field = (typeof(field))entry; \
146 \
147 ret = trace_seq_printf(s, #call ": " print); \
148 if (!ret) \
149 return TRACE_TYPE_PARTIAL_LINE; \
150 \
151 return TRACE_TYPE_HANDLED; \
152}
153
154#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
155
156/*
157 * Setup the showing format of trace point.
158 *
159 * int
160 * ftrace_format_##call(struct trace_seq *s)
161 * {
162 * struct ftrace_raw_##call field;
163 * int ret;
164 *
165 * ret = trace_seq_printf(s, #type " " #item ";"
166 * " offset:%u; size:%u;\n",
167 * offsetof(struct ftrace_raw_##call, item),
168 * sizeof(field.type));
169 *
170 * }
171 */
172
173#undef TP_STRUCT__entry
174#define TP_STRUCT__entry(args...) args
175
176#undef __field
177#define __field(type, item) \
178 ret = trace_seq_printf(s, "\tfield:" #type " " #item ";\t" \
179 "offset:%u;\tsize:%u;\n", \
180 (unsigned int)offsetof(typeof(field), item), \
181 (unsigned int)sizeof(field.item)); \
182 if (!ret) \
183 return 0;
184
185#undef __array
186#define __array(type, item, len) \
187 ret = trace_seq_printf(s, "\tfield:" #type " " #item "[" #len "];\t" \
188 "offset:%u;\tsize:%u;\n", \
189 (unsigned int)offsetof(typeof(field), item), \
190 (unsigned int)sizeof(field.item)); \
191 if (!ret) \
192 return 0;
193
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200194#undef __string
195#define __string(item, src) \
196 ret = trace_seq_printf(s, "\tfield: __str_loc " #item ";\t" \
197 "offset:%u;tsize:%u;\n", \
198 (unsigned int)offsetof(typeof(field), \
199 __str_loc_##item), \
200 (unsigned int)sizeof(field.__str_loc_##item)); \
201 if (!ret) \
202 return 0;
203
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400204#undef __entry
205#define __entry REC
206
207#undef TP_printk
208#define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args)
209
210#undef TP_fast_assign
211#define TP_fast_assign(args...) args
212
213#undef TRACE_EVENT
214#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
215static int \
216ftrace_format_##call(struct trace_seq *s) \
217{ \
Jeremy Fitzhardinge76aa8112009-04-16 23:35:39 -0700218 struct ftrace_raw_##call field __attribute__((unused)); \
219 int ret = 0; \
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400220 \
221 tstruct; \
222 \
223 trace_seq_printf(s, "\nprint fmt: " print); \
224 \
225 return ret; \
226}
227
228#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
229
230#undef __field
231#define __field(type, item) \
232 ret = trace_define_field(event_call, #type, #item, \
233 offsetof(typeof(field), item), \
234 sizeof(field.item)); \
235 if (ret) \
236 return ret;
237
238#undef __array
239#define __array(type, item, len) \
240 BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
241 ret = trace_define_field(event_call, #type "[" #len "]", #item, \
242 offsetof(typeof(field), item), \
243 sizeof(field.item)); \
244 if (ret) \
245 return ret;
246
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200247#undef __string
248#define __string(item, src) \
249 ret = trace_define_field(event_call, "__str_loc", #item, \
250 offsetof(typeof(field), __str_loc_##item), \
251 sizeof(field.__str_loc_##item));
252
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400253#undef TRACE_EVENT
254#define TRACE_EVENT(call, proto, args, tstruct, func, print) \
255int \
256ftrace_define_fields_##call(void) \
257{ \
258 struct ftrace_raw_##call field; \
259 struct ftrace_event_call *event_call = &event_##call; \
260 int ret; \
261 \
Li Zefan7a4f4532009-04-22 16:53:34 +0800262 __common_field(int, type); \
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400263 __common_field(unsigned char, flags); \
264 __common_field(unsigned char, preempt_count); \
265 __common_field(int, pid); \
266 __common_field(int, tgid); \
267 \
268 tstruct; \
269 \
270 return ret; \
271}
272
273#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
274
275/*
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200276 * Stage 4 of the trace events.
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400277 *
278 * Override the macros in <trace/trace_events.h> to include the following:
279 *
280 * static void ftrace_event_<call>(proto)
281 * {
282 * event_trace_printk(_RET_IP_, "<call>: " <fmt>);
283 * }
284 *
285 * static int ftrace_reg_event_<call>(void)
286 * {
287 * int ret;
288 *
289 * ret = register_trace_<call>(ftrace_event_<call>);
290 * if (!ret)
291 * pr_info("event trace: Could not activate trace point "
292 * "probe to <call>");
293 * return ret;
294 * }
295 *
296 * static void ftrace_unreg_event_<call>(void)
297 * {
298 * unregister_trace_<call>(ftrace_event_<call>);
299 * }
300 *
301 * For those macros defined with TRACE_FORMAT:
302 *
303 * static struct ftrace_event_call __used
304 * __attribute__((__aligned__(4)))
305 * __attribute__((section("_ftrace_events"))) event_<call> = {
306 * .name = "<call>",
307 * .regfunc = ftrace_reg_event_<call>,
308 * .unregfunc = ftrace_unreg_event_<call>,
309 * }
310 *
311 *
312 * For those macros defined with TRACE_EVENT:
313 *
314 * static struct ftrace_event_call event_<call>;
315 *
316 * static void ftrace_raw_event_<call>(proto)
317 * {
318 * struct ring_buffer_event *event;
319 * struct ftrace_raw_<call> *entry; <-- defined in stage 1
320 * unsigned long irq_flags;
321 * int pc;
322 *
323 * local_save_flags(irq_flags);
324 * pc = preempt_count();
325 *
326 * event = trace_current_buffer_lock_reserve(event_<call>.id,
327 * sizeof(struct ftrace_raw_<call>),
328 * irq_flags, pc);
329 * if (!event)
330 * return;
331 * entry = ring_buffer_event_data(event);
332 *
333 * <assign>; <-- Here we assign the entries by the __field and
334 * __array macros.
335 *
336 * trace_current_buffer_unlock_commit(event, irq_flags, pc);
337 * }
338 *
339 * static int ftrace_raw_reg_event_<call>(void)
340 * {
341 * int ret;
342 *
343 * ret = register_trace_<call>(ftrace_raw_event_<call>);
344 * if (!ret)
345 * pr_info("event trace: Could not activate trace point "
346 * "probe to <call>");
347 * return ret;
348 * }
349 *
350 * static void ftrace_unreg_event_<call>(void)
351 * {
352 * unregister_trace_<call>(ftrace_raw_event_<call>);
353 * }
354 *
355 * static struct trace_event ftrace_event_type_<call> = {
356 * .trace = ftrace_raw_output_<call>, <-- stage 2
357 * };
358 *
359 * static int ftrace_raw_init_event_<call>(void)
360 * {
361 * int id;
362 *
363 * id = register_ftrace_event(&ftrace_event_type_<call>);
364 * if (!id)
365 * return -ENODEV;
366 * event_<call>.id = id;
367 * return 0;
368 * }
369 *
370 * static struct ftrace_event_call __used
371 * __attribute__((__aligned__(4)))
372 * __attribute__((section("_ftrace_events"))) event_<call> = {
373 * .name = "<call>",
374 * .system = "<system>",
375 * .raw_init = ftrace_raw_init_event_<call>,
376 * .regfunc = ftrace_reg_event_<call>,
377 * .unregfunc = ftrace_unreg_event_<call>,
378 * .show_format = ftrace_format_<call>,
379 * }
380 *
381 */
382
383#undef TP_FMT
384#define TP_FMT(fmt, args...) fmt "\n", ##args
385
386#ifdef CONFIG_EVENT_PROFILE
387#define _TRACE_PROFILE(call, proto, args) \
388static void ftrace_profile_##call(proto) \
389{ \
390 extern void perf_tpcounter_event(int); \
391 perf_tpcounter_event(event_##call.id); \
392} \
393 \
394static int ftrace_profile_enable_##call(struct ftrace_event_call *call) \
395{ \
396 int ret = 0; \
397 \
398 if (!atomic_inc_return(&call->profile_count)) \
399 ret = register_trace_##call(ftrace_profile_##call); \
400 \
401 return ret; \
402} \
403 \
404static void ftrace_profile_disable_##call(struct ftrace_event_call *call) \
405{ \
406 if (atomic_add_negative(-1, &call->profile_count)) \
407 unregister_trace_##call(ftrace_profile_##call); \
408}
409
410#define _TRACE_PROFILE_INIT(call) \
411 .profile_count = ATOMIC_INIT(-1), \
412 .profile_enable = ftrace_profile_enable_##call, \
413 .profile_disable = ftrace_profile_disable_##call,
414
415#else
416#define _TRACE_PROFILE(call, proto, args)
417#define _TRACE_PROFILE_INIT(call)
418#endif
419
420#define _TRACE_FORMAT(call, proto, args, fmt) \
421static void ftrace_event_##call(proto) \
422{ \
423 event_trace_printk(_RET_IP_, #call ": " fmt); \
424} \
425 \
426static int ftrace_reg_event_##call(void) \
427{ \
428 int ret; \
429 \
430 ret = register_trace_##call(ftrace_event_##call); \
431 if (ret) \
432 pr_info("event trace: Could not activate trace point " \
433 "probe to " #call "\n"); \
434 return ret; \
435} \
436 \
437static void ftrace_unreg_event_##call(void) \
438{ \
439 unregister_trace_##call(ftrace_event_##call); \
440} \
441 \
442static struct ftrace_event_call event_##call; \
443 \
444static int ftrace_init_event_##call(void) \
445{ \
446 int id; \
447 \
448 id = register_ftrace_event(NULL); \
449 if (!id) \
450 return -ENODEV; \
451 event_##call.id = id; \
452 return 0; \
453}
454
455#undef TRACE_FORMAT
456#define TRACE_FORMAT(call, proto, args, fmt) \
457_TRACE_FORMAT(call, PARAMS(proto), PARAMS(args), PARAMS(fmt)) \
458_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \
459static struct ftrace_event_call __used \
460__attribute__((__aligned__(4))) \
461__attribute__((section("_ftrace_events"))) event_##call = { \
462 .name = #call, \
463 .system = __stringify(TRACE_SYSTEM), \
464 .raw_init = ftrace_init_event_##call, \
465 .regfunc = ftrace_reg_event_##call, \
466 .unregfunc = ftrace_unreg_event_##call, \
467 _TRACE_PROFILE_INIT(call) \
468}
469
470#undef __entry
471#define __entry entry
472
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200473#undef __field
474#define __field(type, item)
475
476#undef __array
477#define __array(type, item, len)
478
479#undef __string
480#define __string(item, src) \
481 __str_offsets.item = __str_size + \
482 offsetof(typeof(*entry), __str_data); \
483 __str_size += strlen(src) + 1;
484
485#undef __assign_str
486#define __assign_str(dst, src) \
487 __entry->__str_loc_##dst = __str_offsets.dst; \
488 strcpy(__get_str(dst), src);
489
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400490#undef TRACE_EVENT
491#define TRACE_EVENT(call, proto, args, tstruct, assign, print) \
492_TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \
493 \
494static struct ftrace_event_call event_##call; \
495 \
496static void ftrace_raw_event_##call(proto) \
497{ \
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200498 struct ftrace_str_offsets_##call __maybe_unused __str_offsets; \
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400499 struct ftrace_event_call *call = &event_##call; \
500 struct ring_buffer_event *event; \
501 struct ftrace_raw_##call *entry; \
502 unsigned long irq_flags; \
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200503 int __str_size = 0; \
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400504 int pc; \
505 \
506 local_save_flags(irq_flags); \
507 pc = preempt_count(); \
508 \
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200509 tstruct; \
510 \
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400511 event = trace_current_buffer_lock_reserve(event_##call.id, \
Frederic Weisbecker9cbf1172009-04-19 04:51:29 +0200512 sizeof(struct ftrace_raw_##call) + __str_size,\
513 irq_flags, pc); \
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400514 if (!event) \
515 return; \
516 entry = ring_buffer_event_data(event); \
517 \
518 assign; \
519 \
520 if (!filter_current_check_discard(call, entry, event)) \
521 trace_nowake_buffer_unlock_commit(event, irq_flags, pc); \
522} \
523 \
524static int ftrace_raw_reg_event_##call(void) \
525{ \
526 int ret; \
527 \
528 ret = register_trace_##call(ftrace_raw_event_##call); \
529 if (ret) \
530 pr_info("event trace: Could not activate trace point " \
531 "probe to " #call "\n"); \
532 return ret; \
533} \
534 \
535static void ftrace_raw_unreg_event_##call(void) \
536{ \
537 unregister_trace_##call(ftrace_raw_event_##call); \
538} \
539 \
540static struct trace_event ftrace_event_type_##call = { \
541 .trace = ftrace_raw_output_##call, \
542}; \
543 \
544static int ftrace_raw_init_event_##call(void) \
545{ \
546 int id; \
547 \
548 id = register_ftrace_event(&ftrace_event_type_##call); \
549 if (!id) \
550 return -ENODEV; \
551 event_##call.id = id; \
552 INIT_LIST_HEAD(&event_##call.fields); \
553 init_preds(&event_##call); \
554 return 0; \
555} \
556 \
557static struct ftrace_event_call __used \
558__attribute__((__aligned__(4))) \
559__attribute__((section("_ftrace_events"))) event_##call = { \
560 .name = #call, \
561 .system = __stringify(TRACE_SYSTEM), \
Steven Rostedt6d723732009-04-10 14:53:50 -0400562 .event = &ftrace_event_type_##call, \
Steven Rostedtf42c85e2009-04-13 12:25:37 -0400563 .raw_init = ftrace_raw_init_event_##call, \
564 .regfunc = ftrace_raw_reg_event_##call, \
565 .unregfunc = ftrace_raw_unreg_event_##call, \
566 .show_format = ftrace_format_##call, \
567 .define_fields = ftrace_define_fields_##call, \
568 _TRACE_PROFILE_INIT(call) \
569}
570
571#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
572
573#undef _TRACE_PROFILE
574#undef _TRACE_PROFILE_INIT
575