0001
0002 #ifndef _LINUX_JUMP_LABEL_H
0003 #define _LINUX_JUMP_LABEL_H
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074 #ifndef __ASSEMBLY__
0075
0076 #include <linux/types.h>
0077 #include <linux/compiler.h>
0078
0079 extern bool static_key_initialized;
0080
0081 #define STATIC_KEY_CHECK_USE(key) WARN(!static_key_initialized, \
0082 "%s(): static key '%pS' used before call to jump_label_init()", \
0083 __func__, (key))
0084
0085 struct static_key {
0086 atomic_t enabled;
0087 #ifdef CONFIG_JUMP_LABEL
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101 union {
0102 unsigned long type;
0103 struct jump_entry *entries;
0104 struct static_key_mod *next;
0105 };
0106 #endif
0107 };
0108
0109 #endif
0110
0111 #ifdef CONFIG_JUMP_LABEL
0112 #include <asm/jump_label.h>
0113
0114 #ifndef __ASSEMBLY__
0115 #ifdef CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE
0116
0117 struct jump_entry {
0118 s32 code;
0119 s32 target;
0120 long key;
0121 };
0122
0123 static inline unsigned long jump_entry_code(const struct jump_entry *entry)
0124 {
0125 return (unsigned long)&entry->code + entry->code;
0126 }
0127
0128 static inline unsigned long jump_entry_target(const struct jump_entry *entry)
0129 {
0130 return (unsigned long)&entry->target + entry->target;
0131 }
0132
0133 static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
0134 {
0135 long offset = entry->key & ~3L;
0136
0137 return (struct static_key *)((unsigned long)&entry->key + offset);
0138 }
0139
0140 #else
0141
0142 static inline unsigned long jump_entry_code(const struct jump_entry *entry)
0143 {
0144 return entry->code;
0145 }
0146
0147 static inline unsigned long jump_entry_target(const struct jump_entry *entry)
0148 {
0149 return entry->target;
0150 }
0151
0152 static inline struct static_key *jump_entry_key(const struct jump_entry *entry)
0153 {
0154 return (struct static_key *)((unsigned long)entry->key & ~3UL);
0155 }
0156
0157 #endif
0158
0159 static inline bool jump_entry_is_branch(const struct jump_entry *entry)
0160 {
0161 return (unsigned long)entry->key & 1UL;
0162 }
0163
0164 static inline bool jump_entry_is_init(const struct jump_entry *entry)
0165 {
0166 return (unsigned long)entry->key & 2UL;
0167 }
0168
0169 static inline void jump_entry_set_init(struct jump_entry *entry, bool set)
0170 {
0171 if (set)
0172 entry->key |= 2;
0173 else
0174 entry->key &= ~2;
0175 }
0176
0177 static inline int jump_entry_size(struct jump_entry *entry)
0178 {
0179 #ifdef JUMP_LABEL_NOP_SIZE
0180 return JUMP_LABEL_NOP_SIZE;
0181 #else
0182 return arch_jump_entry_size(entry);
0183 #endif
0184 }
0185
0186 #endif
0187 #endif
0188
0189 #ifndef __ASSEMBLY__
0190
0191 enum jump_label_type {
0192 JUMP_LABEL_NOP = 0,
0193 JUMP_LABEL_JMP,
0194 };
0195
0196 struct module;
0197
0198 #ifdef CONFIG_JUMP_LABEL
0199
0200 #define JUMP_TYPE_FALSE 0UL
0201 #define JUMP_TYPE_TRUE 1UL
0202 #define JUMP_TYPE_LINKED 2UL
0203 #define JUMP_TYPE_MASK 3UL
0204
0205 static __always_inline bool static_key_false(struct static_key *key)
0206 {
0207 return arch_static_branch(key, false);
0208 }
0209
0210 static __always_inline bool static_key_true(struct static_key *key)
0211 {
0212 return !arch_static_branch(key, true);
0213 }
0214
0215 extern struct jump_entry __start___jump_table[];
0216 extern struct jump_entry __stop___jump_table[];
0217
0218 extern void jump_label_init(void);
0219 extern void jump_label_lock(void);
0220 extern void jump_label_unlock(void);
0221 extern void arch_jump_label_transform(struct jump_entry *entry,
0222 enum jump_label_type type);
0223 extern bool arch_jump_label_transform_queue(struct jump_entry *entry,
0224 enum jump_label_type type);
0225 extern void arch_jump_label_transform_apply(void);
0226 extern int jump_label_text_reserved(void *start, void *end);
0227 extern void static_key_slow_inc(struct static_key *key);
0228 extern void static_key_slow_dec(struct static_key *key);
0229 extern void static_key_slow_inc_cpuslocked(struct static_key *key);
0230 extern void static_key_slow_dec_cpuslocked(struct static_key *key);
0231 extern int static_key_count(struct static_key *key);
0232 extern void static_key_enable(struct static_key *key);
0233 extern void static_key_disable(struct static_key *key);
0234 extern void static_key_enable_cpuslocked(struct static_key *key);
0235 extern void static_key_disable_cpuslocked(struct static_key *key);
0236 extern enum jump_label_type jump_label_init_type(struct jump_entry *entry);
0237
0238
0239
0240
0241
0242
0243
0244
0245 #define STATIC_KEY_INIT_TRUE \
0246 { .enabled = { 1 }, \
0247 { .type = JUMP_TYPE_TRUE } }
0248 #define STATIC_KEY_INIT_FALSE \
0249 { .enabled = { 0 }, \
0250 { .type = JUMP_TYPE_FALSE } }
0251
0252 #else
0253
0254 #include <linux/atomic.h>
0255 #include <linux/bug.h>
0256
0257 static __always_inline int static_key_count(struct static_key *key)
0258 {
0259 return arch_atomic_read(&key->enabled);
0260 }
0261
0262 static __always_inline void jump_label_init(void)
0263 {
0264 static_key_initialized = true;
0265 }
0266
0267 static __always_inline bool static_key_false(struct static_key *key)
0268 {
0269 if (unlikely_notrace(static_key_count(key) > 0))
0270 return true;
0271 return false;
0272 }
0273
0274 static __always_inline bool static_key_true(struct static_key *key)
0275 {
0276 if (likely_notrace(static_key_count(key) > 0))
0277 return true;
0278 return false;
0279 }
0280
0281 static inline void static_key_slow_inc(struct static_key *key)
0282 {
0283 STATIC_KEY_CHECK_USE(key);
0284 atomic_inc(&key->enabled);
0285 }
0286
0287 static inline void static_key_slow_dec(struct static_key *key)
0288 {
0289 STATIC_KEY_CHECK_USE(key);
0290 atomic_dec(&key->enabled);
0291 }
0292
0293 #define static_key_slow_inc_cpuslocked(key) static_key_slow_inc(key)
0294 #define static_key_slow_dec_cpuslocked(key) static_key_slow_dec(key)
0295
0296 static inline int jump_label_text_reserved(void *start, void *end)
0297 {
0298 return 0;
0299 }
0300
0301 static inline void jump_label_lock(void) {}
0302 static inline void jump_label_unlock(void) {}
0303
0304 static inline void static_key_enable(struct static_key *key)
0305 {
0306 STATIC_KEY_CHECK_USE(key);
0307
0308 if (atomic_read(&key->enabled) != 0) {
0309 WARN_ON_ONCE(atomic_read(&key->enabled) != 1);
0310 return;
0311 }
0312 atomic_set(&key->enabled, 1);
0313 }
0314
0315 static inline void static_key_disable(struct static_key *key)
0316 {
0317 STATIC_KEY_CHECK_USE(key);
0318
0319 if (atomic_read(&key->enabled) != 1) {
0320 WARN_ON_ONCE(atomic_read(&key->enabled) != 0);
0321 return;
0322 }
0323 atomic_set(&key->enabled, 0);
0324 }
0325
0326 #define static_key_enable_cpuslocked(k) static_key_enable((k))
0327 #define static_key_disable_cpuslocked(k) static_key_disable((k))
0328
0329 #define STATIC_KEY_INIT_TRUE { .enabled = ATOMIC_INIT(1) }
0330 #define STATIC_KEY_INIT_FALSE { .enabled = ATOMIC_INIT(0) }
0331
0332 #endif
0333
0334 #define STATIC_KEY_INIT STATIC_KEY_INIT_FALSE
0335 #define jump_label_enabled static_key_enabled
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346 struct static_key_true {
0347 struct static_key key;
0348 };
0349
0350 struct static_key_false {
0351 struct static_key key;
0352 };
0353
0354 #define STATIC_KEY_TRUE_INIT (struct static_key_true) { .key = STATIC_KEY_INIT_TRUE, }
0355 #define STATIC_KEY_FALSE_INIT (struct static_key_false){ .key = STATIC_KEY_INIT_FALSE, }
0356
0357 #define DEFINE_STATIC_KEY_TRUE(name) \
0358 struct static_key_true name = STATIC_KEY_TRUE_INIT
0359
0360 #define DEFINE_STATIC_KEY_TRUE_RO(name) \
0361 struct static_key_true name __ro_after_init = STATIC_KEY_TRUE_INIT
0362
0363 #define DECLARE_STATIC_KEY_TRUE(name) \
0364 extern struct static_key_true name
0365
0366 #define DEFINE_STATIC_KEY_FALSE(name) \
0367 struct static_key_false name = STATIC_KEY_FALSE_INIT
0368
0369 #define DEFINE_STATIC_KEY_FALSE_RO(name) \
0370 struct static_key_false name __ro_after_init = STATIC_KEY_FALSE_INIT
0371
0372 #define DECLARE_STATIC_KEY_FALSE(name) \
0373 extern struct static_key_false name
0374
0375 #define DEFINE_STATIC_KEY_ARRAY_TRUE(name, count) \
0376 struct static_key_true name[count] = { \
0377 [0 ... (count) - 1] = STATIC_KEY_TRUE_INIT, \
0378 }
0379
0380 #define DEFINE_STATIC_KEY_ARRAY_FALSE(name, count) \
0381 struct static_key_false name[count] = { \
0382 [0 ... (count) - 1] = STATIC_KEY_FALSE_INIT, \
0383 }
0384
0385 #define _DEFINE_STATIC_KEY_1(name) DEFINE_STATIC_KEY_TRUE(name)
0386 #define _DEFINE_STATIC_KEY_0(name) DEFINE_STATIC_KEY_FALSE(name)
0387 #define DEFINE_STATIC_KEY_MAYBE(cfg, name) \
0388 __PASTE(_DEFINE_STATIC_KEY_, IS_ENABLED(cfg))(name)
0389
0390 #define _DEFINE_STATIC_KEY_RO_1(name) DEFINE_STATIC_KEY_TRUE_RO(name)
0391 #define _DEFINE_STATIC_KEY_RO_0(name) DEFINE_STATIC_KEY_FALSE_RO(name)
0392 #define DEFINE_STATIC_KEY_MAYBE_RO(cfg, name) \
0393 __PASTE(_DEFINE_STATIC_KEY_RO_, IS_ENABLED(cfg))(name)
0394
0395 #define _DECLARE_STATIC_KEY_1(name) DECLARE_STATIC_KEY_TRUE(name)
0396 #define _DECLARE_STATIC_KEY_0(name) DECLARE_STATIC_KEY_FALSE(name)
0397 #define DECLARE_STATIC_KEY_MAYBE(cfg, name) \
0398 __PASTE(_DECLARE_STATIC_KEY_, IS_ENABLED(cfg))(name)
0399
0400 extern bool ____wrong_branch_error(void);
0401
0402 #define static_key_enabled(x) \
0403 ({ \
0404 if (!__builtin_types_compatible_p(typeof(*x), struct static_key) && \
0405 !__builtin_types_compatible_p(typeof(*x), struct static_key_true) &&\
0406 !__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
0407 ____wrong_branch_error(); \
0408 static_key_count((struct static_key *)x) > 0; \
0409 })
0410
0411 #ifdef CONFIG_JUMP_LABEL
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469 #define static_branch_likely(x) \
0470 ({ \
0471 bool branch; \
0472 if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
0473 branch = !arch_static_branch(&(x)->key, true); \
0474 else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
0475 branch = !arch_static_branch_jump(&(x)->key, true); \
0476 else \
0477 branch = ____wrong_branch_error(); \
0478 likely_notrace(branch); \
0479 })
0480
0481 #define static_branch_unlikely(x) \
0482 ({ \
0483 bool branch; \
0484 if (__builtin_types_compatible_p(typeof(*x), struct static_key_true)) \
0485 branch = arch_static_branch_jump(&(x)->key, false); \
0486 else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
0487 branch = arch_static_branch(&(x)->key, false); \
0488 else \
0489 branch = ____wrong_branch_error(); \
0490 unlikely_notrace(branch); \
0491 })
0492
0493 #else
0494
0495 #define static_branch_likely(x) likely_notrace(static_key_enabled(&(x)->key))
0496 #define static_branch_unlikely(x) unlikely_notrace(static_key_enabled(&(x)->key))
0497
0498 #endif
0499
0500 #define static_branch_maybe(config, x) \
0501 (IS_ENABLED(config) ? static_branch_likely(x) \
0502 : static_branch_unlikely(x))
0503
0504
0505
0506
0507
0508 #define static_branch_inc(x) static_key_slow_inc(&(x)->key)
0509 #define static_branch_dec(x) static_key_slow_dec(&(x)->key)
0510 #define static_branch_inc_cpuslocked(x) static_key_slow_inc_cpuslocked(&(x)->key)
0511 #define static_branch_dec_cpuslocked(x) static_key_slow_dec_cpuslocked(&(x)->key)
0512
0513
0514
0515
0516
0517 #define static_branch_enable(x) static_key_enable(&(x)->key)
0518 #define static_branch_disable(x) static_key_disable(&(x)->key)
0519 #define static_branch_enable_cpuslocked(x) static_key_enable_cpuslocked(&(x)->key)
0520 #define static_branch_disable_cpuslocked(x) static_key_disable_cpuslocked(&(x)->key)
0521
0522 #endif
0523
0524 #endif