13a73333fSSteven Rostedt (Google) /* SPDX-License-Identifier: GPL-2.0 */
23a73333fSSteven Rostedt (Google) /*
33a73333fSSteven Rostedt (Google)  * This is similar to the trace_events.h file, but is to only
43a73333fSSteven Rostedt (Google)  * create custom trace events to be attached to existing tracepoints.
53a73333fSSteven Rostedt (Google)  * Where as the TRACE_EVENT() macro (from trace_events.h) will create
63a73333fSSteven Rostedt (Google)  * both the trace event and the tracepoint it will attach the event to,
73a73333fSSteven Rostedt (Google)  * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing
83a73333fSSteven Rostedt (Google)  * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will
93a73333fSSteven Rostedt (Google)  * be placed in the "custom" system.
103a73333fSSteven Rostedt (Google)  */
113a73333fSSteven Rostedt (Google) 
123a73333fSSteven Rostedt (Google) #include <linux/trace_events.h>
133a73333fSSteven Rostedt (Google) 
143a73333fSSteven Rostedt (Google) /* All custom events are placed in the custom group */
153a73333fSSteven Rostedt (Google) #undef TRACE_SYSTEM
163a73333fSSteven Rostedt (Google) #define TRACE_SYSTEM custom
173a73333fSSteven Rostedt (Google) 
183a73333fSSteven Rostedt (Google) #ifndef TRACE_SYSTEM_VAR
193a73333fSSteven Rostedt (Google) #define TRACE_SYSTEM_VAR TRACE_SYSTEM
203a73333fSSteven Rostedt (Google) #endif
213a73333fSSteven Rostedt (Google) 
223a73333fSSteven Rostedt (Google) /* The init stage creates the system string and enum mappings */
233a73333fSSteven Rostedt (Google) 
243a73333fSSteven Rostedt (Google) #include "stages/init.h"
253a73333fSSteven Rostedt (Google) 
263a73333fSSteven Rostedt (Google) #undef TRACE_CUSTOM_EVENT
273a73333fSSteven Rostedt (Google) #define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \
283a73333fSSteven Rostedt (Google) 	DECLARE_CUSTOM_EVENT_CLASS(name,			      \
293a73333fSSteven Rostedt (Google) 			     PARAMS(proto),		       \
303a73333fSSteven Rostedt (Google) 			     PARAMS(args),		       \
313a73333fSSteven Rostedt (Google) 			     PARAMS(tstruct),		       \
323a73333fSSteven Rostedt (Google) 			     PARAMS(assign),		       \
333a73333fSSteven Rostedt (Google) 			     PARAMS(print));		       \
343a73333fSSteven Rostedt (Google) 	DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args));
353a73333fSSteven Rostedt (Google) 
363a73333fSSteven Rostedt (Google) /* Stage 1 creates the structure of the recorded event layout */
373a73333fSSteven Rostedt (Google) 
38*84055411SSteven Rostedt (Google) #include "stages/stage1_struct_define.h"
393a73333fSSteven Rostedt (Google) 
403a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
413a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
423a73333fSSteven Rostedt (Google) 	struct trace_custom_event_raw_##name {				\
433a73333fSSteven Rostedt (Google) 		struct trace_entry	ent;				\
443a73333fSSteven Rostedt (Google) 		tstruct							\
453a73333fSSteven Rostedt (Google) 		char			__data[];			\
463a73333fSSteven Rostedt (Google) 	};								\
473a73333fSSteven Rostedt (Google) 									\
483a73333fSSteven Rostedt (Google) 	static struct trace_event_class custom_event_class_##name;
493a73333fSSteven Rostedt (Google) 
503a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT
513a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, name, proto, args)	\
523a73333fSSteven Rostedt (Google) 	static struct trace_event_call	__used			\
533a73333fSSteven Rostedt (Google) 	__attribute__((__aligned__(4))) custom_event_##name
543a73333fSSteven Rostedt (Google) 
553a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
563a73333fSSteven Rostedt (Google) 
573a73333fSSteven Rostedt (Google) /* Stage 2 creates the custom class */
583a73333fSSteven Rostedt (Google) 
59*84055411SSteven Rostedt (Google) #include "stages/stage2_data_offsets.h"
603a73333fSSteven Rostedt (Google) 
613a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
623a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print)	\
633a73333fSSteven Rostedt (Google) 	struct trace_custom_event_data_offsets_##call {			\
643a73333fSSteven Rostedt (Google) 		tstruct;						\
653a73333fSSteven Rostedt (Google) 	};
663a73333fSSteven Rostedt (Google) 
673a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT
683a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, name, proto, args)
693a73333fSSteven Rostedt (Google) 
703a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
713a73333fSSteven Rostedt (Google) 
723a73333fSSteven Rostedt (Google) /* Stage 3 create the way to print the custom event */
733a73333fSSteven Rostedt (Google) 
74*84055411SSteven Rostedt (Google) #include "stages/stage3_trace_output.h"
753a73333fSSteven Rostedt (Google) 
763a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
773a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
783a73333fSSteven Rostedt (Google) static notrace enum print_line_t					\
793a73333fSSteven Rostedt (Google) trace_custom_raw_output_##call(struct trace_iterator *iter, int flags,	\
803a73333fSSteven Rostedt (Google) 			struct trace_event *trace_event)		\
813a73333fSSteven Rostedt (Google) {									\
823a73333fSSteven Rostedt (Google) 	struct trace_seq *s = &iter->seq;				\
833a73333fSSteven Rostedt (Google) 	struct trace_seq __maybe_unused *p = &iter->tmp_seq;		\
843a73333fSSteven Rostedt (Google) 	struct trace_custom_event_raw_##call *field;			\
853a73333fSSteven Rostedt (Google) 	int ret;							\
863a73333fSSteven Rostedt (Google) 									\
873a73333fSSteven Rostedt (Google) 	field = (typeof(field))iter->ent;				\
883a73333fSSteven Rostedt (Google) 									\
893a73333fSSteven Rostedt (Google) 	ret = trace_raw_output_prep(iter, trace_event);			\
903a73333fSSteven Rostedt (Google) 	if (ret != TRACE_TYPE_HANDLED)					\
913a73333fSSteven Rostedt (Google) 		return ret;						\
923a73333fSSteven Rostedt (Google) 									\
933a73333fSSteven Rostedt (Google) 	trace_event_printf(iter, print);				\
943a73333fSSteven Rostedt (Google) 									\
953a73333fSSteven Rostedt (Google) 	return trace_handle_return(s);					\
963a73333fSSteven Rostedt (Google) }									\
973a73333fSSteven Rostedt (Google) static struct trace_event_functions trace_custom_event_type_funcs_##call = { \
983a73333fSSteven Rostedt (Google) 	.trace			= trace_custom_raw_output_##call,	\
993a73333fSSteven Rostedt (Google) };
1003a73333fSSteven Rostedt (Google) 
1013a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
1023a73333fSSteven Rostedt (Google) 
1033a73333fSSteven Rostedt (Google) /* Stage 4 creates the offset layout for the fields */
1043a73333fSSteven Rostedt (Google) 
105*84055411SSteven Rostedt (Google) #include "stages/stage4_event_fields.h"
1063a73333fSSteven Rostedt (Google) 
1073a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
1083a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print)	\
1093a73333fSSteven Rostedt (Google) static struct trace_event_fields trace_custom_event_fields_##call[] = {	\
1103a73333fSSteven Rostedt (Google) 	tstruct								\
1113a73333fSSteven Rostedt (Google) 	{} };
1123a73333fSSteven Rostedt (Google) 
1133a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
1143a73333fSSteven Rostedt (Google) 
1153a73333fSSteven Rostedt (Google) /* Stage 5 creates the helper function for dynamic fields */
1163a73333fSSteven Rostedt (Google) 
117*84055411SSteven Rostedt (Google) #include "stages/stage5_get_offsets.h"
1183a73333fSSteven Rostedt (Google) 
1193a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
1203a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
1213a73333fSSteven Rostedt (Google) static inline notrace int trace_custom_event_get_offsets_##call(	\
1223a73333fSSteven Rostedt (Google) 	struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \
1233a73333fSSteven Rostedt (Google) {									\
1243a73333fSSteven Rostedt (Google) 	int __data_size = 0;						\
1253a73333fSSteven Rostedt (Google) 	int __maybe_unused __item_length;				\
1263a73333fSSteven Rostedt (Google) 	struct trace_custom_event_raw_##call __maybe_unused *entry;	\
1273a73333fSSteven Rostedt (Google) 									\
1283a73333fSSteven Rostedt (Google) 	tstruct;							\
1293a73333fSSteven Rostedt (Google) 									\
1303a73333fSSteven Rostedt (Google) 	return __data_size;						\
1313a73333fSSteven Rostedt (Google) }
1323a73333fSSteven Rostedt (Google) 
1333a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
1343a73333fSSteven Rostedt (Google) 
1353a73333fSSteven Rostedt (Google) /* Stage 6 creates the probe function that records the event */
1363a73333fSSteven Rostedt (Google) 
137*84055411SSteven Rostedt (Google) #include "stages/stage6_event_callback.h"
1383a73333fSSteven Rostedt (Google) 
1393a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
1403a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
1413a73333fSSteven Rostedt (Google) 									\
1423a73333fSSteven Rostedt (Google) static notrace void							\
1433a73333fSSteven Rostedt (Google) trace_custom_event_raw_event_##call(void *__data, proto)		\
1443a73333fSSteven Rostedt (Google) {									\
1453a73333fSSteven Rostedt (Google) 	struct trace_event_file *trace_file = __data;			\
1463a73333fSSteven Rostedt (Google) 	struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \
1473a73333fSSteven Rostedt (Google) 	struct trace_event_buffer fbuffer;				\
1483a73333fSSteven Rostedt (Google) 	struct trace_custom_event_raw_##call *entry;			\
1493a73333fSSteven Rostedt (Google) 	int __data_size;						\
1503a73333fSSteven Rostedt (Google) 									\
1513a73333fSSteven Rostedt (Google) 	if (trace_trigger_soft_disabled(trace_file))			\
1523a73333fSSteven Rostedt (Google) 		return;							\
1533a73333fSSteven Rostedt (Google) 									\
1543a73333fSSteven Rostedt (Google) 	__data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \
1553a73333fSSteven Rostedt (Google) 									\
1563a73333fSSteven Rostedt (Google) 	entry = trace_event_buffer_reserve(&fbuffer, trace_file,	\
1573a73333fSSteven Rostedt (Google) 				 sizeof(*entry) + __data_size);		\
1583a73333fSSteven Rostedt (Google) 									\
1593a73333fSSteven Rostedt (Google) 	if (!entry)							\
1603a73333fSSteven Rostedt (Google) 		return;							\
1613a73333fSSteven Rostedt (Google) 									\
1623a73333fSSteven Rostedt (Google) 	tstruct								\
1633a73333fSSteven Rostedt (Google) 									\
1643a73333fSSteven Rostedt (Google) 	{ assign; }							\
1653a73333fSSteven Rostedt (Google) 									\
1663a73333fSSteven Rostedt (Google) 	trace_event_buffer_commit(&fbuffer);				\
1673a73333fSSteven Rostedt (Google) }
1683a73333fSSteven Rostedt (Google) /*
1693a73333fSSteven Rostedt (Google)  * The ftrace_test_custom_probe is compiled out, it is only here as a build time check
1703a73333fSSteven Rostedt (Google)  * to make sure that if the tracepoint handling changes, the ftrace probe will
1713a73333fSSteven Rostedt (Google)  * fail to compile unless it too is updated.
1723a73333fSSteven Rostedt (Google)  */
1733a73333fSSteven Rostedt (Google) 
1743a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT
1753a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, call, proto, args)		\
1763a73333fSSteven Rostedt (Google) static inline void ftrace_test_custom_probe_##call(void)		\
1773a73333fSSteven Rostedt (Google) {									\
1783a73333fSSteven Rostedt (Google) 	check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \
1793a73333fSSteven Rostedt (Google) }
1803a73333fSSteven Rostedt (Google) 
1813a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
1823a73333fSSteven Rostedt (Google) 
1833a73333fSSteven Rostedt (Google) /* Stage 7 creates the actual class and event structure for the custom event */
1843a73333fSSteven Rostedt (Google) 
185*84055411SSteven Rostedt (Google) #include "stages/stage7_class_define.h"
1863a73333fSSteven Rostedt (Google) 
1873a73333fSSteven Rostedt (Google) #undef DECLARE_CUSTOM_EVENT_CLASS
1883a73333fSSteven Rostedt (Google) #define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
1893a73333fSSteven Rostedt (Google) static char custom_print_fmt_##call[] = print;					\
1903a73333fSSteven Rostedt (Google) static struct trace_event_class __used __refdata custom_event_class_##call = { \
1913a73333fSSteven Rostedt (Google) 	.system			= TRACE_SYSTEM_STRING,			\
1923a73333fSSteven Rostedt (Google) 	.fields_array		= trace_custom_event_fields_##call,		\
1933a73333fSSteven Rostedt (Google) 	.fields			= LIST_HEAD_INIT(custom_event_class_##call.fields),\
1943a73333fSSteven Rostedt (Google) 	.raw_init		= trace_event_raw_init,			\
1953a73333fSSteven Rostedt (Google) 	.probe			= trace_custom_event_raw_event_##call,	\
1963a73333fSSteven Rostedt (Google) 	.reg			= trace_event_reg,			\
1973a73333fSSteven Rostedt (Google) };
1983a73333fSSteven Rostedt (Google) 
1993a73333fSSteven Rostedt (Google) #undef DEFINE_CUSTOM_EVENT
2003a73333fSSteven Rostedt (Google) #define DEFINE_CUSTOM_EVENT(template, call, proto, args)		\
2013a73333fSSteven Rostedt (Google) 									\
2023a73333fSSteven Rostedt (Google) static struct trace_event_call __used custom_event_##call = {		\
2033a73333fSSteven Rostedt (Google) 	.name			= #call,				\
2043a73333fSSteven Rostedt (Google) 	.class			= &custom_event_class_##template,	\
2053a73333fSSteven Rostedt (Google) 	.event.funcs		= &trace_custom_event_type_funcs_##template, \
2063a73333fSSteven Rostedt (Google) 	.print_fmt		= custom_print_fmt_##template,		\
2073a73333fSSteven Rostedt (Google) 	.flags			= TRACE_EVENT_FL_CUSTOM,		\
2083a73333fSSteven Rostedt (Google) };									\
2093a73333fSSteven Rostedt (Google) static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \
2103a73333fSSteven Rostedt (Google) {									\
2113a73333fSSteven Rostedt (Google) 	if (tp->name && strcmp(tp->name, #call) == 0) {			\
2123a73333fSSteven Rostedt (Google) 		custom_event_##call.tp = tp;				\
2133a73333fSSteven Rostedt (Google) 		custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT;	\
2143a73333fSSteven Rostedt (Google) 		return 1;						\
2153a73333fSSteven Rostedt (Google) 	}								\
2163a73333fSSteven Rostedt (Google) 	return 0;							\
2173a73333fSSteven Rostedt (Google) }									\
2183a73333fSSteven Rostedt (Google) static struct trace_event_call __used					\
2193a73333fSSteven Rostedt (Google) __section("_ftrace_events") *__custom_event_##call = &custom_event_##call
2203a73333fSSteven Rostedt (Google) 
2213a73333fSSteven Rostedt (Google) #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
222