diff options
Diffstat (limited to 'include/trace/hooks/vendor_hooks.h')
-rw-r--r-- | include/trace/hooks/vendor_hooks.h | 104 |
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 */ | ||