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