Commit 9049fc745300c5e2236cbfc69f5e8cadb6f1f57c

Authored by Jason Baron
Committed by Linus Torvalds
1 parent 1f69bf9c61

dynamic_debug: add jump label support

Although dynamic debug is often only used for debug builds, sometimes
its enabled for production builds as well.  Minimize its impact by using
jump labels.  This reduces the text section by 7000+ bytes in the kernel
image below.  It does increase data, but this should only be referenced
when changing the direction of the branches, and hence usually not in
cache.

     text     data     bss       dec     hex  filename
  8194852  4879776  925696  14000324  d5a0c4  vmlinux.pre
  8187337  4960224  925696  14073257  d6bda9  vmlinux.post

Link: http://lkml.kernel.org/r/d165b465e8c89bc582d973758d40be44c33f018b.1467837322.git.jbaron@akamai.com
Signed-off-by: Jason Baron <jbaron@akamai.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Chris Metcalf <cmetcalf@mellanox.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Joe Perches <joe@perches.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 2 changed files with 61 additions and 6 deletions Side-by-side Diff

include/linux/dynamic_debug.h
1 1 #ifndef _DYNAMIC_DEBUG_H
2 2 #define _DYNAMIC_DEBUG_H
3 3  
  4 +#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
  5 +#include <linux/jump_label.h>
  6 +#endif
  7 +
4 8 /*
5 9 * An instance of this structure is created in a special
6 10 * ELF section at every dynamic debug callsite. At runtime,
... ... @@ -33,6 +37,12 @@
33 37 #define _DPRINTK_FLAGS_DEFAULT 0
34 38 #endif
35 39 unsigned int flags:8;
  40 +#ifdef HAVE_JUMP_LABEL
  41 + union {
  42 + struct static_key_true dd_key_true;
  43 + struct static_key_false dd_key_false;
  44 + } key;
  45 +#endif
36 46 } __attribute__((aligned(8)));
37 47  
38 48  
... ... @@ -60,7 +70,7 @@
60 70 const struct net_device *dev,
61 71 const char *fmt, ...);
62 72  
63   -#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
  73 +#define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init) \
64 74 static struct _ddebug __aligned(8) \
65 75 __attribute__((section("__verbose"))) name = { \
66 76 .modname = KBUILD_MODNAME, \
67 77  
68 78  
... ... @@ -68,13 +78,51 @@
68 78 .filename = __FILE__, \
69 79 .format = (fmt), \
70 80 .lineno = __LINE__, \
71   - .flags = _DPRINTK_FLAGS_DEFAULT, \
  81 + .flags = _DPRINTK_FLAGS_DEFAULT, \
  82 + dd_key_init(key, init) \
72 83 }
73 84  
  85 +#ifdef HAVE_JUMP_LABEL
  86 +
  87 +#define dd_key_init(key, init) key = (init)
  88 +
  89 +#ifdef DEBUG
  90 +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
  91 + DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_true, \
  92 + (STATIC_KEY_TRUE_INIT))
  93 +
  94 +#define DYNAMIC_DEBUG_BRANCH(descriptor) \
  95 + static_branch_likely(&descriptor.key.dd_key_true)
  96 +#else
  97 +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
  98 + DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_false, \
  99 + (STATIC_KEY_FALSE_INIT))
  100 +
  101 +#define DYNAMIC_DEBUG_BRANCH(descriptor) \
  102 + static_branch_unlikely(&descriptor.key.dd_key_false)
  103 +#endif
  104 +
  105 +#else
  106 +
  107 +#define dd_key_init(key, init)
  108 +
  109 +#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
  110 + DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, 0, 0)
  111 +
  112 +#ifdef DEBUG
  113 +#define DYNAMIC_DEBUG_BRANCH(descriptor) \
  114 + likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
  115 +#else
  116 +#define DYNAMIC_DEBUG_BRANCH(descriptor) \
  117 + unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
  118 +#endif
  119 +
  120 +#endif
  121 +
74 122 #define dynamic_pr_debug(fmt, ...) \
75 123 do { \
76 124 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
77   - if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
  125 + if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
78 126 __dynamic_pr_debug(&descriptor, pr_fmt(fmt), \
79 127 ##__VA_ARGS__); \
80 128 } while (0)
... ... @@ -82,7 +130,7 @@
82 130 #define dynamic_dev_dbg(dev, fmt, ...) \
83 131 do { \
84 132 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
85   - if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
  133 + if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
86 134 __dynamic_dev_dbg(&descriptor, dev, fmt, \
87 135 ##__VA_ARGS__); \
88 136 } while (0)
... ... @@ -90,7 +138,7 @@
90 138 #define dynamic_netdev_dbg(dev, fmt, ...) \
91 139 do { \
92 140 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
93   - if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
  141 + if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
94 142 __dynamic_netdev_dbg(&descriptor, dev, fmt, \
95 143 ##__VA_ARGS__); \
96 144 } while (0)
... ... @@ -100,7 +148,7 @@
100 148 do { \
101 149 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \
102 150 __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\
103   - if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \
  151 + if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
104 152 print_hex_dump(KERN_DEBUG, prefix_str, \
105 153 prefix_type, rowsize, groupsize, \
106 154 buf, len, ascii); \
... ... @@ -188,6 +188,13 @@
188 188 newflags = (dp->flags & mask) | flags;
189 189 if (newflags == dp->flags)
190 190 continue;
  191 +#ifdef HAVE_JUMP_LABEL
  192 + if (dp->flags & _DPRINTK_FLAGS_PRINT) {
  193 + if (!(flags & _DPRINTK_FLAGS_PRINT))
  194 + static_branch_disable(&dp->key.dd_key_true);
  195 + } else if (flags & _DPRINTK_FLAGS_PRINT)
  196 + static_branch_enable(&dp->key.dd_key_true);
  197 +#endif
191 198 dp->flags = newflags;
192 199 vpr_info("changed %s:%d [%s]%s =%s\n",
193 200 trim_prefix(dp->filename), dp->lineno,