aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2015-03-24 17:58:09 -0400
committerSteven Rostedt <rostedt@goodmis.org>2015-04-08 09:39:56 -0400
commit0c564a538aa934ad15b2145aaf8b64f3feb0be63 (patch)
tree136ee858e4d9b1c4e2d9d39d4614eb8af175afb0 /include
parent889204278ccf98c5c097b1d1ae69babc6a3222fd (diff)
tracing: Add TRACE_DEFINE_ENUM() macro to map enums to their values
Several tracepoints use the helper functions __print_symbolic() or __print_flags() and pass in enums that do the mapping between the binary data stored and the value to print. This works well for reading the ASCII trace files, but when the data is read via userspace tools such as perf and trace-cmd, the conversion of the binary value to a human string format is lost if an enum is used, as userspace does not have access to what the ENUM is. For example, the tracepoint trace_tlb_flush() has: __print_symbolic(REC->reason, { TLB_FLUSH_ON_TASK_SWITCH, "flush on task switch" }, { TLB_REMOTE_SHOOTDOWN, "remote shootdown" }, { TLB_LOCAL_SHOOTDOWN, "local shootdown" }, { TLB_LOCAL_MM_SHOOTDOWN, "local mm shootdown" }) Which maps the enum values to the strings they represent. But perf and trace-cmd do no know what value TLB_LOCAL_MM_SHOOTDOWN is, and would not be able to map it. With TRACE_DEFINE_ENUM(), developers can place these in the event header files and ftrace will convert the enums to their values: By adding: TRACE_DEFINE_ENUM(TLB_FLUSH_ON_TASK_SWITCH); TRACE_DEFINE_ENUM(TLB_REMOTE_SHOOTDOWN); TRACE_DEFINE_ENUM(TLB_LOCAL_SHOOTDOWN); TRACE_DEFINE_ENUM(TLB_LOCAL_MM_SHOOTDOWN); $ cat /sys/kernel/debug/tracing/events/tlb/tlb_flush/format [...] __print_symbolic(REC->reason, { 0, "flush on task switch" }, { 1, "remote shootdown" }, { 2, "local shootdown" }, { 3, "local mm shootdown" }) The above is what userspace expects to see, and tools do not need to be modified to parse them. Link: http://lkml.kernel.org/r/20150403013802.220157513@goodmis.org Cc: Guilherme Cox <cox@computer.org> Cc: Tony Luck <tony.luck@gmail.com> Cc: Xie XiuQi <xiexiuqi@huawei.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Tested-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'include')
-rw-r--r--include/asm-generic/vmlinux.lds.h5
-rw-r--r--include/linux/ftrace_event.h2
-rw-r--r--include/linux/tracepoint.h8
-rw-r--r--include/trace/ftrace.h22
4 files changed, 32 insertions, 5 deletions
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ac78910d7416..f8e8b34dc427 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -124,7 +124,10 @@
124#define FTRACE_EVENTS() . = ALIGN(8); \ 124#define FTRACE_EVENTS() . = ALIGN(8); \
125 VMLINUX_SYMBOL(__start_ftrace_events) = .; \ 125 VMLINUX_SYMBOL(__start_ftrace_events) = .; \
126 *(_ftrace_events) \ 126 *(_ftrace_events) \
127 VMLINUX_SYMBOL(__stop_ftrace_events) = .; 127 VMLINUX_SYMBOL(__stop_ftrace_events) = .; \
128 VMLINUX_SYMBOL(__start_ftrace_enum_maps) = .; \
129 *(_ftrace_enum_map) \
130 VMLINUX_SYMBOL(__stop_ftrace_enum_maps) = .;
128#else 131#else
129#define FTRACE_EVENTS() 132#define FTRACE_EVENTS()
130#endif 133#endif
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 62b8fac7ded5..112cf49d9576 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -285,7 +285,7 @@ struct ftrace_event_call {
285 struct tracepoint *tp; 285 struct tracepoint *tp;
286 }; 286 };
287 struct trace_event event; 287 struct trace_event event;
288 const char *print_fmt; 288 char *print_fmt;
289 struct event_filter *filter; 289 struct event_filter *filter;
290 void *mod; 290 void *mod;
291 void *data; 291 void *data;
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index c72851328ca9..a5f7f3ecafa3 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -36,6 +36,12 @@ struct tracepoint {
36 struct tracepoint_func __rcu *funcs; 36 struct tracepoint_func __rcu *funcs;
37}; 37};
38 38
39struct trace_enum_map {
40 const char *system;
41 const char *enum_string;
42 unsigned long enum_value;
43};
44
39extern int 45extern int
40tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data); 46tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
41extern int 47extern int
@@ -87,6 +93,8 @@ extern void syscall_unregfunc(void);
87 93
88#define PARAMS(args...) args 94#define PARAMS(args...) args
89 95
96#define TRACE_DEFINE_ENUM(x)
97
90#endif /* _LINUX_TRACEPOINT_H */ 98#endif /* _LINUX_TRACEPOINT_H */
91 99
92/* 100/*
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 2f9b95b6d3fb..37d4b10b111d 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -33,6 +33,19 @@
33 33
34TRACE_MAKE_SYSTEM_STR(); 34TRACE_MAKE_SYSTEM_STR();
35 35
36#undef TRACE_DEFINE_ENUM
37#define TRACE_DEFINE_ENUM(a) \
38 static struct trace_enum_map __used __initdata \
39 __##TRACE_SYSTEM##_##a = \
40 { \
41 .system = TRACE_SYSTEM_STRING, \
42 .enum_string = #a, \
43 .enum_value = a \
44 }; \
45 static struct trace_enum_map __used \
46 __attribute__((section("_ftrace_enum_map"))) \
47 *TRACE_SYSTEM##_##a = &__##TRACE_SYSTEM##_##a
48
36/* 49/*
37 * DECLARE_EVENT_CLASS can be used to add a generic function 50 * DECLARE_EVENT_CLASS can be used to add a generic function
38 * handlers for events. That is, if all events have the same 51 * handlers for events. That is, if all events have the same
@@ -136,6 +149,9 @@ TRACE_MAKE_SYSTEM_STR();
136 * The size of an array is also encoded, in the higher 16 bits of <item>. 149 * The size of an array is also encoded, in the higher 16 bits of <item>.
137 */ 150 */
138 151
152#undef TRACE_DEFINE_ENUM
153#define TRACE_DEFINE_ENUM(a)
154
139#undef __field 155#undef __field
140#define __field(type, item) 156#define __field(type, item)
141 157
@@ -553,7 +569,7 @@ static inline notrace int ftrace_get_offsets_##call( \
553 * .trace = ftrace_raw_output_<call>, <-- stage 2 569 * .trace = ftrace_raw_output_<call>, <-- stage 2
554 * }; 570 * };
555 * 571 *
556 * static const char print_fmt_<call>[] = <TP_printk>; 572 * static char print_fmt_<call>[] = <TP_printk>;
557 * 573 *
558 * static struct ftrace_event_class __used event_class_<template> = { 574 * static struct ftrace_event_class __used event_class_<template> = {
559 * .system = "<system>", 575 * .system = "<system>",
@@ -704,7 +720,7 @@ static inline void ftrace_test_probe_##call(void) \
704#undef DECLARE_EVENT_CLASS 720#undef DECLARE_EVENT_CLASS
705#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 721#define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
706_TRACE_PERF_PROTO(call, PARAMS(proto)); \ 722_TRACE_PERF_PROTO(call, PARAMS(proto)); \
707static const char print_fmt_##call[] = print; \ 723static char print_fmt_##call[] = print; \
708static struct ftrace_event_class __used __refdata event_class_##call = { \ 724static struct ftrace_event_class __used __refdata event_class_##call = { \
709 .system = TRACE_SYSTEM_STRING, \ 725 .system = TRACE_SYSTEM_STRING, \
710 .define_fields = ftrace_define_fields_##call, \ 726 .define_fields = ftrace_define_fields_##call, \
@@ -733,7 +749,7 @@ __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call
733#undef DEFINE_EVENT_PRINT 749#undef DEFINE_EVENT_PRINT
734#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \ 750#define DEFINE_EVENT_PRINT(template, call, proto, args, print) \
735 \ 751 \
736static const char print_fmt_##call[] = print; \ 752static char print_fmt_##call[] = print; \
737 \ 753 \
738static struct ftrace_event_call __used event_##call = { \ 754static struct ftrace_event_call __used event_##call = { \
739 .class = &event_class_##template, \ 755 .class = &event_class_##template, \