162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This is similar to the trace_events.h file, but is to only 462306a36Sopenharmony_ci * create custom trace events to be attached to existing tracepoints. 562306a36Sopenharmony_ci * Where as the TRACE_EVENT() macro (from trace_events.h) will create 662306a36Sopenharmony_ci * both the trace event and the tracepoint it will attach the event to, 762306a36Sopenharmony_ci * TRACE_CUSTOM_EVENT() is to create only a custom version of an existing 862306a36Sopenharmony_ci * trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will 962306a36Sopenharmony_ci * be placed in the "custom" system. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/trace_events.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* All custom events are placed in the custom group */ 1562306a36Sopenharmony_ci#undef TRACE_SYSTEM 1662306a36Sopenharmony_ci#define TRACE_SYSTEM custom 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#ifndef TRACE_SYSTEM_VAR 1962306a36Sopenharmony_ci#define TRACE_SYSTEM_VAR TRACE_SYSTEM 2062306a36Sopenharmony_ci#endif 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* The init stage creates the system string and enum mappings */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "stages/init.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#undef TRACE_CUSTOM_EVENT 2762306a36Sopenharmony_ci#define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \ 2862306a36Sopenharmony_ci DECLARE_CUSTOM_EVENT_CLASS(name, \ 2962306a36Sopenharmony_ci PARAMS(proto), \ 3062306a36Sopenharmony_ci PARAMS(args), \ 3162306a36Sopenharmony_ci PARAMS(tstruct), \ 3262306a36Sopenharmony_ci PARAMS(assign), \ 3362306a36Sopenharmony_ci PARAMS(print)); \ 3462306a36Sopenharmony_ci DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args)); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* Stage 1 creates the structure of the recorded event layout */ 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include "stages/stage1_struct_define.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#undef DECLARE_CUSTOM_EVENT_CLASS 4162306a36Sopenharmony_ci#define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \ 4262306a36Sopenharmony_ci struct trace_custom_event_raw_##name { \ 4362306a36Sopenharmony_ci struct trace_entry ent; \ 4462306a36Sopenharmony_ci tstruct \ 4562306a36Sopenharmony_ci char __data[]; \ 4662306a36Sopenharmony_ci }; \ 4762306a36Sopenharmony_ci \ 4862306a36Sopenharmony_ci static struct trace_event_class custom_event_class_##name; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci#undef DEFINE_CUSTOM_EVENT 5162306a36Sopenharmony_ci#define DEFINE_CUSTOM_EVENT(template, name, proto, args) \ 5262306a36Sopenharmony_ci static struct trace_event_call __used \ 5362306a36Sopenharmony_ci __attribute__((__aligned__(4))) custom_event_##name 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* Stage 2 creates the custom class */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#include "stages/stage2_data_offsets.h" 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#undef DECLARE_CUSTOM_EVENT_CLASS 6262306a36Sopenharmony_ci#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 6362306a36Sopenharmony_ci struct trace_custom_event_data_offsets_##call { \ 6462306a36Sopenharmony_ci tstruct; \ 6562306a36Sopenharmony_ci }; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#undef DEFINE_CUSTOM_EVENT 6862306a36Sopenharmony_ci#define DEFINE_CUSTOM_EVENT(template, name, proto, args) 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci/* Stage 3 create the way to print the custom event */ 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#include "stages/stage3_trace_output.h" 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#undef DECLARE_CUSTOM_EVENT_CLASS 7762306a36Sopenharmony_ci#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 7862306a36Sopenharmony_cistatic notrace enum print_line_t \ 7962306a36Sopenharmony_citrace_custom_raw_output_##call(struct trace_iterator *iter, int flags, \ 8062306a36Sopenharmony_ci struct trace_event *trace_event) \ 8162306a36Sopenharmony_ci{ \ 8262306a36Sopenharmony_ci struct trace_seq *s = &iter->seq; \ 8362306a36Sopenharmony_ci struct trace_seq __maybe_unused *p = &iter->tmp_seq; \ 8462306a36Sopenharmony_ci struct trace_custom_event_raw_##call *field; \ 8562306a36Sopenharmony_ci int ret; \ 8662306a36Sopenharmony_ci \ 8762306a36Sopenharmony_ci field = (typeof(field))iter->ent; \ 8862306a36Sopenharmony_ci \ 8962306a36Sopenharmony_ci ret = trace_raw_output_prep(iter, trace_event); \ 9062306a36Sopenharmony_ci if (ret != TRACE_TYPE_HANDLED) \ 9162306a36Sopenharmony_ci return ret; \ 9262306a36Sopenharmony_ci \ 9362306a36Sopenharmony_ci trace_event_printf(iter, print); \ 9462306a36Sopenharmony_ci \ 9562306a36Sopenharmony_ci return trace_handle_return(s); \ 9662306a36Sopenharmony_ci} \ 9762306a36Sopenharmony_cistatic struct trace_event_functions trace_custom_event_type_funcs_##call = { \ 9862306a36Sopenharmony_ci .trace = trace_custom_raw_output_##call, \ 9962306a36Sopenharmony_ci}; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/* Stage 4 creates the offset layout for the fields */ 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci#include "stages/stage4_event_fields.h" 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#undef DECLARE_CUSTOM_EVENT_CLASS 10862306a36Sopenharmony_ci#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print) \ 10962306a36Sopenharmony_cistatic struct trace_event_fields trace_custom_event_fields_##call[] = { \ 11062306a36Sopenharmony_ci tstruct \ 11162306a36Sopenharmony_ci {} }; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* Stage 5 creates the helper function for dynamic fields */ 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#include "stages/stage5_get_offsets.h" 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci#undef DECLARE_CUSTOM_EVENT_CLASS 12062306a36Sopenharmony_ci#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 12162306a36Sopenharmony_cistatic inline notrace int trace_custom_event_get_offsets_##call( \ 12262306a36Sopenharmony_ci struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \ 12362306a36Sopenharmony_ci{ \ 12462306a36Sopenharmony_ci int __data_size = 0; \ 12562306a36Sopenharmony_ci int __maybe_unused __item_length; \ 12662306a36Sopenharmony_ci struct trace_custom_event_raw_##call __maybe_unused *entry; \ 12762306a36Sopenharmony_ci \ 12862306a36Sopenharmony_ci tstruct; \ 12962306a36Sopenharmony_ci \ 13062306a36Sopenharmony_ci return __data_size; \ 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci/* Stage 6 creates the probe function that records the event */ 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#include "stages/stage6_event_callback.h" 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci#undef DECLARE_CUSTOM_EVENT_CLASS 14062306a36Sopenharmony_ci#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 14162306a36Sopenharmony_ci \ 14262306a36Sopenharmony_cistatic notrace void \ 14362306a36Sopenharmony_citrace_custom_event_raw_event_##call(void *__data, proto) \ 14462306a36Sopenharmony_ci{ \ 14562306a36Sopenharmony_ci struct trace_event_file *trace_file = __data; \ 14662306a36Sopenharmony_ci struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \ 14762306a36Sopenharmony_ci struct trace_event_buffer fbuffer; \ 14862306a36Sopenharmony_ci struct trace_custom_event_raw_##call *entry; \ 14962306a36Sopenharmony_ci int __data_size; \ 15062306a36Sopenharmony_ci \ 15162306a36Sopenharmony_ci if (trace_trigger_soft_disabled(trace_file)) \ 15262306a36Sopenharmony_ci return; \ 15362306a36Sopenharmony_ci \ 15462306a36Sopenharmony_ci __data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \ 15562306a36Sopenharmony_ci \ 15662306a36Sopenharmony_ci entry = trace_event_buffer_reserve(&fbuffer, trace_file, \ 15762306a36Sopenharmony_ci sizeof(*entry) + __data_size); \ 15862306a36Sopenharmony_ci \ 15962306a36Sopenharmony_ci if (!entry) \ 16062306a36Sopenharmony_ci return; \ 16162306a36Sopenharmony_ci \ 16262306a36Sopenharmony_ci tstruct \ 16362306a36Sopenharmony_ci \ 16462306a36Sopenharmony_ci { assign; } \ 16562306a36Sopenharmony_ci \ 16662306a36Sopenharmony_ci trace_event_buffer_commit(&fbuffer); \ 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci/* 16962306a36Sopenharmony_ci * The ftrace_test_custom_probe is compiled out, it is only here as a build time check 17062306a36Sopenharmony_ci * to make sure that if the tracepoint handling changes, the ftrace probe will 17162306a36Sopenharmony_ci * fail to compile unless it too is updated. 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci#undef DEFINE_CUSTOM_EVENT 17562306a36Sopenharmony_ci#define DEFINE_CUSTOM_EVENT(template, call, proto, args) \ 17662306a36Sopenharmony_cistatic inline void ftrace_test_custom_probe_##call(void) \ 17762306a36Sopenharmony_ci{ \ 17862306a36Sopenharmony_ci check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \ 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/* Stage 7 creates the actual class and event structure for the custom event */ 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#include "stages/stage7_class_define.h" 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci#undef DECLARE_CUSTOM_EVENT_CLASS 18862306a36Sopenharmony_ci#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 18962306a36Sopenharmony_cistatic char custom_print_fmt_##call[] = print; \ 19062306a36Sopenharmony_cistatic struct trace_event_class __used __refdata custom_event_class_##call = { \ 19162306a36Sopenharmony_ci .system = TRACE_SYSTEM_STRING, \ 19262306a36Sopenharmony_ci .fields_array = trace_custom_event_fields_##call, \ 19362306a36Sopenharmony_ci .fields = LIST_HEAD_INIT(custom_event_class_##call.fields),\ 19462306a36Sopenharmony_ci .raw_init = trace_event_raw_init, \ 19562306a36Sopenharmony_ci .probe = trace_custom_event_raw_event_##call, \ 19662306a36Sopenharmony_ci .reg = trace_event_reg, \ 19762306a36Sopenharmony_ci}; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci#undef DEFINE_CUSTOM_EVENT 20062306a36Sopenharmony_ci#define DEFINE_CUSTOM_EVENT(template, call, proto, args) \ 20162306a36Sopenharmony_ci \ 20262306a36Sopenharmony_cistatic struct trace_event_call __used custom_event_##call = { \ 20362306a36Sopenharmony_ci .name = #call, \ 20462306a36Sopenharmony_ci .class = &custom_event_class_##template, \ 20562306a36Sopenharmony_ci .event.funcs = &trace_custom_event_type_funcs_##template, \ 20662306a36Sopenharmony_ci .print_fmt = custom_print_fmt_##template, \ 20762306a36Sopenharmony_ci .flags = TRACE_EVENT_FL_CUSTOM, \ 20862306a36Sopenharmony_ci}; \ 20962306a36Sopenharmony_cistatic inline int trace_custom_event_##call##_update(struct tracepoint *tp) \ 21062306a36Sopenharmony_ci{ \ 21162306a36Sopenharmony_ci if (tp->name && strcmp(tp->name, #call) == 0) { \ 21262306a36Sopenharmony_ci custom_event_##call.tp = tp; \ 21362306a36Sopenharmony_ci custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT; \ 21462306a36Sopenharmony_ci return 1; \ 21562306a36Sopenharmony_ci } \ 21662306a36Sopenharmony_ci return 0; \ 21762306a36Sopenharmony_ci} \ 21862306a36Sopenharmony_cistatic struct trace_event_call __used \ 21962306a36Sopenharmony_ci__section("_ftrace_events") *__custom_event_##call = &custom_event_##call 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 222