1115284d8SJosh Poimboeuf /* SPDX-License-Identifier: GPL-2.0 */ 2115284d8SJosh Poimboeuf #ifndef _STATIC_CALL_TYPES_H 3115284d8SJosh Poimboeuf #define _STATIC_CALL_TYPES_H 4115284d8SJosh Poimboeuf 59183c3f9SJosh Poimboeuf #include <linux/types.h> 6115284d8SJosh Poimboeuf #include <linux/stringify.h> 7880cfed3SPeter Zijlstra #include <linux/compiler.h> 8115284d8SJosh Poimboeuf 9115284d8SJosh Poimboeuf #define STATIC_CALL_KEY_PREFIX __SCK__ 109183c3f9SJosh Poimboeuf #define STATIC_CALL_KEY_PREFIX_STR __stringify(STATIC_CALL_KEY_PREFIX) 119183c3f9SJosh Poimboeuf #define STATIC_CALL_KEY_PREFIX_LEN (sizeof(STATIC_CALL_KEY_PREFIX_STR) - 1) 12115284d8SJosh Poimboeuf #define STATIC_CALL_KEY(name) __PASTE(STATIC_CALL_KEY_PREFIX, name) 1373f44fe1SJosh Poimboeuf #define STATIC_CALL_KEY_STR(name) __stringify(STATIC_CALL_KEY(name)) 14115284d8SJosh Poimboeuf 15115284d8SJosh Poimboeuf #define STATIC_CALL_TRAMP_PREFIX __SCT__ 16115284d8SJosh Poimboeuf #define STATIC_CALL_TRAMP_PREFIX_STR __stringify(STATIC_CALL_TRAMP_PREFIX) 179183c3f9SJosh Poimboeuf #define STATIC_CALL_TRAMP_PREFIX_LEN (sizeof(STATIC_CALL_TRAMP_PREFIX_STR) - 1) 18115284d8SJosh Poimboeuf #define STATIC_CALL_TRAMP(name) __PASTE(STATIC_CALL_TRAMP_PREFIX, name) 19115284d8SJosh Poimboeuf #define STATIC_CALL_TRAMP_STR(name) __stringify(STATIC_CALL_TRAMP(name)) 20115284d8SJosh Poimboeuf 219183c3f9SJosh Poimboeuf /* 225b06fd3bSPeter Zijlstra * Flags in the low bits of static_call_site::key. 235b06fd3bSPeter Zijlstra */ 245b06fd3bSPeter Zijlstra #define STATIC_CALL_SITE_TAIL 1UL /* tail call */ 255b06fd3bSPeter Zijlstra #define STATIC_CALL_SITE_INIT 2UL /* init section */ 265b06fd3bSPeter Zijlstra #define STATIC_CALL_SITE_FLAGS 3UL 275b06fd3bSPeter Zijlstra 285b06fd3bSPeter Zijlstra /* 299183c3f9SJosh Poimboeuf * The static call site table needs to be created by external tooling (objtool 309183c3f9SJosh Poimboeuf * or a compiler plugin). 319183c3f9SJosh Poimboeuf */ 329183c3f9SJosh Poimboeuf struct static_call_site { 339183c3f9SJosh Poimboeuf s32 addr; 349183c3f9SJosh Poimboeuf s32 key; 359183c3f9SJosh Poimboeuf }; 369183c3f9SJosh Poimboeuf 37880cfed3SPeter Zijlstra #define DECLARE_STATIC_CALL(name, func) \ 38880cfed3SPeter Zijlstra extern struct static_call_key STATIC_CALL_KEY(name); \ 39880cfed3SPeter Zijlstra extern typeof(func) STATIC_CALL_TRAMP(name); 40880cfed3SPeter Zijlstra 41880cfed3SPeter Zijlstra #ifdef CONFIG_HAVE_STATIC_CALL 42880cfed3SPeter Zijlstra 4373f44fe1SJosh Poimboeuf #define __raw_static_call(name) (&STATIC_CALL_TRAMP(name)) 4473f44fe1SJosh Poimboeuf 4573f44fe1SJosh Poimboeuf #ifdef CONFIG_HAVE_STATIC_CALL_INLINE 4673f44fe1SJosh Poimboeuf 47880cfed3SPeter Zijlstra /* 48880cfed3SPeter Zijlstra * __ADDRESSABLE() is used to ensure the key symbol doesn't get stripped from 49880cfed3SPeter Zijlstra * the symbol table so that objtool can reference it when it generates the 50880cfed3SPeter Zijlstra * .static_call_sites section. 51880cfed3SPeter Zijlstra */ 5273f44fe1SJosh Poimboeuf #define __STATIC_CALL_ADDRESSABLE(name) \ 5373f44fe1SJosh Poimboeuf __ADDRESSABLE(STATIC_CALL_KEY(name)) 5473f44fe1SJosh Poimboeuf 55880cfed3SPeter Zijlstra #define __static_call(name) \ 56880cfed3SPeter Zijlstra ({ \ 5773f44fe1SJosh Poimboeuf __STATIC_CALL_ADDRESSABLE(name); \ 5873f44fe1SJosh Poimboeuf __raw_static_call(name); \ 59880cfed3SPeter Zijlstra }) 60880cfed3SPeter Zijlstra 61*b0466648SJuergen Gross struct static_call_key { 62*b0466648SJuergen Gross void *func; 63*b0466648SJuergen Gross union { 64*b0466648SJuergen Gross /* bit 0: 0 = mods, 1 = sites */ 65*b0466648SJuergen Gross unsigned long type; 66*b0466648SJuergen Gross struct static_call_mod *mods; 67*b0466648SJuergen Gross struct static_call_site *sites; 68*b0466648SJuergen Gross }; 69*b0466648SJuergen Gross }; 70*b0466648SJuergen Gross 7173f44fe1SJosh Poimboeuf #else /* !CONFIG_HAVE_STATIC_CALL_INLINE */ 7273f44fe1SJosh Poimboeuf 7373f44fe1SJosh Poimboeuf #define __STATIC_CALL_ADDRESSABLE(name) 7473f44fe1SJosh Poimboeuf #define __static_call(name) __raw_static_call(name) 7573f44fe1SJosh Poimboeuf 76*b0466648SJuergen Gross struct static_call_key { 77*b0466648SJuergen Gross void *func; 78*b0466648SJuergen Gross }; 79*b0466648SJuergen Gross 8073f44fe1SJosh Poimboeuf #endif /* CONFIG_HAVE_STATIC_CALL_INLINE */ 8173f44fe1SJosh Poimboeuf 8273f44fe1SJosh Poimboeuf #ifdef MODULE 8373f44fe1SJosh Poimboeuf #define __STATIC_CALL_MOD_ADDRESSABLE(name) 8473f44fe1SJosh Poimboeuf #define static_call_mod(name) __raw_static_call(name) 8573f44fe1SJosh Poimboeuf #else 8673f44fe1SJosh Poimboeuf #define __STATIC_CALL_MOD_ADDRESSABLE(name) __STATIC_CALL_ADDRESSABLE(name) 8773f44fe1SJosh Poimboeuf #define static_call_mod(name) __static_call(name) 8873f44fe1SJosh Poimboeuf #endif 8973f44fe1SJosh Poimboeuf 90880cfed3SPeter Zijlstra #define static_call(name) __static_call(name) 91880cfed3SPeter Zijlstra 92880cfed3SPeter Zijlstra #else 93880cfed3SPeter Zijlstra 94*b0466648SJuergen Gross struct static_call_key { 95*b0466648SJuergen Gross void *func; 96*b0466648SJuergen Gross }; 97*b0466648SJuergen Gross 98880cfed3SPeter Zijlstra #define static_call(name) \ 99880cfed3SPeter Zijlstra ((typeof(STATIC_CALL_TRAMP(name))*)(STATIC_CALL_KEY(name).func)) 100880cfed3SPeter Zijlstra 101880cfed3SPeter Zijlstra #endif /* CONFIG_HAVE_STATIC_CALL */ 102880cfed3SPeter Zijlstra 103115284d8SJosh Poimboeuf #endif /* _STATIC_CALL_TYPES_H */ 104