brintos

brintos / linux-shallow public Read only

0
0
Text · 7.1 KiB · 6e492db Raw
222 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * This is similar to the trace_events.h file, but is to only4 * create custom trace events to be attached to existing tracepoints.5 * Where as the TRACE_EVENT() macro (from trace_events.h) will create6 * 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 existing8 * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will9 * 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_SYSTEM16#define TRACE_SYSTEM custom17 18#ifndef TRACE_SYSTEM_VAR19#define TRACE_SYSTEM_VAR TRACE_SYSTEM20#endif21 22/* The init stage creates the system string and enum mappings */23 24#include "stages/init.h"25 26#undef TRACE_CUSTOM_EVENT27#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_CLASS41#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_EVENT51#define DEFINE_CUSTOM_EVENT(template, name, proto, args)	\52	static struct trace_event_call	__used			\53	__attribute__((__aligned__(4))) custom_event_##name54 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_CLASS62#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_EVENT68#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_CLASS77#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \78static notrace enum print_line_t					\79trace_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}									\97static 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_CLASS108#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print)	\109static 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_CLASS120#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \121static 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_CLASS140#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \141									\142static notrace void							\143trace_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 check170 * to make sure that if the tracepoint handling changes, the ftrace probe will171 * fail to compile unless it too is updated.172 */173 174#undef DEFINE_CUSTOM_EVENT175#define DEFINE_CUSTOM_EVENT(template, call, proto, args)		\176static 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_CLASS188#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \189static char custom_print_fmt_##call[] = print;					\190static 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_EVENT200#define DEFINE_CUSTOM_EVENT(template, call, proto, args)		\201									\202static 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};									\209static 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}									\218static struct trace_event_call __used					\219__section("_ftrace_events") *__custom_event_##call = &custom_event_##call220 221#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)222