aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Baron <jbaron@akamai.com>2016-08-03 16:46:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-04 08:50:07 -0400
commit9049fc745300c5e2236cbfc69f5e8cadb6f1f57c (patch)
tree032e8c7503e5c8c27e7fd177579df82790528d3c
parent1f69bf9c6137602cd028c96b4f8329121ec89231 (diff)
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>
-rw-r--r--include/linux/dynamic_debug.h60
-rw-r--r--lib/dynamic_debug.c7
2 files changed, 61 insertions, 6 deletions
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 4f1bbc68cd1b..546d68057e3b 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -1,6 +1,10 @@
1#ifndef _DYNAMIC_DEBUG_H 1#ifndef _DYNAMIC_DEBUG_H
2#define _DYNAMIC_DEBUG_H 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 * An instance of this structure is created in a special 9 * An instance of this structure is created in a special
6 * ELF section at every dynamic debug callsite. At runtime, 10 * ELF section at every dynamic debug callsite. At runtime,
@@ -33,6 +37,12 @@ struct _ddebug {
33#define _DPRINTK_FLAGS_DEFAULT 0 37#define _DPRINTK_FLAGS_DEFAULT 0
34#endif 38#endif
35 unsigned int flags:8; 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} __attribute__((aligned(8))); 46} __attribute__((aligned(8)));
37 47
38 48
@@ -60,7 +70,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
60 const struct net_device *dev, 70 const struct net_device *dev,
61 const char *fmt, ...); 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 static struct _ddebug __aligned(8) \ 74 static struct _ddebug __aligned(8) \
65 __attribute__((section("__verbose"))) name = { \ 75 __attribute__((section("__verbose"))) name = { \
66 .modname = KBUILD_MODNAME, \ 76 .modname = KBUILD_MODNAME, \
@@ -68,13 +78,51 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
68 .filename = __FILE__, \ 78 .filename = __FILE__, \
69 .format = (fmt), \ 79 .format = (fmt), \
70 .lineno = __LINE__, \ 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#define dynamic_pr_debug(fmt, ...) \ 122#define dynamic_pr_debug(fmt, ...) \
75do { \ 123do { \
76 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ 124 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
77 if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ 125 if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
78 __dynamic_pr_debug(&descriptor, pr_fmt(fmt), \ 126 __dynamic_pr_debug(&descriptor, pr_fmt(fmt), \
79 ##__VA_ARGS__); \ 127 ##__VA_ARGS__); \
80} while (0) 128} while (0)
@@ -82,7 +130,7 @@ do { \
82#define dynamic_dev_dbg(dev, fmt, ...) \ 130#define dynamic_dev_dbg(dev, fmt, ...) \
83do { \ 131do { \
84 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ 132 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
85 if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ 133 if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
86 __dynamic_dev_dbg(&descriptor, dev, fmt, \ 134 __dynamic_dev_dbg(&descriptor, dev, fmt, \
87 ##__VA_ARGS__); \ 135 ##__VA_ARGS__); \
88} while (0) 136} while (0)
@@ -90,7 +138,7 @@ do { \
90#define dynamic_netdev_dbg(dev, fmt, ...) \ 138#define dynamic_netdev_dbg(dev, fmt, ...) \
91do { \ 139do { \
92 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ 140 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
93 if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ 141 if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
94 __dynamic_netdev_dbg(&descriptor, dev, fmt, \ 142 __dynamic_netdev_dbg(&descriptor, dev, fmt, \
95 ##__VA_ARGS__); \ 143 ##__VA_ARGS__); \
96} while (0) 144} while (0)
@@ -100,7 +148,7 @@ do { \
100do { \ 148do { \
101 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \ 149 DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \
102 __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\ 150 __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\
103 if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ 151 if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
104 print_hex_dump(KERN_DEBUG, prefix_str, \ 152 print_hex_dump(KERN_DEBUG, prefix_str, \
105 prefix_type, rowsize, groupsize, \ 153 prefix_type, rowsize, groupsize, \
106 buf, len, ascii); \ 154 buf, len, ascii); \
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index fe42b6ec3f0c..da796e2dc4f5 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -188,6 +188,13 @@ static int ddebug_change(const struct ddebug_query *query,
188 newflags = (dp->flags & mask) | flags; 188 newflags = (dp->flags & mask) | flags;
189 if (newflags == dp->flags) 189 if (newflags == dp->flags)
190 continue; 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 dp->flags = newflags; 198 dp->flags = newflags;
192 vpr_info("changed %s:%d [%s]%s =%s\n", 199 vpr_info("changed %s:%d [%s]%s =%s\n",
193 trim_prefix(dp->filename), dp->lineno, 200 trim_prefix(dp->filename), dp->lineno,