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)
222