xref: /openbmc/linux/include/trace/trace_custom_events.h (revision 3a73333fb370f7b65de9d94c53df503642bda789)
1*3a73333fSSteven Rostedt (Google) /* SPDX-License-Identifier: GPL-2.0 */
2*3a73333fSSteven Rostedt (Google) /*
3*3a73333fSSteven Rostedt (Google)  * This is similar to the trace_events.h file, but is to only
4*3a73333fSSteven Rostedt (Google)  * create custom trace events to be attached to existing tracepoints.
5*3a73333fSSteven Rostedt (Google)  * Where as the TRACE_EVENT() macro (from trace_events.h) will create
6*3a73333fSSteven Rostedt (Google)  * both the trace event and the tracepoint it will attach the event to,
7*3a73333fSSteven Rostedt (Google)  * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing
8*3a73333fSSteven Rostedt (Google)  * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will
9*3a73333fSSteven Rostedt (Google)  * be placed in the "custom" system.
10*3a73333fSSteven Rostedt (Google)  */
11*3a73333fSSteven Rostedt (Google) 
12*3a73333fSSteven Rostedt (Google) #include <linux/trace_events.h>
13*3a73333fSSteven Rostedt (Google) 
14*3a73333fSSteven Rostedt (Google) /* All custom events are placed in the custom group */
15*3a73333fSSteven Rostedt (Google) #undef TRACE_SYSTEM
16*3a73333fSSteven Rostedt (Google) #define TRACE_SYSTEM custom
17*3a73333fSSteven Rostedt (Google) 
18*3a73333fSSteven Rostedt (Google) #ifndef TRACE_SYSTEM_VAR
19*3a73333fSSteven Rostedt (Google) #define TRACE_SYSTEM_VAR TRACE_SYSTEM
20*3a73333fSSteven Rostedt (Google) #endif
21*3a73333fSSteven Rostedt (Google) 
22*3a73333fSSteven Rostedt (Google) /* The init stage creates the system string and enum mappings */
23*3a73333fSSteven Rostedt (Google) 
24*3a73333fSSteven Rostedt (Google) #include "stages/init.h"
25*3a73333fSSteven Rostedt (Google) 
26*3a73333fSSteven Rostedt (Google) #undef TRACE_CUSTOM_EVENT
27*3a73333fSSteven Rostedt (Google) #define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \
28*3a73333fSSteven Rostedt (Google) 	DECLARE_CUSTOM_EVENT_CLASS(name,			      \
29*3a73333fSSteven Rostedt (Google) 			     PARAMS(proto),		       \
30*3a73333fSSteven Rostedt (Google) 			     PARAMS(args),		       \
31*3a73333fSSteven Rostedt (Google) 			     PARAMS(tstruct),		       \
32*3a73333fSSteven Rostedt (Google) 			     PARAMS(assign),		       \
33*3a73333fSSteven Rostedt (Google) 			     PARAMS(print));		       \
34*3a73333fSSteven Rostedt (Google) 	DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args));
35*3a73333fSSteven Rostedt (Google) 
36*3a73333fSSteven Rostedt (Google) /* Stage 1 creates the structure of the recorded event layout */
37*3a73333fSSteven Rostedt (Google) 
38*3a73333fSSteven Rostedt (Google) #include "stages/stage1_defines.h"
39*3a73333fSSteven Rostedt (Google) 
40*3a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
41*3a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
42*3a73333fSSteven Rostedt (Google) 	struct trace_custom_event_raw_##name {				\
43*3a73333fSSteven Rostedt (Google) 		struct trace_entry	ent;				\
44*3a73333fSSteven Rostedt (Google) 		tstruct							\
45*3a73333fSSteven Rostedt (Google) 		char			__data[];			\
46*3a73333fSSteven Rostedt (Google) 	};								\
47*3a73333fSSteven Rostedt (Google) 									\
48*3a73333fSSteven Rostedt (Google) 	static struct trace_event_class custom_event_class_##name;
49*3a73333fSSteven Rostedt (Google) 
50*3a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT
51*3a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, name, proto, args)	\
52*3a73333fSSteven Rostedt (Google) 	static struct trace_event_call	__used			\
53*3a73333fSSteven Rostedt (Google) 	__attribute__((__aligned__(4))) custom_event_##name
54*3a73333fSSteven Rostedt (Google) 
55*3a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
56*3a73333fSSteven Rostedt (Google) 
57*3a73333fSSteven Rostedt (Google) /* Stage 2 creates the custom class */
58*3a73333fSSteven Rostedt (Google) 
59*3a73333fSSteven Rostedt (Google) #include "stages/stage2_defines.h"
60*3a73333fSSteven Rostedt (Google) 
61*3a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
62*3a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print)	\
63*3a73333fSSteven Rostedt (Google) 	struct trace_custom_event_data_offsets_##call {			\
64*3a73333fSSteven Rostedt (Google) 		tstruct;						\
65*3a73333fSSteven Rostedt (Google) 	};
66*3a73333fSSteven Rostedt (Google) 
67*3a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT
68*3a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, name, proto, args)
69*3a73333fSSteven Rostedt (Google) 
70*3a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
71*3a73333fSSteven Rostedt (Google) 
72*3a73333fSSteven Rostedt (Google) /* Stage 3 create the way to print the custom event */
73*3a73333fSSteven Rostedt (Google) 
74*3a73333fSSteven Rostedt (Google) #include "stages/stage3_defines.h"
75*3a73333fSSteven Rostedt (Google) 
76*3a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
77*3a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
78*3a73333fSSteven Rostedt (Google) static notrace enum print_line_t					\
79*3a73333fSSteven Rostedt (Google) trace_custom_raw_output_##call(struct trace_iterator *iter, int flags,	\
80*3a73333fSSteven Rostedt (Google) 			struct trace_event *trace_event)		\
81*3a73333fSSteven Rostedt (Google) {									\
82*3a73333fSSteven Rostedt (Google) 	struct trace_seq *s = &iter->seq;				\
83*3a73333fSSteven Rostedt (Google) 	struct trace_seq __maybe_unused *p = &iter->tmp_seq;		\
84*3a73333fSSteven Rostedt (Google) 	struct trace_custom_event_raw_##call *field;			\
85*3a73333fSSteven Rostedt (Google) 	int ret;							\
86*3a73333fSSteven Rostedt (Google) 									\
87*3a73333fSSteven Rostedt (Google) 	field = (typeof(field))iter->ent;				\
88*3a73333fSSteven Rostedt (Google) 									\
89*3a73333fSSteven Rostedt (Google) 	ret = trace_raw_output_prep(iter, trace_event);			\
90*3a73333fSSteven Rostedt (Google) 	if (ret != TRACE_TYPE_HANDLED)					\
91*3a73333fSSteven Rostedt (Google) 		return ret;						\
92*3a73333fSSteven Rostedt (Google) 									\
93*3a73333fSSteven Rostedt (Google) 	trace_event_printf(iter, print);				\
94*3a73333fSSteven Rostedt (Google) 									\
95*3a73333fSSteven Rostedt (Google) 	return trace_handle_return(s);					\
96*3a73333fSSteven Rostedt (Google) }									\
97*3a73333fSSteven Rostedt (Google) static struct trace_event_functions trace_custom_event_type_funcs_##call = { \
98*3a73333fSSteven Rostedt (Google) 	.trace			= trace_custom_raw_output_##call,	\
99*3a73333fSSteven Rostedt (Google) };
100*3a73333fSSteven Rostedt (Google) 
101*3a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
102*3a73333fSSteven Rostedt (Google) 
103*3a73333fSSteven Rostedt (Google) /* Stage 4 creates the offset layout for the fields */
104*3a73333fSSteven Rostedt (Google) 
105*3a73333fSSteven Rostedt (Google) #include "stages/stage4_defines.h"
106*3a73333fSSteven Rostedt (Google) 
107*3a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
108*3a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print)	\
109*3a73333fSSteven Rostedt (Google) static struct trace_event_fields trace_custom_event_fields_##call[] = {	\
110*3a73333fSSteven Rostedt (Google) 	tstruct								\
111*3a73333fSSteven Rostedt (Google) 	{} };
112*3a73333fSSteven Rostedt (Google) 
113*3a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
114*3a73333fSSteven Rostedt (Google) 
115*3a73333fSSteven Rostedt (Google) /* Stage 5 creates the helper function for dynamic fields */
116*3a73333fSSteven Rostedt (Google) 
117*3a73333fSSteven Rostedt (Google) #include "stages/stage5_defines.h"
118*3a73333fSSteven Rostedt (Google) 
119*3a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
120*3a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
121*3a73333fSSteven Rostedt (Google) static inline notrace int trace_custom_event_get_offsets_##call(	\
122*3a73333fSSteven Rostedt (Google) 	struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \
123*3a73333fSSteven Rostedt (Google) {									\
124*3a73333fSSteven Rostedt (Google) 	int __data_size = 0;						\
125*3a73333fSSteven Rostedt (Google) 	int __maybe_unused __item_length;				\
126*3a73333fSSteven Rostedt (Google) 	struct trace_custom_event_raw_##call __maybe_unused *entry;	\
127*3a73333fSSteven Rostedt (Google) 									\
128*3a73333fSSteven Rostedt (Google) 	tstruct;							\
129*3a73333fSSteven Rostedt (Google) 									\
130*3a73333fSSteven Rostedt (Google) 	return __data_size;						\
131*3a73333fSSteven Rostedt (Google) }
132*3a73333fSSteven Rostedt (Google) 
133*3a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
134*3a73333fSSteven Rostedt (Google) 
135*3a73333fSSteven Rostedt (Google) /* Stage 6 creates the probe function that records the event */
136*3a73333fSSteven Rostedt (Google) 
137*3a73333fSSteven Rostedt (Google) #include "stages/stage6_defines.h"
138*3a73333fSSteven Rostedt (Google) 
139*3a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
140*3a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
141*3a73333fSSteven Rostedt (Google) 									\
142*3a73333fSSteven Rostedt (Google) static notrace void							\
143*3a73333fSSteven Rostedt (Google) trace_custom_event_raw_event_##call(void *__data, proto)		\
144*3a73333fSSteven Rostedt (Google) {									\
145*3a73333fSSteven Rostedt (Google) 	struct trace_event_file *trace_file = __data;			\
146*3a73333fSSteven Rostedt (Google) 	struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \
147*3a73333fSSteven Rostedt (Google) 	struct trace_event_buffer fbuffer;				\
148*3a73333fSSteven Rostedt (Google) 	struct trace_custom_event_raw_##call *entry;			\
149*3a73333fSSteven Rostedt (Google) 	int __data_size;						\
150*3a73333fSSteven Rostedt (Google) 									\
151*3a73333fSSteven Rostedt (Google) 	if (trace_trigger_soft_disabled(trace_file))			\
152*3a73333fSSteven Rostedt (Google) 		return;							\
153*3a73333fSSteven Rostedt (Google) 									\
154*3a73333fSSteven Rostedt (Google) 	__data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \
155*3a73333fSSteven Rostedt (Google) 									\
156*3a73333fSSteven Rostedt (Google) 	entry = trace_event_buffer_reserve(&fbuffer, trace_file,	\
157*3a73333fSSteven Rostedt (Google) 				 sizeof(*entry) + __data_size);		\
158*3a73333fSSteven Rostedt (Google) 									\
159*3a73333fSSteven Rostedt (Google) 	if (!entry)							\
160*3a73333fSSteven Rostedt (Google) 		return;							\
161*3a73333fSSteven Rostedt (Google) 									\
162*3a73333fSSteven Rostedt (Google) 	tstruct								\
163*3a73333fSSteven Rostedt (Google) 									\
164*3a73333fSSteven Rostedt (Google) 	{ assign; }							\
165*3a73333fSSteven Rostedt (Google) 									\
166*3a73333fSSteven Rostedt (Google) 	trace_event_buffer_commit(&fbuffer);				\
167*3a73333fSSteven Rostedt (Google) }
168*3a73333fSSteven Rostedt (Google) /*
169*3a73333fSSteven Rostedt (Google)  * The ftrace_test_custom_probe is compiled out, it is only here as a build time check
170*3a73333fSSteven Rostedt (Google)  * to make sure that if the tracepoint handling changes, the ftrace probe will
171*3a73333fSSteven Rostedt (Google)  * fail to compile unless it too is updated.
172*3a73333fSSteven Rostedt (Google)  */
173*3a73333fSSteven Rostedt (Google) 
174*3a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT
175*3a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, call, proto, args)		\
176*3a73333fSSteven Rostedt (Google) static inline void ftrace_test_custom_probe_##call(void)		\
177*3a73333fSSteven Rostedt (Google) {									\
178*3a73333fSSteven Rostedt (Google) 	check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \
179*3a73333fSSteven Rostedt (Google) }
180*3a73333fSSteven Rostedt (Google) 
181*3a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
182*3a73333fSSteven Rostedt (Google) 
183*3a73333fSSteven Rostedt (Google) /* Stage 7 creates the actual class and event structure for the custom event */
184*3a73333fSSteven Rostedt (Google) 
185*3a73333fSSteven Rostedt (Google) #include "stages/stage7_defines.h"
186*3a73333fSSteven Rostedt (Google) 
187*3a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
188*3a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
189*3a73333fSSteven Rostedt (Google) static char custom_print_fmt_##call[] = print;					\
190*3a73333fSSteven Rostedt (Google) static struct trace_event_class __used __refdata custom_event_class_##call = { \
191*3a73333fSSteven Rostedt (Google) 	.system			= TRACE_SYSTEM_STRING,			\
192*3a73333fSSteven Rostedt (Google) 	.fields_array		= trace_custom_event_fields_##call,		\
193*3a73333fSSteven Rostedt (Google) 	.fields			= LIST_HEAD_INIT(custom_event_class_##call.fields),\
194*3a73333fSSteven Rostedt (Google) 	.raw_init		= trace_event_raw_init,			\
195*3a73333fSSteven Rostedt (Google) 	.probe			= trace_custom_event_raw_event_##call,	\
196*3a73333fSSteven Rostedt (Google) 	.reg			= trace_event_reg,			\
197*3a73333fSSteven Rostedt (Google) };
198*3a73333fSSteven Rostedt (Google) 
199*3a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT
200*3a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, call, proto, args)		\
201*3a73333fSSteven Rostedt (Google) 									\
202*3a73333fSSteven Rostedt (Google) static struct trace_event_call __used custom_event_##call = {		\
203*3a73333fSSteven Rostedt (Google) 	.name			= #call,				\
204*3a73333fSSteven Rostedt (Google) 	.class			= &custom_event_class_##template,	\
205*3a73333fSSteven Rostedt (Google) 	.event.funcs		= &trace_custom_event_type_funcs_##template, \
206*3a73333fSSteven Rostedt (Google) 	.print_fmt		= custom_print_fmt_##template,		\
207*3a73333fSSteven Rostedt (Google) 	.flags			= TRACE_EVENT_FL_CUSTOM,		\
208*3a73333fSSteven Rostedt (Google) };									\
209*3a73333fSSteven Rostedt (Google) static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \
210*3a73333fSSteven Rostedt (Google) {									\
211*3a73333fSSteven Rostedt (Google) 	if (tp->name && strcmp(tp->name, #call) == 0) {			\
212*3a73333fSSteven Rostedt (Google) 		custom_event_##call.tp = tp;				\
213*3a73333fSSteven Rostedt (Google) 		custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT;	\
214*3a73333fSSteven Rostedt (Google) 		return 1;						\
215*3a73333fSSteven Rostedt (Google) 	}								\
216*3a73333fSSteven Rostedt (Google) 	return 0;							\
217*3a73333fSSteven Rostedt (Google) }									\
218*3a73333fSSteven Rostedt (Google) static struct trace_event_call __used					\
219*3a73333fSSteven Rostedt (Google) __section("_ftrace_events") *__custom_event_##call = &custom_event_##call
220*3a73333fSSteven Rostedt (Google) 
221*3a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
222