1*8fd4dddaSChristophe Leroy // SPDX-License-Identifier: GPL-2.0 2*8fd4dddaSChristophe Leroy #include <linux/init.h> 3*8fd4dddaSChristophe Leroy #include <linux/static_call.h> 4*8fd4dddaSChristophe Leroy #include <linux/bug.h> 5*8fd4dddaSChristophe Leroy #include <linux/smp.h> 6*8fd4dddaSChristophe Leroy #include <linux/sort.h> 7*8fd4dddaSChristophe Leroy #include <linux/slab.h> 8*8fd4dddaSChristophe Leroy #include <linux/module.h> 9*8fd4dddaSChristophe Leroy #include <linux/cpu.h> 10*8fd4dddaSChristophe Leroy #include <linux/processor.h> 11*8fd4dddaSChristophe Leroy #include <asm/sections.h> 12*8fd4dddaSChristophe Leroy 13*8fd4dddaSChristophe Leroy extern struct static_call_site __start_static_call_sites[], 14*8fd4dddaSChristophe Leroy __stop_static_call_sites[]; 15*8fd4dddaSChristophe Leroy extern struct static_call_tramp_key __start_static_call_tramp_key[], 16*8fd4dddaSChristophe Leroy __stop_static_call_tramp_key[]; 17*8fd4dddaSChristophe Leroy 18*8fd4dddaSChristophe Leroy static bool static_call_initialized; 19*8fd4dddaSChristophe Leroy 20*8fd4dddaSChristophe Leroy /* mutex to protect key modules/sites */ 21*8fd4dddaSChristophe Leroy static DEFINE_MUTEX(static_call_mutex); 22*8fd4dddaSChristophe Leroy 23*8fd4dddaSChristophe Leroy static void static_call_lock(void) 24*8fd4dddaSChristophe Leroy { 25*8fd4dddaSChristophe Leroy mutex_lock(&static_call_mutex); 26*8fd4dddaSChristophe Leroy } 27*8fd4dddaSChristophe Leroy 28*8fd4dddaSChristophe Leroy static void static_call_unlock(void) 29*8fd4dddaSChristophe Leroy { 30*8fd4dddaSChristophe Leroy mutex_unlock(&static_call_mutex); 31*8fd4dddaSChristophe Leroy } 32*8fd4dddaSChristophe Leroy 33*8fd4dddaSChristophe Leroy static inline void *static_call_addr(struct static_call_site *site) 34*8fd4dddaSChristophe Leroy { 35*8fd4dddaSChristophe Leroy return (void *)((long)site->addr + (long)&site->addr); 36*8fd4dddaSChristophe Leroy } 37*8fd4dddaSChristophe Leroy 38*8fd4dddaSChristophe Leroy static inline unsigned long __static_call_key(const struct static_call_site *site) 39*8fd4dddaSChristophe Leroy { 40*8fd4dddaSChristophe Leroy return (long)site->key + (long)&site->key; 41*8fd4dddaSChristophe Leroy } 42*8fd4dddaSChristophe Leroy 43*8fd4dddaSChristophe Leroy static inline struct static_call_key *static_call_key(const struct static_call_site *site) 44*8fd4dddaSChristophe Leroy { 45*8fd4dddaSChristophe Leroy return (void *)(__static_call_key(site) & ~STATIC_CALL_SITE_FLAGS); 46*8fd4dddaSChristophe Leroy } 47*8fd4dddaSChristophe Leroy 48*8fd4dddaSChristophe Leroy /* These assume the key is word-aligned. */ 49*8fd4dddaSChristophe Leroy static inline bool static_call_is_init(struct static_call_site *site) 50*8fd4dddaSChristophe Leroy { 51*8fd4dddaSChristophe Leroy return __static_call_key(site) & STATIC_CALL_SITE_INIT; 52*8fd4dddaSChristophe Leroy } 53*8fd4dddaSChristophe Leroy 54*8fd4dddaSChristophe Leroy static inline bool static_call_is_tail(struct static_call_site *site) 55*8fd4dddaSChristophe Leroy { 56*8fd4dddaSChristophe Leroy return __static_call_key(site) & STATIC_CALL_SITE_TAIL; 57*8fd4dddaSChristophe Leroy } 58*8fd4dddaSChristophe Leroy 59*8fd4dddaSChristophe Leroy static inline void static_call_set_init(struct static_call_site *site) 60*8fd4dddaSChristophe Leroy { 61*8fd4dddaSChristophe Leroy site->key = (__static_call_key(site) | STATIC_CALL_SITE_INIT) - 62*8fd4dddaSChristophe Leroy (long)&site->key; 63*8fd4dddaSChristophe Leroy } 64*8fd4dddaSChristophe Leroy 65*8fd4dddaSChristophe Leroy static int static_call_site_cmp(const void *_a, const void *_b) 66*8fd4dddaSChristophe Leroy { 67*8fd4dddaSChristophe Leroy const struct static_call_site *a = _a; 68*8fd4dddaSChristophe Leroy const struct static_call_site *b = _b; 69*8fd4dddaSChristophe Leroy const struct static_call_key *key_a = static_call_key(a); 70*8fd4dddaSChristophe Leroy const struct static_call_key *key_b = static_call_key(b); 71*8fd4dddaSChristophe Leroy 72*8fd4dddaSChristophe Leroy if (key_a < key_b) 73*8fd4dddaSChristophe Leroy return -1; 74*8fd4dddaSChristophe Leroy 75*8fd4dddaSChristophe Leroy if (key_a > key_b) 76*8fd4dddaSChristophe Leroy return 1; 77*8fd4dddaSChristophe Leroy 78*8fd4dddaSChristophe Leroy return 0; 79*8fd4dddaSChristophe Leroy } 80*8fd4dddaSChristophe Leroy 81*8fd4dddaSChristophe Leroy static void static_call_site_swap(void *_a, void *_b, int size) 82*8fd4dddaSChristophe Leroy { 83*8fd4dddaSChristophe Leroy long delta = (unsigned long)_a - (unsigned long)_b; 84*8fd4dddaSChristophe Leroy struct static_call_site *a = _a; 85*8fd4dddaSChristophe Leroy struct static_call_site *b = _b; 86*8fd4dddaSChristophe Leroy struct static_call_site tmp = *a; 87*8fd4dddaSChristophe Leroy 88*8fd4dddaSChristophe Leroy a->addr = b->addr - delta; 89*8fd4dddaSChristophe Leroy a->key = b->key - delta; 90*8fd4dddaSChristophe Leroy 91*8fd4dddaSChristophe Leroy b->addr = tmp.addr + delta; 92*8fd4dddaSChristophe Leroy b->key = tmp.key + delta; 93*8fd4dddaSChristophe Leroy } 94*8fd4dddaSChristophe Leroy 95*8fd4dddaSChristophe Leroy static inline void static_call_sort_entries(struct static_call_site *start, 96*8fd4dddaSChristophe Leroy struct static_call_site *stop) 97*8fd4dddaSChristophe Leroy { 98*8fd4dddaSChristophe Leroy sort(start, stop - start, sizeof(struct static_call_site), 99*8fd4dddaSChristophe Leroy static_call_site_cmp, static_call_site_swap); 100*8fd4dddaSChristophe Leroy } 101*8fd4dddaSChristophe Leroy 102*8fd4dddaSChristophe Leroy static inline bool static_call_key_has_mods(struct static_call_key *key) 103*8fd4dddaSChristophe Leroy { 104*8fd4dddaSChristophe Leroy return !(key->type & 1); 105*8fd4dddaSChristophe Leroy } 106*8fd4dddaSChristophe Leroy 107*8fd4dddaSChristophe Leroy static inline struct static_call_mod *static_call_key_next(struct static_call_key *key) 108*8fd4dddaSChristophe Leroy { 109*8fd4dddaSChristophe Leroy if (!static_call_key_has_mods(key)) 110*8fd4dddaSChristophe Leroy return NULL; 111*8fd4dddaSChristophe Leroy 112*8fd4dddaSChristophe Leroy return key->mods; 113*8fd4dddaSChristophe Leroy } 114*8fd4dddaSChristophe Leroy 115*8fd4dddaSChristophe Leroy static inline struct static_call_site *static_call_key_sites(struct static_call_key *key) 116*8fd4dddaSChristophe Leroy { 117*8fd4dddaSChristophe Leroy if (static_call_key_has_mods(key)) 118*8fd4dddaSChristophe Leroy return NULL; 119*8fd4dddaSChristophe Leroy 120*8fd4dddaSChristophe Leroy return (struct static_call_site *)(key->type & ~1); 121*8fd4dddaSChristophe Leroy } 122*8fd4dddaSChristophe Leroy 123*8fd4dddaSChristophe Leroy void __static_call_update(struct static_call_key *key, void *tramp, void *func) 124*8fd4dddaSChristophe Leroy { 125*8fd4dddaSChristophe Leroy struct static_call_site *site, *stop; 126*8fd4dddaSChristophe Leroy struct static_call_mod *site_mod, first; 127*8fd4dddaSChristophe Leroy 128*8fd4dddaSChristophe Leroy cpus_read_lock(); 129*8fd4dddaSChristophe Leroy static_call_lock(); 130*8fd4dddaSChristophe Leroy 131*8fd4dddaSChristophe Leroy if (key->func == func) 132*8fd4dddaSChristophe Leroy goto done; 133*8fd4dddaSChristophe Leroy 134*8fd4dddaSChristophe Leroy key->func = func; 135*8fd4dddaSChristophe Leroy 136*8fd4dddaSChristophe Leroy arch_static_call_transform(NULL, tramp, func, false); 137*8fd4dddaSChristophe Leroy 138*8fd4dddaSChristophe Leroy /* 139*8fd4dddaSChristophe Leroy * If uninitialized, we'll not update the callsites, but they still 140*8fd4dddaSChristophe Leroy * point to the trampoline and we just patched that. 141*8fd4dddaSChristophe Leroy */ 142*8fd4dddaSChristophe Leroy if (WARN_ON_ONCE(!static_call_initialized)) 143*8fd4dddaSChristophe Leroy goto done; 144*8fd4dddaSChristophe Leroy 145*8fd4dddaSChristophe Leroy first = (struct static_call_mod){ 146*8fd4dddaSChristophe Leroy .next = static_call_key_next(key), 147*8fd4dddaSChristophe Leroy .mod = NULL, 148*8fd4dddaSChristophe Leroy .sites = static_call_key_sites(key), 149*8fd4dddaSChristophe Leroy }; 150*8fd4dddaSChristophe Leroy 151*8fd4dddaSChristophe Leroy for (site_mod = &first; site_mod; site_mod = site_mod->next) { 152*8fd4dddaSChristophe Leroy bool init = system_state < SYSTEM_RUNNING; 153*8fd4dddaSChristophe Leroy struct module *mod = site_mod->mod; 154*8fd4dddaSChristophe Leroy 155*8fd4dddaSChristophe Leroy if (!site_mod->sites) { 156*8fd4dddaSChristophe Leroy /* 157*8fd4dddaSChristophe Leroy * This can happen if the static call key is defined in 158*8fd4dddaSChristophe Leroy * a module which doesn't use it. 159*8fd4dddaSChristophe Leroy * 160*8fd4dddaSChristophe Leroy * It also happens in the has_mods case, where the 161*8fd4dddaSChristophe Leroy * 'first' entry has no sites associated with it. 162*8fd4dddaSChristophe Leroy */ 163*8fd4dddaSChristophe Leroy continue; 164*8fd4dddaSChristophe Leroy } 165*8fd4dddaSChristophe Leroy 166*8fd4dddaSChristophe Leroy stop = __stop_static_call_sites; 167*8fd4dddaSChristophe Leroy 168*8fd4dddaSChristophe Leroy if (mod) { 169*8fd4dddaSChristophe Leroy #ifdef CONFIG_MODULES 170*8fd4dddaSChristophe Leroy stop = mod->static_call_sites + 171*8fd4dddaSChristophe Leroy mod->num_static_call_sites; 172*8fd4dddaSChristophe Leroy init = mod->state == MODULE_STATE_COMING; 173*8fd4dddaSChristophe Leroy #endif 174*8fd4dddaSChristophe Leroy } 175*8fd4dddaSChristophe Leroy 176*8fd4dddaSChristophe Leroy for (site = site_mod->sites; 177*8fd4dddaSChristophe Leroy site < stop && static_call_key(site) == key; site++) { 178*8fd4dddaSChristophe Leroy void *site_addr = static_call_addr(site); 179*8fd4dddaSChristophe Leroy 180*8fd4dddaSChristophe Leroy if (!init && static_call_is_init(site)) 181*8fd4dddaSChristophe Leroy continue; 182*8fd4dddaSChristophe Leroy 183*8fd4dddaSChristophe Leroy if (!kernel_text_address((unsigned long)site_addr)) { 184*8fd4dddaSChristophe Leroy /* 185*8fd4dddaSChristophe Leroy * This skips patching built-in __exit, which 186*8fd4dddaSChristophe Leroy * is part of init_section_contains() but is 187*8fd4dddaSChristophe Leroy * not part of kernel_text_address(). 188*8fd4dddaSChristophe Leroy * 189*8fd4dddaSChristophe Leroy * Skipping built-in __exit is fine since it 190*8fd4dddaSChristophe Leroy * will never be executed. 191*8fd4dddaSChristophe Leroy */ 192*8fd4dddaSChristophe Leroy WARN_ONCE(!static_call_is_init(site), 193*8fd4dddaSChristophe Leroy "can't patch static call site at %pS", 194*8fd4dddaSChristophe Leroy site_addr); 195*8fd4dddaSChristophe Leroy continue; 196*8fd4dddaSChristophe Leroy } 197*8fd4dddaSChristophe Leroy 198*8fd4dddaSChristophe Leroy arch_static_call_transform(site_addr, NULL, func, 199*8fd4dddaSChristophe Leroy static_call_is_tail(site)); 200*8fd4dddaSChristophe Leroy } 201*8fd4dddaSChristophe Leroy } 202*8fd4dddaSChristophe Leroy 203*8fd4dddaSChristophe Leroy done: 204*8fd4dddaSChristophe Leroy static_call_unlock(); 205*8fd4dddaSChristophe Leroy cpus_read_unlock(); 206*8fd4dddaSChristophe Leroy } 207*8fd4dddaSChristophe Leroy EXPORT_SYMBOL_GPL(__static_call_update); 208*8fd4dddaSChristophe Leroy 209*8fd4dddaSChristophe Leroy static int __static_call_init(struct module *mod, 210*8fd4dddaSChristophe Leroy struct static_call_site *start, 211*8fd4dddaSChristophe Leroy struct static_call_site *stop) 212*8fd4dddaSChristophe Leroy { 213*8fd4dddaSChristophe Leroy struct static_call_site *site; 214*8fd4dddaSChristophe Leroy struct static_call_key *key, *prev_key = NULL; 215*8fd4dddaSChristophe Leroy struct static_call_mod *site_mod; 216*8fd4dddaSChristophe Leroy 217*8fd4dddaSChristophe Leroy if (start == stop) 218*8fd4dddaSChristophe Leroy return 0; 219*8fd4dddaSChristophe Leroy 220*8fd4dddaSChristophe Leroy static_call_sort_entries(start, stop); 221*8fd4dddaSChristophe Leroy 222*8fd4dddaSChristophe Leroy for (site = start; site < stop; site++) { 223*8fd4dddaSChristophe Leroy void *site_addr = static_call_addr(site); 224*8fd4dddaSChristophe Leroy 225*8fd4dddaSChristophe Leroy if ((mod && within_module_init((unsigned long)site_addr, mod)) || 226*8fd4dddaSChristophe Leroy (!mod && init_section_contains(site_addr, 1))) 227*8fd4dddaSChristophe Leroy static_call_set_init(site); 228*8fd4dddaSChristophe Leroy 229*8fd4dddaSChristophe Leroy key = static_call_key(site); 230*8fd4dddaSChristophe Leroy if (key != prev_key) { 231*8fd4dddaSChristophe Leroy prev_key = key; 232*8fd4dddaSChristophe Leroy 233*8fd4dddaSChristophe Leroy /* 234*8fd4dddaSChristophe Leroy * For vmlinux (!mod) avoid the allocation by storing 235*8fd4dddaSChristophe Leroy * the sites pointer in the key itself. Also see 236*8fd4dddaSChristophe Leroy * __static_call_update()'s @first. 237*8fd4dddaSChristophe Leroy * 238*8fd4dddaSChristophe Leroy * This allows architectures (eg. x86) to call 239*8fd4dddaSChristophe Leroy * static_call_init() before memory allocation works. 240*8fd4dddaSChristophe Leroy */ 241*8fd4dddaSChristophe Leroy if (!mod) { 242*8fd4dddaSChristophe Leroy key->sites = site; 243*8fd4dddaSChristophe Leroy key->type |= 1; 244*8fd4dddaSChristophe Leroy goto do_transform; 245*8fd4dddaSChristophe Leroy } 246*8fd4dddaSChristophe Leroy 247*8fd4dddaSChristophe Leroy site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL); 248*8fd4dddaSChristophe Leroy if (!site_mod) 249*8fd4dddaSChristophe Leroy return -ENOMEM; 250*8fd4dddaSChristophe Leroy 251*8fd4dddaSChristophe Leroy /* 252*8fd4dddaSChristophe Leroy * When the key has a direct sites pointer, extract 253*8fd4dddaSChristophe Leroy * that into an explicit struct static_call_mod, so we 254*8fd4dddaSChristophe Leroy * can have a list of modules. 255*8fd4dddaSChristophe Leroy */ 256*8fd4dddaSChristophe Leroy if (static_call_key_sites(key)) { 257*8fd4dddaSChristophe Leroy site_mod->mod = NULL; 258*8fd4dddaSChristophe Leroy site_mod->next = NULL; 259*8fd4dddaSChristophe Leroy site_mod->sites = static_call_key_sites(key); 260*8fd4dddaSChristophe Leroy 261*8fd4dddaSChristophe Leroy key->mods = site_mod; 262*8fd4dddaSChristophe Leroy 263*8fd4dddaSChristophe Leroy site_mod = kzalloc(sizeof(*site_mod), GFP_KERNEL); 264*8fd4dddaSChristophe Leroy if (!site_mod) 265*8fd4dddaSChristophe Leroy return -ENOMEM; 266*8fd4dddaSChristophe Leroy } 267*8fd4dddaSChristophe Leroy 268*8fd4dddaSChristophe Leroy site_mod->mod = mod; 269*8fd4dddaSChristophe Leroy site_mod->sites = site; 270*8fd4dddaSChristophe Leroy site_mod->next = static_call_key_next(key); 271*8fd4dddaSChristophe Leroy key->mods = site_mod; 272*8fd4dddaSChristophe Leroy } 273*8fd4dddaSChristophe Leroy 274*8fd4dddaSChristophe Leroy do_transform: 275*8fd4dddaSChristophe Leroy arch_static_call_transform(site_addr, NULL, key->func, 276*8fd4dddaSChristophe Leroy static_call_is_tail(site)); 277*8fd4dddaSChristophe Leroy } 278*8fd4dddaSChristophe Leroy 279*8fd4dddaSChristophe Leroy return 0; 280*8fd4dddaSChristophe Leroy } 281*8fd4dddaSChristophe Leroy 282*8fd4dddaSChristophe Leroy static int addr_conflict(struct static_call_site *site, void *start, void *end) 283*8fd4dddaSChristophe Leroy { 284*8fd4dddaSChristophe Leroy unsigned long addr = (unsigned long)static_call_addr(site); 285*8fd4dddaSChristophe Leroy 286*8fd4dddaSChristophe Leroy if (addr <= (unsigned long)end && 287*8fd4dddaSChristophe Leroy addr + CALL_INSN_SIZE > (unsigned long)start) 288*8fd4dddaSChristophe Leroy return 1; 289*8fd4dddaSChristophe Leroy 290*8fd4dddaSChristophe Leroy return 0; 291*8fd4dddaSChristophe Leroy } 292*8fd4dddaSChristophe Leroy 293*8fd4dddaSChristophe Leroy static int __static_call_text_reserved(struct static_call_site *iter_start, 294*8fd4dddaSChristophe Leroy struct static_call_site *iter_stop, 295*8fd4dddaSChristophe Leroy void *start, void *end, bool init) 296*8fd4dddaSChristophe Leroy { 297*8fd4dddaSChristophe Leroy struct static_call_site *iter = iter_start; 298*8fd4dddaSChristophe Leroy 299*8fd4dddaSChristophe Leroy while (iter < iter_stop) { 300*8fd4dddaSChristophe Leroy if (init || !static_call_is_init(iter)) { 301*8fd4dddaSChristophe Leroy if (addr_conflict(iter, start, end)) 302*8fd4dddaSChristophe Leroy return 1; 303*8fd4dddaSChristophe Leroy } 304*8fd4dddaSChristophe Leroy iter++; 305*8fd4dddaSChristophe Leroy } 306*8fd4dddaSChristophe Leroy 307*8fd4dddaSChristophe Leroy return 0; 308*8fd4dddaSChristophe Leroy } 309*8fd4dddaSChristophe Leroy 310*8fd4dddaSChristophe Leroy #ifdef CONFIG_MODULES 311*8fd4dddaSChristophe Leroy 312*8fd4dddaSChristophe Leroy static int __static_call_mod_text_reserved(void *start, void *end) 313*8fd4dddaSChristophe Leroy { 314*8fd4dddaSChristophe Leroy struct module *mod; 315*8fd4dddaSChristophe Leroy int ret; 316*8fd4dddaSChristophe Leroy 317*8fd4dddaSChristophe Leroy preempt_disable(); 318*8fd4dddaSChristophe Leroy mod = __module_text_address((unsigned long)start); 319*8fd4dddaSChristophe Leroy WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod); 320*8fd4dddaSChristophe Leroy if (!try_module_get(mod)) 321*8fd4dddaSChristophe Leroy mod = NULL; 322*8fd4dddaSChristophe Leroy preempt_enable(); 323*8fd4dddaSChristophe Leroy 324*8fd4dddaSChristophe Leroy if (!mod) 325*8fd4dddaSChristophe Leroy return 0; 326*8fd4dddaSChristophe Leroy 327*8fd4dddaSChristophe Leroy ret = __static_call_text_reserved(mod->static_call_sites, 328*8fd4dddaSChristophe Leroy mod->static_call_sites + mod->num_static_call_sites, 329*8fd4dddaSChristophe Leroy start, end, mod->state == MODULE_STATE_COMING); 330*8fd4dddaSChristophe Leroy 331*8fd4dddaSChristophe Leroy module_put(mod); 332*8fd4dddaSChristophe Leroy 333*8fd4dddaSChristophe Leroy return ret; 334*8fd4dddaSChristophe Leroy } 335*8fd4dddaSChristophe Leroy 336*8fd4dddaSChristophe Leroy static unsigned long tramp_key_lookup(unsigned long addr) 337*8fd4dddaSChristophe Leroy { 338*8fd4dddaSChristophe Leroy struct static_call_tramp_key *start = __start_static_call_tramp_key; 339*8fd4dddaSChristophe Leroy struct static_call_tramp_key *stop = __stop_static_call_tramp_key; 340*8fd4dddaSChristophe Leroy struct static_call_tramp_key *tramp_key; 341*8fd4dddaSChristophe Leroy 342*8fd4dddaSChristophe Leroy for (tramp_key = start; tramp_key != stop; tramp_key++) { 343*8fd4dddaSChristophe Leroy unsigned long tramp; 344*8fd4dddaSChristophe Leroy 345*8fd4dddaSChristophe Leroy tramp = (long)tramp_key->tramp + (long)&tramp_key->tramp; 346*8fd4dddaSChristophe Leroy if (tramp == addr) 347*8fd4dddaSChristophe Leroy return (long)tramp_key->key + (long)&tramp_key->key; 348*8fd4dddaSChristophe Leroy } 349*8fd4dddaSChristophe Leroy 350*8fd4dddaSChristophe Leroy return 0; 351*8fd4dddaSChristophe Leroy } 352*8fd4dddaSChristophe Leroy 353*8fd4dddaSChristophe Leroy static int static_call_add_module(struct module *mod) 354*8fd4dddaSChristophe Leroy { 355*8fd4dddaSChristophe Leroy struct static_call_site *start = mod->static_call_sites; 356*8fd4dddaSChristophe Leroy struct static_call_site *stop = start + mod->num_static_call_sites; 357*8fd4dddaSChristophe Leroy struct static_call_site *site; 358*8fd4dddaSChristophe Leroy 359*8fd4dddaSChristophe Leroy for (site = start; site != stop; site++) { 360*8fd4dddaSChristophe Leroy unsigned long s_key = __static_call_key(site); 361*8fd4dddaSChristophe Leroy unsigned long addr = s_key & ~STATIC_CALL_SITE_FLAGS; 362*8fd4dddaSChristophe Leroy unsigned long key; 363*8fd4dddaSChristophe Leroy 364*8fd4dddaSChristophe Leroy /* 365*8fd4dddaSChristophe Leroy * Is the key is exported, 'addr' points to the key, which 366*8fd4dddaSChristophe Leroy * means modules are allowed to call static_call_update() on 367*8fd4dddaSChristophe Leroy * it. 368*8fd4dddaSChristophe Leroy * 369*8fd4dddaSChristophe Leroy * Otherwise, the key isn't exported, and 'addr' points to the 370*8fd4dddaSChristophe Leroy * trampoline so we need to lookup the key. 371*8fd4dddaSChristophe Leroy * 372*8fd4dddaSChristophe Leroy * We go through this dance to prevent crazy modules from 373*8fd4dddaSChristophe Leroy * abusing sensitive static calls. 374*8fd4dddaSChristophe Leroy */ 375*8fd4dddaSChristophe Leroy if (!kernel_text_address(addr)) 376*8fd4dddaSChristophe Leroy continue; 377*8fd4dddaSChristophe Leroy 378*8fd4dddaSChristophe Leroy key = tramp_key_lookup(addr); 379*8fd4dddaSChristophe Leroy if (!key) { 380*8fd4dddaSChristophe Leroy pr_warn("Failed to fixup __raw_static_call() usage at: %ps\n", 381*8fd4dddaSChristophe Leroy static_call_addr(site)); 382*8fd4dddaSChristophe Leroy return -EINVAL; 383*8fd4dddaSChristophe Leroy } 384*8fd4dddaSChristophe Leroy 385*8fd4dddaSChristophe Leroy key |= s_key & STATIC_CALL_SITE_FLAGS; 386*8fd4dddaSChristophe Leroy site->key = key - (long)&site->key; 387*8fd4dddaSChristophe Leroy } 388*8fd4dddaSChristophe Leroy 389*8fd4dddaSChristophe Leroy return __static_call_init(mod, start, stop); 390*8fd4dddaSChristophe Leroy } 391*8fd4dddaSChristophe Leroy 392*8fd4dddaSChristophe Leroy static void static_call_del_module(struct module *mod) 393*8fd4dddaSChristophe Leroy { 394*8fd4dddaSChristophe Leroy struct static_call_site *start = mod->static_call_sites; 395*8fd4dddaSChristophe Leroy struct static_call_site *stop = mod->static_call_sites + 396*8fd4dddaSChristophe Leroy mod->num_static_call_sites; 397*8fd4dddaSChristophe Leroy struct static_call_key *key, *prev_key = NULL; 398*8fd4dddaSChristophe Leroy struct static_call_mod *site_mod, **prev; 399*8fd4dddaSChristophe Leroy struct static_call_site *site; 400*8fd4dddaSChristophe Leroy 401*8fd4dddaSChristophe Leroy for (site = start; site < stop; site++) { 402*8fd4dddaSChristophe Leroy key = static_call_key(site); 403*8fd4dddaSChristophe Leroy if (key == prev_key) 404*8fd4dddaSChristophe Leroy continue; 405*8fd4dddaSChristophe Leroy 406*8fd4dddaSChristophe Leroy prev_key = key; 407*8fd4dddaSChristophe Leroy 408*8fd4dddaSChristophe Leroy for (prev = &key->mods, site_mod = key->mods; 409*8fd4dddaSChristophe Leroy site_mod && site_mod->mod != mod; 410*8fd4dddaSChristophe Leroy prev = &site_mod->next, site_mod = site_mod->next) 411*8fd4dddaSChristophe Leroy ; 412*8fd4dddaSChristophe Leroy 413*8fd4dddaSChristophe Leroy if (!site_mod) 414*8fd4dddaSChristophe Leroy continue; 415*8fd4dddaSChristophe Leroy 416*8fd4dddaSChristophe Leroy *prev = site_mod->next; 417*8fd4dddaSChristophe Leroy kfree(site_mod); 418*8fd4dddaSChristophe Leroy } 419*8fd4dddaSChristophe Leroy } 420*8fd4dddaSChristophe Leroy 421*8fd4dddaSChristophe Leroy static int static_call_module_notify(struct notifier_block *nb, 422*8fd4dddaSChristophe Leroy unsigned long val, void *data) 423*8fd4dddaSChristophe Leroy { 424*8fd4dddaSChristophe Leroy struct module *mod = data; 425*8fd4dddaSChristophe Leroy int ret = 0; 426*8fd4dddaSChristophe Leroy 427*8fd4dddaSChristophe Leroy cpus_read_lock(); 428*8fd4dddaSChristophe Leroy static_call_lock(); 429*8fd4dddaSChristophe Leroy 430*8fd4dddaSChristophe Leroy switch (val) { 431*8fd4dddaSChristophe Leroy case MODULE_STATE_COMING: 432*8fd4dddaSChristophe Leroy ret = static_call_add_module(mod); 433*8fd4dddaSChristophe Leroy if (ret) { 434*8fd4dddaSChristophe Leroy WARN(1, "Failed to allocate memory for static calls"); 435*8fd4dddaSChristophe Leroy static_call_del_module(mod); 436*8fd4dddaSChristophe Leroy } 437*8fd4dddaSChristophe Leroy break; 438*8fd4dddaSChristophe Leroy case MODULE_STATE_GOING: 439*8fd4dddaSChristophe Leroy static_call_del_module(mod); 440*8fd4dddaSChristophe Leroy break; 441*8fd4dddaSChristophe Leroy } 442*8fd4dddaSChristophe Leroy 443*8fd4dddaSChristophe Leroy static_call_unlock(); 444*8fd4dddaSChristophe Leroy cpus_read_unlock(); 445*8fd4dddaSChristophe Leroy 446*8fd4dddaSChristophe Leroy return notifier_from_errno(ret); 447*8fd4dddaSChristophe Leroy } 448*8fd4dddaSChristophe Leroy 449*8fd4dddaSChristophe Leroy static struct notifier_block static_call_module_nb = { 450*8fd4dddaSChristophe Leroy .notifier_call = static_call_module_notify, 451*8fd4dddaSChristophe Leroy }; 452*8fd4dddaSChristophe Leroy 453*8fd4dddaSChristophe Leroy #else 454*8fd4dddaSChristophe Leroy 455*8fd4dddaSChristophe Leroy static inline int __static_call_mod_text_reserved(void *start, void *end) 456*8fd4dddaSChristophe Leroy { 457*8fd4dddaSChristophe Leroy return 0; 458*8fd4dddaSChristophe Leroy } 459*8fd4dddaSChristophe Leroy 460*8fd4dddaSChristophe Leroy #endif /* CONFIG_MODULES */ 461*8fd4dddaSChristophe Leroy 462*8fd4dddaSChristophe Leroy int static_call_text_reserved(void *start, void *end) 463*8fd4dddaSChristophe Leroy { 464*8fd4dddaSChristophe Leroy bool init = system_state < SYSTEM_RUNNING; 465*8fd4dddaSChristophe Leroy int ret = __static_call_text_reserved(__start_static_call_sites, 466*8fd4dddaSChristophe Leroy __stop_static_call_sites, start, end, init); 467*8fd4dddaSChristophe Leroy 468*8fd4dddaSChristophe Leroy if (ret) 469*8fd4dddaSChristophe Leroy return ret; 470*8fd4dddaSChristophe Leroy 471*8fd4dddaSChristophe Leroy return __static_call_mod_text_reserved(start, end); 472*8fd4dddaSChristophe Leroy } 473*8fd4dddaSChristophe Leroy 474*8fd4dddaSChristophe Leroy int __init static_call_init(void) 475*8fd4dddaSChristophe Leroy { 476*8fd4dddaSChristophe Leroy int ret; 477*8fd4dddaSChristophe Leroy 478*8fd4dddaSChristophe Leroy if (static_call_initialized) 479*8fd4dddaSChristophe Leroy return 0; 480*8fd4dddaSChristophe Leroy 481*8fd4dddaSChristophe Leroy cpus_read_lock(); 482*8fd4dddaSChristophe Leroy static_call_lock(); 483*8fd4dddaSChristophe Leroy ret = __static_call_init(NULL, __start_static_call_sites, 484*8fd4dddaSChristophe Leroy __stop_static_call_sites); 485*8fd4dddaSChristophe Leroy static_call_unlock(); 486*8fd4dddaSChristophe Leroy cpus_read_unlock(); 487*8fd4dddaSChristophe Leroy 488*8fd4dddaSChristophe Leroy if (ret) { 489*8fd4dddaSChristophe Leroy pr_err("Failed to allocate memory for static_call!\n"); 490*8fd4dddaSChristophe Leroy BUG(); 491*8fd4dddaSChristophe Leroy } 492*8fd4dddaSChristophe Leroy 493*8fd4dddaSChristophe Leroy static_call_initialized = true; 494*8fd4dddaSChristophe Leroy 495*8fd4dddaSChristophe Leroy #ifdef CONFIG_MODULES 496*8fd4dddaSChristophe Leroy register_module_notifier(&static_call_module_nb); 497*8fd4dddaSChristophe Leroy #endif 498*8fd4dddaSChristophe Leroy return 0; 499*8fd4dddaSChristophe Leroy } 500*8fd4dddaSChristophe Leroy early_initcall(static_call_init); 501*8fd4dddaSChristophe Leroy 502*8fd4dddaSChristophe Leroy #ifdef CONFIG_STATIC_CALL_SELFTEST 503*8fd4dddaSChristophe Leroy 504*8fd4dddaSChristophe Leroy static int func_a(int x) 505*8fd4dddaSChristophe Leroy { 506*8fd4dddaSChristophe Leroy return x+1; 507*8fd4dddaSChristophe Leroy } 508*8fd4dddaSChristophe Leroy 509*8fd4dddaSChristophe Leroy static int func_b(int x) 510*8fd4dddaSChristophe Leroy { 511*8fd4dddaSChristophe Leroy return x+2; 512*8fd4dddaSChristophe Leroy } 513*8fd4dddaSChristophe Leroy 514*8fd4dddaSChristophe Leroy DEFINE_STATIC_CALL(sc_selftest, func_a); 515*8fd4dddaSChristophe Leroy 516*8fd4dddaSChristophe Leroy static struct static_call_data { 517*8fd4dddaSChristophe Leroy int (*func)(int); 518*8fd4dddaSChristophe Leroy int val; 519*8fd4dddaSChristophe Leroy int expect; 520*8fd4dddaSChristophe Leroy } static_call_data [] __initdata = { 521*8fd4dddaSChristophe Leroy { NULL, 2, 3 }, 522*8fd4dddaSChristophe Leroy { func_b, 2, 4 }, 523*8fd4dddaSChristophe Leroy { func_a, 2, 3 } 524*8fd4dddaSChristophe Leroy }; 525*8fd4dddaSChristophe Leroy 526*8fd4dddaSChristophe Leroy static int __init test_static_call_init(void) 527*8fd4dddaSChristophe Leroy { 528*8fd4dddaSChristophe Leroy int i; 529*8fd4dddaSChristophe Leroy 530*8fd4dddaSChristophe Leroy for (i = 0; i < ARRAY_SIZE(static_call_data); i++ ) { 531*8fd4dddaSChristophe Leroy struct static_call_data *scd = &static_call_data[i]; 532*8fd4dddaSChristophe Leroy 533*8fd4dddaSChristophe Leroy if (scd->func) 534*8fd4dddaSChristophe Leroy static_call_update(sc_selftest, scd->func); 535*8fd4dddaSChristophe Leroy 536*8fd4dddaSChristophe Leroy WARN_ON(static_call(sc_selftest)(scd->val) != scd->expect); 537*8fd4dddaSChristophe Leroy } 538*8fd4dddaSChristophe Leroy 539*8fd4dddaSChristophe Leroy return 0; 540*8fd4dddaSChristophe Leroy } 541*8fd4dddaSChristophe Leroy early_initcall(test_static_call_init); 542*8fd4dddaSChristophe Leroy 543*8fd4dddaSChristophe Leroy #endif /* CONFIG_STATIC_CALL_SELFTEST */ 544