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