aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/jump_label.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-02-27 16:26:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-02-27 16:26:17 -0500
commit79b17ea740d9fab178d6a1aa15d848b5e6c01b82 (patch)
treeb0c18df8713999e16bcc6e5a32cbef880efb3b10 /kernel/jump_label.c
parente5d56efc97f8240d0b5d66c03949382b6d7e5570 (diff)
parent67d04bb2bcbd3e99f4c4daa58599c90a83ad314a (diff)
Merge tag 'trace-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing updates from Steven Rostedt: "This release has no new tracing features, just clean ups, minor fixes and small optimizations" * tag 'trace-v4.11' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (25 commits) tracing: Remove outdated ring buffer comment tracing/probes: Fix a warning message to show correct maximum length tracing: Fix return value check in trace_benchmark_reg() tracing: Use modern function declaration jump_label: Reduce the size of struct static_key tracing/probe: Show subsystem name in messages tracing/hwlat: Update old comment about migration timers: Make flags output in the timer_start tracepoint useful tracing: Have traceprobe_probes_write() not access userspace unnecessarily tracing: Have COMM event filter key be treated as a string ftrace: Have set_graph_function handle multiple functions in one write ftrace: Do not hold references of ftrace_graph_{notrace_}hash out of graph_lock tracing: Reset parser->buffer to allow multiple "puts" ftrace: Have set_graph_functions handle write with RDWR ftrace: Reset fgd->hash in ftrace_graph_write() ftrace: Replace (void *)1 with a meaningful macro name FTRACE_GRAPH_EMPTY ftrace: Create a slight optimization on searching the ftrace_hash tracing: Add ftrace_hash_key() helper function ftrace: Convert graph filter to use hash tables ftrace: Expose ftrace_hash_empty and ftrace_lookup_ip ...
Diffstat (limited to 'kernel/jump_label.c')
-rw-r--r--kernel/jump_label.c153
1 files changed, 127 insertions, 26 deletions
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index a9b8cf500591..6c9cb208ac48 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -236,12 +236,28 @@ void __weak __init_or_module arch_jump_label_transform_static(struct jump_entry
236 236
237static inline struct jump_entry *static_key_entries(struct static_key *key) 237static inline struct jump_entry *static_key_entries(struct static_key *key)
238{ 238{
239 return (struct jump_entry *)((unsigned long)key->entries & ~JUMP_TYPE_MASK); 239 WARN_ON_ONCE(key->type & JUMP_TYPE_LINKED);
240 return (struct jump_entry *)(key->type & ~JUMP_TYPE_MASK);
240} 241}
241 242
242static inline bool static_key_type(struct static_key *key) 243static inline bool static_key_type(struct static_key *key)
243{ 244{
244 return (unsigned long)key->entries & JUMP_TYPE_MASK; 245 return key->type & JUMP_TYPE_TRUE;
246}
247
248static inline bool static_key_linked(struct static_key *key)
249{
250 return key->type & JUMP_TYPE_LINKED;
251}
252
253static inline void static_key_clear_linked(struct static_key *key)
254{
255 key->type &= ~JUMP_TYPE_LINKED;
256}
257
258static inline void static_key_set_linked(struct static_key *key)
259{
260 key->type |= JUMP_TYPE_LINKED;
245} 261}
246 262
247static inline struct static_key *jump_entry_key(struct jump_entry *entry) 263static inline struct static_key *jump_entry_key(struct jump_entry *entry)
@@ -254,6 +270,26 @@ static bool jump_entry_branch(struct jump_entry *entry)
254 return (unsigned long)entry->key & 1UL; 270 return (unsigned long)entry->key & 1UL;
255} 271}
256 272
273/***
274 * A 'struct static_key' uses a union such that it either points directly
275 * to a table of 'struct jump_entry' or to a linked list of modules which in
276 * turn point to 'struct jump_entry' tables.
277 *
278 * The two lower bits of the pointer are used to keep track of which pointer
279 * type is in use and to store the initial branch direction, we use an access
280 * function which preserves these bits.
281 */
282static void static_key_set_entries(struct static_key *key,
283 struct jump_entry *entries)
284{
285 unsigned long type;
286
287 WARN_ON_ONCE((unsigned long)entries & JUMP_TYPE_MASK);
288 type = key->type & JUMP_TYPE_MASK;
289 key->entries = entries;
290 key->type |= type;
291}
292
257static enum jump_label_type jump_label_type(struct jump_entry *entry) 293static enum jump_label_type jump_label_type(struct jump_entry *entry)
258{ 294{
259 struct static_key *key = jump_entry_key(entry); 295 struct static_key *key = jump_entry_key(entry);
@@ -313,13 +349,7 @@ void __init jump_label_init(void)
313 continue; 349 continue;
314 350
315 key = iterk; 351 key = iterk;
316 /* 352 static_key_set_entries(key, iter);
317 * Set key->entries to iter, but preserve JUMP_LABEL_TRUE_BRANCH.
318 */
319 *((unsigned long *)&key->entries) += (unsigned long)iter;
320#ifdef CONFIG_MODULES
321 key->next = NULL;
322#endif
323 } 353 }
324 static_key_initialized = true; 354 static_key_initialized = true;
325 jump_label_unlock(); 355 jump_label_unlock();
@@ -343,6 +373,29 @@ struct static_key_mod {
343 struct module *mod; 373 struct module *mod;
344}; 374};
345 375
376static inline struct static_key_mod *static_key_mod(struct static_key *key)
377{
378 WARN_ON_ONCE(!(key->type & JUMP_TYPE_LINKED));
379 return (struct static_key_mod *)(key->type & ~JUMP_TYPE_MASK);
380}
381
382/***
383 * key->type and key->next are the same via union.
384 * This sets key->next and preserves the type bits.
385 *
386 * See additional comments above static_key_set_entries().
387 */
388static void static_key_set_mod(struct static_key *key,
389 struct static_key_mod *mod)
390{
391 unsigned long type;
392
393 WARN_ON_ONCE((unsigned long)mod & JUMP_TYPE_MASK);
394 type = key->type & JUMP_TYPE_MASK;
395 key->next = mod;
396 key->type |= type;
397}
398
346static int __jump_label_mod_text_reserved(void *start, void *end) 399static int __jump_label_mod_text_reserved(void *start, void *end)
347{ 400{
348 struct module *mod; 401 struct module *mod;
@@ -365,11 +418,23 @@ static void __jump_label_mod_update(struct static_key *key)
365{ 418{
366 struct static_key_mod *mod; 419 struct static_key_mod *mod;
367 420
368 for (mod = key->next; mod; mod = mod->next) { 421 for (mod = static_key_mod(key); mod; mod = mod->next) {
369 struct module *m = mod->mod; 422 struct jump_entry *stop;
423 struct module *m;
424
425 /*
426 * NULL if the static_key is defined in a module
427 * that does not use it
428 */
429 if (!mod->entries)
430 continue;
370 431
371 __jump_label_update(key, mod->entries, 432 m = mod->mod;
372 m->jump_entries + m->num_jump_entries); 433 if (!m)
434 stop = __stop___jump_table;
435 else
436 stop = m->jump_entries + m->num_jump_entries;
437 __jump_label_update(key, mod->entries, stop);
373 } 438 }
374} 439}
375 440
@@ -404,7 +469,7 @@ static int jump_label_add_module(struct module *mod)
404 struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; 469 struct jump_entry *iter_stop = iter_start + mod->num_jump_entries;
405 struct jump_entry *iter; 470 struct jump_entry *iter;
406 struct static_key *key = NULL; 471 struct static_key *key = NULL;
407 struct static_key_mod *jlm; 472 struct static_key_mod *jlm, *jlm2;
408 473
409 /* if the module doesn't have jump label entries, just return */ 474 /* if the module doesn't have jump label entries, just return */
410 if (iter_start == iter_stop) 475 if (iter_start == iter_stop)
@@ -421,20 +486,32 @@ static int jump_label_add_module(struct module *mod)
421 486
422 key = iterk; 487 key = iterk;
423 if (within_module(iter->key, mod)) { 488 if (within_module(iter->key, mod)) {
424 /* 489 static_key_set_entries(key, iter);
425 * Set key->entries to iter, but preserve JUMP_LABEL_TRUE_BRANCH.
426 */
427 *((unsigned long *)&key->entries) += (unsigned long)iter;
428 key->next = NULL;
429 continue; 490 continue;
430 } 491 }
431 jlm = kzalloc(sizeof(struct static_key_mod), GFP_KERNEL); 492 jlm = kzalloc(sizeof(struct static_key_mod), GFP_KERNEL);
432 if (!jlm) 493 if (!jlm)
433 return -ENOMEM; 494 return -ENOMEM;
495 if (!static_key_linked(key)) {
496 jlm2 = kzalloc(sizeof(struct static_key_mod),
497 GFP_KERNEL);
498 if (!jlm2) {
499 kfree(jlm);
500 return -ENOMEM;
501 }
502 preempt_disable();
503 jlm2->mod = __module_address((unsigned long)key);
504 preempt_enable();
505 jlm2->entries = static_key_entries(key);
506 jlm2->next = NULL;
507 static_key_set_mod(key, jlm2);
508 static_key_set_linked(key);
509 }
434 jlm->mod = mod; 510 jlm->mod = mod;
435 jlm->entries = iter; 511 jlm->entries = iter;
436 jlm->next = key->next; 512 jlm->next = static_key_mod(key);
437 key->next = jlm; 513 static_key_set_mod(key, jlm);
514 static_key_set_linked(key);
438 515
439 /* Only update if we've changed from our initial state */ 516 /* Only update if we've changed from our initial state */
440 if (jump_label_type(iter) != jump_label_init_type(iter)) 517 if (jump_label_type(iter) != jump_label_init_type(iter))
@@ -461,16 +538,34 @@ static void jump_label_del_module(struct module *mod)
461 if (within_module(iter->key, mod)) 538 if (within_module(iter->key, mod))
462 continue; 539 continue;
463 540
541 /* No memory during module load */
542 if (WARN_ON(!static_key_linked(key)))
543 continue;
544
464 prev = &key->next; 545 prev = &key->next;
465 jlm = key->next; 546 jlm = static_key_mod(key);
466 547
467 while (jlm && jlm->mod != mod) { 548 while (jlm && jlm->mod != mod) {
468 prev = &jlm->next; 549 prev = &jlm->next;
469 jlm = jlm->next; 550 jlm = jlm->next;
470 } 551 }
471 552
472 if (jlm) { 553 /* No memory during module load */
554 if (WARN_ON(!jlm))
555 continue;
556
557 if (prev == &key->next)
558 static_key_set_mod(key, jlm->next);
559 else
473 *prev = jlm->next; 560 *prev = jlm->next;
561
562 kfree(jlm);
563
564 jlm = static_key_mod(key);
565 /* if only one etry is left, fold it back into the static_key */
566 if (jlm->next == NULL) {
567 static_key_set_entries(key, jlm->entries);
568 static_key_clear_linked(key);
474 kfree(jlm); 569 kfree(jlm);
475 } 570 }
476 } 571 }
@@ -499,8 +594,10 @@ jump_label_module_notify(struct notifier_block *self, unsigned long val,
499 case MODULE_STATE_COMING: 594 case MODULE_STATE_COMING:
500 jump_label_lock(); 595 jump_label_lock();
501 ret = jump_label_add_module(mod); 596 ret = jump_label_add_module(mod);
502 if (ret) 597 if (ret) {
598 WARN(1, "Failed to allocatote memory: jump_label may not work properly.\n");
503 jump_label_del_module(mod); 599 jump_label_del_module(mod);
600 }
504 jump_label_unlock(); 601 jump_label_unlock();
505 break; 602 break;
506 case MODULE_STATE_GOING: 603 case MODULE_STATE_GOING:
@@ -561,11 +658,14 @@ int jump_label_text_reserved(void *start, void *end)
561static void jump_label_update(struct static_key *key) 658static void jump_label_update(struct static_key *key)
562{ 659{
563 struct jump_entry *stop = __stop___jump_table; 660 struct jump_entry *stop = __stop___jump_table;
564 struct jump_entry *entry = static_key_entries(key); 661 struct jump_entry *entry;
565#ifdef CONFIG_MODULES 662#ifdef CONFIG_MODULES
566 struct module *mod; 663 struct module *mod;
567 664
568 __jump_label_mod_update(key); 665 if (static_key_linked(key)) {
666 __jump_label_mod_update(key);
667 return;
668 }
569 669
570 preempt_disable(); 670 preempt_disable();
571 mod = __module_address((unsigned long)key); 671 mod = __module_address((unsigned long)key);
@@ -573,6 +673,7 @@ static void jump_label_update(struct static_key *key)
573 stop = mod->jump_entries + mod->num_jump_entries; 673 stop = mod->jump_entries + mod->num_jump_entries;
574 preempt_enable(); 674 preempt_enable();
575#endif 675#endif
676 entry = static_key_entries(key);
576 /* if there are no users, entry can be NULL */ 677 /* if there are no users, entry can be NULL */
577 if (entry) 678 if (entry)
578 __jump_label_update(key, entry, stop); 679 __jump_label_update(key, entry, stop);