aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'include/trace/hooks/vendor_hooks.h')
-rw-r--r--include/trace/hooks/vendor_hooks.h104
1 files changed, 104 insertions, 0 deletions
diff --git a/include/trace/hooks/vendor_hooks.h b/include/trace/hooks/vendor_hooks.h
new file mode 100644
index 000000000000..e6cabd366eeb
--- /dev/null
+++ b/include/trace/hooks/vendor_hooks.h
@@ -0,0 +1,104 @@
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#include <linux/tracepoint.h>
11
12#define DECLARE_HOOK DECLARE_TRACE
13
14#ifdef TRACE_HEADER_MULTI_READ
15
16#define DEFINE_HOOK_FN(_name, _reg, _unreg, proto, args) \
17 static const char __tpstrtab_##_name[] \
18 __section("__tracepoints_strings") = #_name; \
19 extern struct static_call_key STATIC_CALL_KEY(tp_func_##_name); \
20 int __traceiter_##_name(void *__data, proto); \
21 struct tracepoint __tracepoint_##_name __used \
22 __section("__tracepoints") = { \
23 .name = __tpstrtab_##_name, \
24 .key = STATIC_KEY_INIT_FALSE, \
25 .static_call_key = &STATIC_CALL_KEY(tp_func_##_name), \
26 .static_call_tramp = STATIC_CALL_TRAMP_ADDR(tp_func_##_name), \
27 .iterator = &__traceiter_##_name, \
28 .regfunc = _reg, \
29 .unregfunc = _unreg, \
30 .funcs = NULL }; \
31 __TRACEPOINT_ENTRY(_name); \
32 int __traceiter_##_name(void *__data, proto) \
33 { \
34 struct tracepoint_func *it_func_ptr; \
35 void *it_func; \
36 \
37 it_func_ptr = (&__tracepoint_##_name)->funcs; \
38 it_func = (it_func_ptr)->func; \
39 __data = (it_func_ptr)->data; \
40 ((void(*)(void *, proto))(it_func))(__data, args); \
41 WARN_ON(((++it_func_ptr)->func)); \
42 return 0; \
43 } \
44 DEFINE_STATIC_CALL(tp_func_##_name, __traceiter_##_name);
45
46#undef DECLARE_RESTRICTED_HOOK
47#define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \
48 DEFINE_HOOK_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args))
49
50/* prevent additional recursion */
51#undef TRACE_HEADER_MULTI_READ
52#else /* TRACE_HEADER_MULTI_READ */
53
54#define DO_HOOK(name, proto, args, cond) \
55 do { \
56 struct tracepoint_func *it_func_ptr; \
57 void *__data; \
58 \
59 if (!(cond)) \
60 return; \
61 \
62 it_func_ptr = (&__tracepoint_##name)->funcs; \
63 if (it_func_ptr) { \
64 __data = (it_func_ptr)->data; \
65 __DO_TRACE_CALL(name)(args); \
66 } \
67 } while (0)
68
69#define __DECLARE_HOOK(name, proto, args, cond, data_proto, data_args) \
70 extern int __traceiter_##name(data_proto); \
71 DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \
72 extern struct tracepoint __tracepoint_##name; \
73 static inline void trace_##name(proto) \
74 { \
75 if (static_key_false(&__tracepoint_##name.key)) \
76 DO_HOOK(name, \
77 TP_PROTO(data_proto), \
78 TP_ARGS(data_args), \
79 TP_CONDITION(cond)); \
80 } \
81 static inline bool \
82 trace_##name##_enabled(void) \
83 { \
84 return static_key_false(&__tracepoint_##name.key); \
85 } \
86 static inline int \
87 register_trace_##name(void (*probe)(data_proto), void *data) \
88 { \
89 /* only allow a single attachment */ \
90 if (trace_##name##_enabled()) \
91 return -EBUSY; \
92 return tracepoint_probe_register(&__tracepoint_##name, \
93 (void *)probe, data); \
94 } \
95 /* vendor hooks cannot be unregistered */ \
96
97#undef DECLARE_RESTRICTED_HOOK
98#define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \
99 __DECLARE_HOOK(name, PARAMS(proto), PARAMS(args), \
100 cond, \
101 PARAMS(void *__data, proto), \
102 PARAMS(__data, args))
103
104#endif /* TRACE_HEADER_MULTI_READ */