]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - include/linux/static_call.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_STATIC_CALL_H
3 #define _LINUX_STATIC_CALL_H
8 * Static calls use code patching to hard-code function pointers into direct
9 * branch instructions. They give the flexibility of function pointers, but
10 * with improved performance. This is especially important for cases where
11 * retpolines would otherwise be used, as retpolines can significantly impact
17 * DECLARE_STATIC_CALL(name, func);
18 * DEFINE_STATIC_CALL(name, func);
19 * static_call(name)(args...);
20 * static_call_update(name, func);
24 * # Start with the following functions (with identical prototypes):
25 * int func_a(int arg1, int arg2);
26 * int func_b(int arg1, int arg2);
28 * # Define a 'my_name' reference, associated with func_a() by default
29 * DEFINE_STATIC_CALL(my_name, func_a);
32 * static_call(my_name)(arg1, arg2);
34 * # Update 'my_name' to point to func_b()
35 * static_call_update(my_name, &func_b);
38 * static_call(my_name)(arg1, arg2);
41 * Implementation details:
43 * This requires some arch-specific code (CONFIG_HAVE_STATIC_CALL).
44 * Otherwise basic indirect calls are used (with function pointers).
46 * Each static_call() site calls into a trampoline associated with the name.
47 * The trampoline has a direct branch to the default function. Updates to a
48 * name will modify the trampoline's branch destination.
50 * If the arch has CONFIG_HAVE_STATIC_CALL_INLINE, then the call sites
51 * themselves will be patched at runtime to call the functions directly,
52 * rather than calling through the trampoline. This requires objtool or a
53 * compiler plugin to detect all the static_call() sites and annotate them
54 * in the .static_call_sites section.
57 #include <linux/types.h>
58 #include <linux/cpu.h>
59 #include <linux/static_call_types.h>
61 #ifdef CONFIG_HAVE_STATIC_CALL
62 #include <asm/static_call.h>
65 * Either @site or @tramp can be NULL.
67 extern void arch_static_call_transform(void *site
, void *tramp
, void *func
);
69 #define STATIC_CALL_TRAMP_ADDR(name) &STATIC_CALL_TRAMP(name)
72 * __ADDRESSABLE() is used to ensure the key symbol doesn't get stripped from
73 * the symbol table so that objtool can reference it when it generates the
74 * .static_call_sites section.
76 #define __static_call(name) \
78 __ADDRESSABLE(STATIC_CALL_KEY(name)); \
79 &STATIC_CALL_TRAMP(name); \
83 #define STATIC_CALL_TRAMP_ADDR(name) NULL
87 #define DECLARE_STATIC_CALL(name, func) \
88 extern struct static_call_key STATIC_CALL_KEY(name); \
89 extern typeof(func) STATIC_CALL_TRAMP(name);
91 #define static_call_update(name, func) \
93 BUILD_BUG_ON(!__same_type(*(func), STATIC_CALL_TRAMP(name))); \
94 __static_call_update(&STATIC_CALL_KEY(name), \
95 STATIC_CALL_TRAMP_ADDR(name), func); \
98 #ifdef CONFIG_HAVE_STATIC_CALL_INLINE
100 struct static_call_mod
{
101 struct static_call_mod
*next
;
102 struct module
*mod
; /* for vmlinux, mod == NULL */
103 struct static_call_site
*sites
;
106 struct static_call_key
{
108 struct static_call_mod
*mods
;
111 extern void __static_call_update(struct static_call_key
*key
, void *tramp
, void *func
);
112 extern int static_call_mod_init(struct module
*mod
);
114 #define DEFINE_STATIC_CALL(name, _func) \
115 DECLARE_STATIC_CALL(name, _func); \
116 struct static_call_key STATIC_CALL_KEY(name) = { \
120 ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
122 #define static_call(name) __static_call(name)
124 #define EXPORT_STATIC_CALL(name) \
125 EXPORT_SYMBOL(STATIC_CALL_KEY(name)); \
126 EXPORT_SYMBOL(STATIC_CALL_TRAMP(name))
128 #define EXPORT_STATIC_CALL_GPL(name) \
129 EXPORT_SYMBOL_GPL(STATIC_CALL_KEY(name)); \
130 EXPORT_SYMBOL_GPL(STATIC_CALL_TRAMP(name))
132 #elif defined(CONFIG_HAVE_STATIC_CALL)
134 struct static_call_key
{
138 #define DEFINE_STATIC_CALL(name, _func) \
139 DECLARE_STATIC_CALL(name, _func); \
140 struct static_call_key STATIC_CALL_KEY(name) = { \
143 ARCH_DEFINE_STATIC_CALL_TRAMP(name, _func)
145 #define static_call(name) __static_call(name)
148 void __static_call_update(struct static_call_key
*key
, void *tramp
, void *func
)
151 WRITE_ONCE(key
->func
, func
);
152 arch_static_call_transform(NULL
, tramp
, func
);
156 #define EXPORT_STATIC_CALL(name) \
157 EXPORT_SYMBOL(STATIC_CALL_KEY(name)); \
158 EXPORT_SYMBOL(STATIC_CALL_TRAMP(name))
160 #define EXPORT_STATIC_CALL_GPL(name) \
161 EXPORT_SYMBOL_GPL(STATIC_CALL_KEY(name)); \
162 EXPORT_SYMBOL_GPL(STATIC_CALL_TRAMP(name))
164 #else /* Generic implementation */
166 struct static_call_key
{
170 #define DEFINE_STATIC_CALL(name, _func) \
171 DECLARE_STATIC_CALL(name, _func); \
172 struct static_call_key STATIC_CALL_KEY(name) = { \
176 #define static_call(name) \
177 ((typeof(STATIC_CALL_TRAMP(name))*)(STATIC_CALL_KEY(name).func))
180 void __static_call_update(struct static_call_key
*key
, void *tramp
, void *func
)
182 WRITE_ONCE(key
->func
, func
);
185 #define EXPORT_STATIC_CALL(name) EXPORT_SYMBOL(STATIC_CALL_KEY(name))
186 #define EXPORT_STATIC_CALL_GPL(name) EXPORT_SYMBOL_GPL(STATIC_CALL_KEY(name))
188 #endif /* CONFIG_HAVE_STATIC_CALL */
190 #endif /* _LINUX_STATIC_CALL_H */