1
2#ifndef _LINUX_JUMP_LABEL_H
3#define _LINUX_JUMP_LABEL_H
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
75# define HAVE_JUMP_LABEL
76#endif
77
78#ifndef __ASSEMBLY__
79
80#include <linux/types.h>
81#include <linux/compiler.h>
82
83extern bool static_key_initialized;
84
85#define STATIC_KEY_CHECK_USE(key) WARN(!static_key_initialized, \
86 "%s(): static key '%pS' used before call to jump_label_init()", \
87 __func__, (key))
88
89#ifdef HAVE_JUMP_LABEL
90
91struct static_key {
92 atomic_t enabled;
93
94
95
96
97
98
99
100
101
102
103
104
105
106 union {
107 unsigned long type;
108 struct jump_entry *entries;
109 struct static_key_mod *next;
110 };
111};
112
113#else
114struct static_key {
115 atomic_t enabled;
116};
117#endif
118#endif
119
120#ifdef HAVE_JUMP_LABEL
121#include <asm/jump_label.h>
122
123#ifndef __ASSEMBLY__
124#ifdef CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE
125
126struct jump_entry {
127 s32 code;
128 s32 target;
129 long key;
130};
131
132static inline unsigned long jump_entry_code(const struct jump_entry *entry)
133{
134 return (unsigned long)&entry->code + entry->code;
135}
136
137static inline unsigned long jump_entry_target(const struct jump_entry *entry)
138{
139 return (unsigned long)&entry->target + entry->target;
140}
141
142static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
143{
144 long offset = entry->key & ~3L;
145
146 return (struct static_key *)((unsigned long)&entry->key + offset);
147}
148
149#else
150
151static inline unsigned long jump_entry_code(const struct jump_entry *entry)
152{
153 return entry->code;
154}
155
156static inline unsigned long jump_entry_target(const struct jump_entry *entry)
157{
158 return entry->target;
159}
160
161static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
162{
163 return (struct static_key *)((unsigned long)entry->key & ~3UL);
164}
165
166#endif
167
168static inline bool jump_entry_is_branch(const struct jump_entry *entry)
169{
170 return (unsigned long)entry->key & 1UL;
171}
172
173static inline bool jump_entry_is_init(const struct jump_entry *entry)
174{
175 return (unsigned long)entry->key & 2UL;
176}
177
178static inline void jump_entry_set_init(struct jump_entry *entry)
179{
180 entry->key |= 2;
181}
182
183#endif
184#endif
185
186#ifndef __ASSEMBLY__
187
188enum jump_label_type {
189 JUMP_LABEL_NOP = 0,
190 JUMP_LABEL_JMP,
191};
192
193struct module;
194
195#ifdef HAVE_JUMP_LABEL
196
197#define JUMP_TYPE_FALSE 0UL
198#define JUMP_TYPE_TRUE 1UL
199#define JUMP_TYPE_LINKED 2UL
200#define JUMP_TYPE_MASK 3UL
201
202static __always_inline bool static_key_false(struct static_key *key)
203{
204 return arch_static_branch(key, false);
205}
206
207static __always_inline bool static_key_true(struct static_key *key)
208{
209 return !arch_static_branch(key, true);
210}
211
212extern struct jump_entry __start___jump_table[];
213extern struct jump_entry __stop___jump_table[];
214
215extern void jump_label_init(void);
216extern void jump_label_lock(void);
217extern void jump_label_unlock(void);
218extern void arch_jump_label_transform(struct jump_entry *entry,
219 enum jump_label_type type);
220extern void arch_jump_label_transform_static(struct jump_entry *entry,
221 enum jump_label_type type);
222extern bool arch_jump_label_transform_queue(struct jump_entry *entry,
223 enum jump_label_type type);
224extern void arch_jump_label_transform_apply(void);
225extern int jump_label_text_reserved(void *start, void *end);
226extern void static_key_slow_inc(struct static_key *key);
227extern void static_key_slow_dec(struct static_key *key);
228extern void static_key_slow_inc_cpuslocked(struct static_key *key);
229extern void static_key_slow_dec_cpuslocked(struct static_key *key);
230extern void jump_label_apply_nops(struct module *mod);
231extern int static_key_count(struct static_key *key);
232extern void static_key_enable(struct static_key *key);
233extern void static_key_disable(struct static_key *key);
234extern void static_key_enable_cpuslocked(struct static_key *key);
235extern void static_key_disable_cpuslocked(struct static_key *key);
236
237
238
239
240
241
242
243
244#define STATIC_KEY_INIT_TRUE \
245 { .enabled = { 1 }, \
246 { .entries = (void *)JUMP_TYPE_TRUE } }
247#define STATIC_KEY_INIT_FALSE \
248 { .enabled = { 0 }, \
249 { .entries = (void *)JUMP_TYPE_FALSE } }
250
251#else
252
253#include <linux/atomic.h>
254#include <linux/bug.h>
255
256static inline int static_key_count(struct static_key *key)
257{
258 return atomic_read(&key->enabled);
259}
260
261static __always_inline void jump_label_init(void)
262{
263 static_key_initialized = true;
264}
265
266static __always_inline bool static_key_false(struct static_key *key)
267{
268 if (unlikely(static_key_count(key) > 0))
269 return true;
270 return false;
271}
272
273static __always_inline bool static_key_true(struct static_key *key)
274{
275 if (likely(static_key_count(key) > 0))
276 return true;
277 return false;
278}
279
280static inline void static_key_slow_inc(struct static_key *key)
281{
282 STATIC_KEY_CHECK_USE(key);
283 atomic_inc(&key->enabled);
284}
285
286static inline void static_key_slow_dec(struct static_key *key)
287{
288 STATIC_KEY_CHECK_USE(key);
289 atomic_dec(&key->enabled);
290}
291
292#define static_key_slow_inc_cpuslocked(key) static_key_slow_inc(key)
293#define static_key_slow_dec_cpuslocked(key) static_key_slow_dec(key)
294
295static inline int jump_label_text_reserved(void *start, void *end)
296{
297 return 0;
298}
299
300static inline void jump_label_lock(void) {}
301static inline void jump_label_unlock(void) {}
302
303static inline int jump_label_apply_nops(struct module *mod)
304{
305 return 0;
306}
307
308static inline void static_key_enable(struct static_key *key)
309{
310 STATIC_KEY_CHECK_USE(key);
311
312 if (atomic_read(&key->enabled) != 0) {
313 WARN_ON_ONCE(atomic_read(&key->enabled) != 1);
314 return;
315 }
316 atomic_set(&key->enabled, 1);
317}
318
319static inline void static_key_disable(struct static_key *key)
320{
321 STATIC_KEY_CHECK_USE(key);
322
323 if (atomic_read(&key->enabled) != 1) {
324 WARN_ON_ONCE(atomic_read(&key->enabled) != 0);
325 return;
326 }
327 atomic_set(&key->enabled, 0);
328}
329
330#define static_key_enable_cpuslocked(k) static_key_enable((k))
331#define static_key_disable_cpuslocked(k) static_key_disable((k))
332
333#define STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) }
334#define STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) }
335
336#endif
337
338#define STATIC_KEY_INIT STATIC_KEY_INIT_FALSE
339#define jump_label_enabled static_key_enabled
340
341
342
343
344
345
346
347
348
349
350struct static_key_true {
351 struct static_key key;
352};
353
354struct static_key_false {
355 struct static_key key;
356};
357
358#define STATIC_KEY_TRUE_INIT (struct static_key_true) { .key = STATIC_KEY_INIT_TRUE, }
359#define STATIC_KEY_FALSE_INIT (struct static_key_false){ .key = STATIC_KEY_INIT_FALSE, }
360
361#define DEFINE_STATIC_KEY_TRUE(name) \
362 struct static_key_true name = STATIC_KEY_TRUE_INIT
363
364#define DEFINE_STATIC_KEY_TRUE_RO(name) \
365 struct static_key_true name __ro_after_init = STATIC_KEY_TRUE_INIT
366
367#define DECLARE_STATIC_KEY_TRUE(name) \
368 extern struct static_key_true name
369
370#define DEFINE_STATIC_KEY_FALSE(name) \
371 struct static_key_false name = STATIC_KEY_FALSE_INIT
372
373#define DEFINE_STATIC_KEY_FALSE_RO(name) \
374 struct static_key_false name __ro_after_init = STATIC_KEY_FALSE_INIT
375
376#define DECLARE_STATIC_KEY_FALSE(name) \
377 extern struct static_key_false name
378
379#define DEFINE_STATIC_KEY_ARRAY_TRUE(name, count) \
380 struct static_key_true name[count] = { \
381 [0 ... (count) - 1] = STATIC_KEY_TRUE_INIT, \
382 }
383
384#define DEFINE_STATIC_KEY_ARRAY_FALSE(name, count) \
385 struct static_key_false name[count] = { \
386 [0 ... (count) - 1] = STATIC_KEY_FALSE_INIT, \
387 }
388
389extern bool ____wrong_branch_error(void);
390
391#define static_key_enabled(x) \
392({ \
393 if (!__builtin_types_compatible_p(typeof(*x), struct static_key) && \
394 !__builtin_types_compatible_p(typeof(*x), struct static_key_true) &&\
395 !__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
396 ____wrong_branch_error(); \
397 static_key_count((struct static_key *)x) > 0; \
398})
399
400#ifdef HAVE_JUMP_LABEL
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458#define static_branch_likely(x) \
459({ \
460 bool branch; \
461 if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
462 branch = !arch_static_branch(&(x)->key, true); \
463 else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
464 branch = !arch_static_branch_jump(&(x)->key, true); \
465 else \
466 branch = ____wrong_branch_error(); \
467 likely(branch); \
468})
469
470#define static_branch_unlikely(x) \
471({ \
472 bool branch; \
473 if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
474 branch = arch_static_branch_jump(&(x)->key, false); \
475 else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
476 branch = arch_static_branch(&(x)->key, false); \
477 else \
478 branch = ____wrong_branch_error(); \
479 unlikely(branch); \
480})
481
482#else
483
484#define static_branch_likely(x) likely(static_key_enabled(&(x)->key))
485#define static_branch_unlikely(x) unlikely(static_key_enabled(&(x)->key))
486
487#endif
488
489
490
491
492
493#define static_branch_inc(x) static_key_slow_inc(&(x)->key)
494#define static_branch_dec(x) static_key_slow_dec(&(x)->key)
495#define static_branch_inc_cpuslocked(x) static_key_slow_inc_cpuslocked(&(x)->key)
496#define static_branch_dec_cpuslocked(x) static_key_slow_dec_cpuslocked(&(x)->key)
497
498
499
500
501
502#define static_branch_enable(x) static_key_enable(&(x)->key)
503#define static_branch_disable(x) static_key_disable(&(x)->key)
504#define static_branch_enable_cpuslocked(x) static_key_enable_cpuslocked(&(x)->key)
505#define static_branch_disable_cpuslocked(x) static_key_disable_cpuslocked(&(x)->key)
506
507#endif
508
509#endif
510