1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _STATIC_CALL_TYPES_H 3 #define _STATIC_CALL_TYPES_H 4 5 #include <linux/types.h> 6 #include <linux/stringify.h> 7 #include <linux/compiler.h> 8 9 #define STATIC_CALL_KEY_PREFIX __SCK__ 10 #define STATIC_CALL_KEY_PREFIX_STR __stringify(STATIC_CALL_KEY_PREFIX) 11 #define STATIC_CALL_KEY_PREFIX_LEN (sizeof(STATIC_CALL_KEY_PREFIX_STR) - 1) 12 #define STATIC_CALL_KEY(name) __PASTE(STATIC_CALL_KEY_PREFIX, name) 13 #define STATIC_CALL_KEY_STR(name) __stringify(STATIC_CALL_KEY(name)) 14 15 #define STATIC_CALL_TRAMP_PREFIX __SCT__ 16 #define STATIC_CALL_TRAMP_PREFIX_STR __stringify(STATIC_CALL_TRAMP_PREFIX) 17 #define STATIC_CALL_TRAMP_PREFIX_LEN (sizeof(STATIC_CALL_TRAMP_PREFIX_STR) - 1) 18 #define STATIC_CALL_TRAMP(name) __PASTE(STATIC_CALL_TRAMP_PREFIX, name) 19 #define STATIC_CALL_TRAMP_STR(name) __stringify(STATIC_CALL_TRAMP(name)) 20 21 /* 22 * Flags in the low bits of static_call_site::key. 23 */ 24 #define STATIC_CALL_SITE_TAIL 1UL /* tail call */ 25 #define STATIC_CALL_SITE_INIT 2UL /* init section */ 26 #define STATIC_CALL_SITE_FLAGS 3UL 27 28 /* 29 * The static call site table needs to be created by external tooling (objtool 30 * or a compiler plugin). 31 */ 32 struct static_call_site { 33 s32 addr; 34 s32 key; 35 }; 36 37 #define DECLARE_STATIC_CALL(name, func) \ 38 extern struct static_call_key STATIC_CALL_KEY(name); \ 39 extern typeof(func) STATIC_CALL_TRAMP(name); 40 41 #ifdef CONFIG_HAVE_STATIC_CALL 42 43 #define __raw_static_call(name) (&STATIC_CALL_TRAMP(name)) 44 45 #ifdef CONFIG_HAVE_STATIC_CALL_INLINE 46 47 /* 48 * __ADDRESSABLE() is used to ensure the key symbol doesn't get stripped from 49 * the symbol table so that objtool can reference it when it generates the 50 * .static_call_sites section. 51 */ 52 #define __STATIC_CALL_ADDRESSABLE(name) \ 53 __ADDRESSABLE(STATIC_CALL_KEY(name)) 54 55 #define __static_call(name) \ 56 ({ \ 57 __STATIC_CALL_ADDRESSABLE(name); \ 58 __raw_static_call(name); \ 59 }) 60 61 struct static_call_key { 62 void *func; 63 union { 64 /* bit 0: 0 = mods, 1 = sites */ 65 unsigned long type; 66 struct static_call_mod *mods; 67 struct static_call_site *sites; 68 }; 69 }; 70 71 #else /* !CONFIG_HAVE_STATIC_CALL_INLINE */ 72 73 #define __STATIC_CALL_ADDRESSABLE(name) 74 #define __static_call(name) __raw_static_call(name) 75 76 struct static_call_key { 77 void *func; 78 }; 79 80 #endif /* CONFIG_HAVE_STATIC_CALL_INLINE */ 81 82 #ifdef MODULE 83 #define __STATIC_CALL_MOD_ADDRESSABLE(name) 84 #define static_call_mod(name) __raw_static_call(name) 85 #else 86 #define __STATIC_CALL_MOD_ADDRESSABLE(name) __STATIC_CALL_ADDRESSABLE(name) 87 #define static_call_mod(name) __static_call(name) 88 #endif 89 90 #define static_call(name) __static_call(name) 91 92 #else 93 94 struct static_call_key { 95 void *func; 96 }; 97 98 #define static_call(name) \ 99 ((typeof(STATIC_CALL_TRAMP(name))*)(STATIC_CALL_KEY(name).func)) 100 101 #endif /* CONFIG_HAVE_STATIC_CALL */ 102 103 #endif /* _STATIC_CALL_TYPES_H */ 104