1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun /* 4*4882a593Smuzhiyun * Note: we intentionally omit include file ifdef protection 5*4882a593Smuzhiyun * This is due to the way trace events work. If a file includes two 6*4882a593Smuzhiyun * trace event headers under one "CREATE_TRACE_POINTS" the first include 7*4882a593Smuzhiyun * will override the DECLARE_RESTRICTED_HOOK and break the second include. 8*4882a593Smuzhiyun */ 9*4882a593Smuzhiyun 10*4882a593Smuzhiyun #ifndef __GENKSYMS__ 11*4882a593Smuzhiyun #include <linux/tracepoint.h> 12*4882a593Smuzhiyun #endif 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun #if defined(CONFIG_TRACEPOINTS) && defined(CONFIG_ANDROID_VENDOR_HOOKS) 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun #define DECLARE_HOOK DECLARE_TRACE 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun int android_rvh_probe_register(struct tracepoint *tp, void *probe, void *data); 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun #ifdef TRACE_HEADER_MULTI_READ 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun #define DEFINE_HOOK_FN(_name, _reg, _unreg, proto, args) \ 23*4882a593Smuzhiyun static const char __tpstrtab_##_name[] \ 24*4882a593Smuzhiyun __section("__tracepoints_strings") = #_name; \ 25*4882a593Smuzhiyun extern struct static_call_key STATIC_CALL_KEY(tp_func_##_name); \ 26*4882a593Smuzhiyun int __traceiter_##_name(void *__data, proto); \ 27*4882a593Smuzhiyun struct tracepoint __tracepoint_##_name __used \ 28*4882a593Smuzhiyun __section("__tracepoints") = { \ 29*4882a593Smuzhiyun .name = __tpstrtab_##_name, \ 30*4882a593Smuzhiyun .key = STATIC_KEY_INIT_FALSE, \ 31*4882a593Smuzhiyun .static_call_key = &STATIC_CALL_KEY(tp_func_##_name), \ 32*4882a593Smuzhiyun .static_call_tramp = STATIC_CALL_TRAMP_ADDR(tp_func_##_name), \ 33*4882a593Smuzhiyun .iterator = &__traceiter_##_name, \ 34*4882a593Smuzhiyun .regfunc = _reg, \ 35*4882a593Smuzhiyun .unregfunc = _unreg, \ 36*4882a593Smuzhiyun .funcs = NULL }; \ 37*4882a593Smuzhiyun __TRACEPOINT_ENTRY(_name); \ 38*4882a593Smuzhiyun int __nocfi __traceiter_##_name(void *__data, proto) \ 39*4882a593Smuzhiyun { \ 40*4882a593Smuzhiyun struct tracepoint_func *it_func_ptr; \ 41*4882a593Smuzhiyun void *it_func; \ 42*4882a593Smuzhiyun \ 43*4882a593Smuzhiyun it_func_ptr = (&__tracepoint_##_name)->funcs; \ 44*4882a593Smuzhiyun it_func = (it_func_ptr)->func; \ 45*4882a593Smuzhiyun do { \ 46*4882a593Smuzhiyun __data = (it_func_ptr)->data; \ 47*4882a593Smuzhiyun ((void(*)(void *, proto))(it_func))(__data, args); \ 48*4882a593Smuzhiyun it_func = READ_ONCE((++it_func_ptr)->func); \ 49*4882a593Smuzhiyun } while (it_func); \ 50*4882a593Smuzhiyun return 0; \ 51*4882a593Smuzhiyun } \ 52*4882a593Smuzhiyun DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name); 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun #undef DECLARE_RESTRICTED_HOOK 55*4882a593Smuzhiyun #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \ 56*4882a593Smuzhiyun DEFINE_HOOK_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args)) 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun /* prevent additional recursion */ 59*4882a593Smuzhiyun #undef TRACE_HEADER_MULTI_READ 60*4882a593Smuzhiyun #else /* TRACE_HEADER_MULTI_READ */ 61*4882a593Smuzhiyun 62*4882a593Smuzhiyun #define DO_HOOK(name, proto, args, cond) \ 63*4882a593Smuzhiyun do { \ 64*4882a593Smuzhiyun struct tracepoint_func *it_func_ptr; \ 65*4882a593Smuzhiyun void *__data; \ 66*4882a593Smuzhiyun \ 67*4882a593Smuzhiyun if (!(cond)) \ 68*4882a593Smuzhiyun return; \ 69*4882a593Smuzhiyun \ 70*4882a593Smuzhiyun it_func_ptr = (&__tracepoint_##name)->funcs; \ 71*4882a593Smuzhiyun if (it_func_ptr) { \ 72*4882a593Smuzhiyun __data = (it_func_ptr)->data; \ 73*4882a593Smuzhiyun __DO_TRACE_CALL(name)(args); \ 74*4882a593Smuzhiyun } \ 75*4882a593Smuzhiyun } while (0) 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun #define __DECLARE_HOOK(name, proto, args, cond, data_proto, data_args) \ 78*4882a593Smuzhiyun extern int __traceiter_##name(data_proto); \ 79*4882a593Smuzhiyun DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \ 80*4882a593Smuzhiyun extern struct tracepoint __tracepoint_##name; \ 81*4882a593Smuzhiyun static inline void __nocfi trace_##name(proto) \ 82*4882a593Smuzhiyun { \ 83*4882a593Smuzhiyun if (static_key_false(&__tracepoint_##name.key)) \ 84*4882a593Smuzhiyun DO_HOOK(name, \ 85*4882a593Smuzhiyun TP_PROTO(data_proto), \ 86*4882a593Smuzhiyun TP_ARGS(data_args), \ 87*4882a593Smuzhiyun TP_CONDITION(cond)); \ 88*4882a593Smuzhiyun } \ 89*4882a593Smuzhiyun static inline bool \ 90*4882a593Smuzhiyun trace_##name##_enabled(void) \ 91*4882a593Smuzhiyun { \ 92*4882a593Smuzhiyun return static_key_false(&__tracepoint_##name.key); \ 93*4882a593Smuzhiyun } \ 94*4882a593Smuzhiyun static inline int \ 95*4882a593Smuzhiyun register_trace_##name(void (*probe)(data_proto), void *data) \ 96*4882a593Smuzhiyun { \ 97*4882a593Smuzhiyun return android_rvh_probe_register(&__tracepoint_##name, \ 98*4882a593Smuzhiyun (void *)probe, data); \ 99*4882a593Smuzhiyun } \ 100*4882a593Smuzhiyun /* vendor hooks cannot be unregistered */ \ 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun #undef DECLARE_RESTRICTED_HOOK 103*4882a593Smuzhiyun #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \ 104*4882a593Smuzhiyun __DECLARE_HOOK(name, PARAMS(proto), PARAMS(args), \ 105*4882a593Smuzhiyun cond, \ 106*4882a593Smuzhiyun PARAMS(void *__data, proto), \ 107*4882a593Smuzhiyun PARAMS(__data, args)) 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun #endif /* TRACE_HEADER_MULTI_READ */ 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun #else /* !CONFIG_TRACEPOINTS || !CONFIG_ANDROID_VENDOR_HOOKS */ 112*4882a593Smuzhiyun /* suppress trace hooks */ 113*4882a593Smuzhiyun #define DECLARE_HOOK DECLARE_EVENT_NOP 114*4882a593Smuzhiyun #define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \ 115*4882a593Smuzhiyun DECLARE_EVENT_NOP(name, PARAMS(proto), PARAMS(args)) 116*4882a593Smuzhiyun #endif 117