Skip to content

Commit 346e15b

Browse files
jibarongregkh
authored andcommitted
driver core: basic infrastructure for per-module dynamic debug messages
Base infrastructure to enable per-module debug messages. I've introduced CONFIG_DYNAMIC_PRINTK_DEBUG, which when enabled centralizes control of debugging statements on a per-module basis in one /proc file, currently, <debugfs>/dynamic_printk/modules. When, CONFIG_DYNAMIC_PRINTK_DEBUG, is not set, debugging statements can still be enabled as before, often by defining 'DEBUG' for the proper compilation unit. Thus, this patch set has no affect when CONFIG_DYNAMIC_PRINTK_DEBUG is not set. The infrastructure currently ties into all pr_debug() and dev_dbg() calls. That is, if CONFIG_DYNAMIC_PRINTK_DEBUG is set, all pr_debug() and dev_dbg() calls can be dynamically enabled/disabled on a per-module basis. Future plans include extending this functionality to subsystems, that define their own debug levels and flags. Usage: Dynamic debugging is controlled by the debugfs file, <debugfs>/dynamic_printk/modules. This file contains a list of the modules that can be enabled. The format of the file is as follows: <module_name> <enabled=0/1> . . . <module_name> : Name of the module in which the debug call resides <enabled=0/1> : whether the messages are enabled or not For example: snd_hda_intel enabled=0 fixup enabled=1 driver enabled=0 Enable a module: $echo "set enabled=1 <module_name>" > dynamic_printk/modules Disable a module: $echo "set enabled=0 <module_name>" > dynamic_printk/modules Enable all modules: $echo "set enabled=1 all" > dynamic_printk/modules Disable all modules: $echo "set enabled=0 all" > dynamic_printk/modules Finally, passing "dynamic_printk" at the command line enables debugging for all modules. This mode can be turned off via the above disable command. [gkh: minor cleanups and tweaks to make the build work quietly] Signed-off-by: Jason Baron <jbaron@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
1 parent 33376c1 commit 346e15b

14 files changed

Lines changed: 700 additions & 7 deletions

File tree

Documentation/kernel-parameters.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,6 +1713,11 @@ and is between 256 and 4096 characters. It is defined in the file
17131713
autoconfiguration.
17141714
Ranges are in pairs (memory base and size).
17151715

1716+
dynamic_printk
1717+
Enables pr_debug()/dev_dbg() calls if
1718+
CONFIG_DYNAMIC_PRINTK_DEBUG has been enabled. These can also
1719+
be switched on/off via <debugfs>/dynamic_printk/modules
1720+
17161721
print-fatal-signals=
17171722
[KNL] debug: print fatal signals
17181723
print-fatal-signals=1: print segfault info to

include/asm-generic/vmlinux.lds.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,15 @@
268268
CPU_DISCARD(init.data) \
269269
CPU_DISCARD(init.rodata) \
270270
MEM_DISCARD(init.data) \
271-
MEM_DISCARD(init.rodata)
271+
MEM_DISCARD(init.rodata) \
272+
/* implement dynamic printk debug */ \
273+
VMLINUX_SYMBOL(__start___verbose_strings) = .; \
274+
*(__verbose_strings) \
275+
VMLINUX_SYMBOL(__stop___verbose_strings) = .; \
276+
. = ALIGN(8); \
277+
VMLINUX_SYMBOL(__start___verbose) = .; \
278+
*(__verbose) \
279+
VMLINUX_SYMBOL(__stop___verbose) = .;
272280

273281
#define INIT_TEXT \
274282
*(.init.text) \

include/linux/device.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,11 @@ extern const char *dev_driver_string(const struct device *dev);
550550
#define dev_info(dev, format, arg...) \
551551
dev_printk(KERN_INFO , dev , format , ## arg)
552552

553-
#ifdef DEBUG
553+
#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
554+
#define dev_dbg(dev, format, ...) do { \
555+
dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
556+
} while (0)
557+
#elif defined(DEBUG)
554558
#define dev_dbg(dev, format, arg...) \
555559
dev_printk(KERN_DEBUG , dev , format , ## arg)
556560
#else

include/linux/dynamic_printk.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#ifndef _DYNAMIC_PRINTK_H
2+
#define _DYNAMIC_PRINTK_H
3+
4+
#define DYNAMIC_DEBUG_HASH_BITS 6
5+
#define DEBUG_HASH_TABLE_SIZE (1 << DYNAMIC_DEBUG_HASH_BITS)
6+
7+
#define TYPE_BOOLEAN 1
8+
9+
#define DYNAMIC_ENABLED_ALL 0
10+
#define DYNAMIC_ENABLED_NONE 1
11+
#define DYNAMIC_ENABLED_SOME 2
12+
13+
extern int dynamic_enabled;
14+
15+
/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
16+
* bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
17+
* use independent hash functions, to reduce the chance of false positives.
18+
*/
19+
extern long long dynamic_printk_enabled;
20+
extern long long dynamic_printk_enabled2;
21+
22+
struct mod_debug {
23+
char *modname;
24+
char *logical_modname;
25+
char *flag_names;
26+
int type;
27+
int hash;
28+
int hash2;
29+
} __attribute__((aligned(8)));
30+
31+
int register_dynamic_debug_module(char *mod_name, int type, char *share_name,
32+
char *flags, int hash, int hash2);
33+
34+
#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
35+
extern int unregister_dynamic_debug_module(char *mod_name);
36+
extern int __dynamic_dbg_enabled_helper(char *modname, int type,
37+
int value, int hash);
38+
39+
#define __dynamic_dbg_enabled(module, type, value, level, hash) ({ \
40+
int __ret = 0; \
41+
if (unlikely((dynamic_printk_enabled & (1LL << DEBUG_HASH)) && \
42+
(dynamic_printk_enabled2 & (1LL << DEBUG_HASH2)))) \
43+
__ret = __dynamic_dbg_enabled_helper(module, type, \
44+
value, hash);\
45+
__ret; })
46+
47+
#define dynamic_pr_debug(fmt, ...) do { \
48+
static char mod_name[] \
49+
__attribute__((section("__verbose_strings"))) \
50+
= KBUILD_MODNAME; \
51+
static struct mod_debug descriptor \
52+
__used \
53+
__attribute__((section("__verbose"), aligned(8))) = \
54+
{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
55+
if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN, \
56+
0, 0, DEBUG_HASH)) \
57+
printk(KERN_DEBUG KBUILD_MODNAME ":" fmt, \
58+
##__VA_ARGS__); \
59+
} while (0)
60+
61+
#define dynamic_dev_dbg(dev, format, ...) do { \
62+
static char mod_name[] \
63+
__attribute__((section("__verbose_strings"))) \
64+
= KBUILD_MODNAME; \
65+
static struct mod_debug descriptor \
66+
__used \
67+
__attribute__((section("__verbose"), aligned(8))) = \
68+
{ mod_name, mod_name, NULL, TYPE_BOOLEAN, DEBUG_HASH, DEBUG_HASH2 };\
69+
if (__dynamic_dbg_enabled(KBUILD_MODNAME, TYPE_BOOLEAN, \
70+
0, 0, DEBUG_HASH)) \
71+
dev_printk(KERN_DEBUG, dev, \
72+
KBUILD_MODNAME ": " format, \
73+
##__VA_ARGS__); \
74+
} while (0)
75+
76+
#else
77+
78+
static inline int unregister_dynamic_debug_module(const char *mod_name)
79+
{
80+
return 0;
81+
}
82+
static inline int __dynamic_dbg_enabled_helper(char *modname, int type,
83+
int value, int hash)
84+
{
85+
return 0;
86+
}
87+
88+
#define __dynamic_dbg_enabled(module, type, value, level, hash) ({ 0; })
89+
#define dynamic_pr_debug(fmt, ...) do { } while (0)
90+
#define dynamic_dev_dbg(dev, format, ...) do { } while (0)
91+
#endif
92+
93+
#endif

include/linux/kernel.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/log2.h>
1717
#include <linux/typecheck.h>
1818
#include <linux/ratelimit.h>
19+
#include <linux/dynamic_printk.h>
1920
#include <asm/byteorder.h>
2021
#include <asm/bug.h>
2122

@@ -303,8 +304,12 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
303304
#define pr_info(fmt, arg...) \
304305
printk(KERN_INFO fmt, ##arg)
305306

306-
#ifdef DEBUG
307307
/* If you are writing a driver, please use dev_dbg instead */
308+
#if defined(CONFIG_DYNAMIC_PRINTK_DEBUG)
309+
#define pr_debug(fmt, ...) do { \
310+
dynamic_pr_debug(fmt, ##__VA_ARGS__); \
311+
} while (0)
312+
#elif defined(DEBUG)
308313
#define pr_debug(fmt, arg...) \
309314
printk(KERN_DEBUG fmt, ##arg)
310315
#else

include/linux/module.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,6 @@ struct module
345345
/* Reference counts */
346346
struct module_ref ref[NR_CPUS];
347347
#endif
348-
349348
};
350349
#ifndef MODULE_ARCH_INIT
351350
#define MODULE_ARCH_INIT {}

kernel/module.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,7 @@ sys_delete_module(const char __user *name_user, unsigned int flags)
784784
mutex_lock(&module_mutex);
785785
/* Store the name of the last unloaded module for diagnostic purposes */
786786
strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
787+
unregister_dynamic_debug_module(mod->name);
787788
free_module(mod);
788789

789790
out:
@@ -1783,6 +1784,33 @@ static inline void add_kallsyms(struct module *mod,
17831784
}
17841785
#endif /* CONFIG_KALLSYMS */
17851786

1787+
#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
1788+
static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex)
1789+
{
1790+
struct mod_debug *debug_info;
1791+
unsigned long pos, end;
1792+
unsigned int num_verbose;
1793+
1794+
pos = sechdrs[verboseindex].sh_addr;
1795+
num_verbose = sechdrs[verboseindex].sh_size /
1796+
sizeof(struct mod_debug);
1797+
end = pos + (num_verbose * sizeof(struct mod_debug));
1798+
1799+
for (; pos < end; pos += sizeof(struct mod_debug)) {
1800+
debug_info = (struct mod_debug *)pos;
1801+
register_dynamic_debug_module(debug_info->modname,
1802+
debug_info->type, debug_info->logical_modname,
1803+
debug_info->flag_names, debug_info->hash,
1804+
debug_info->hash2);
1805+
}
1806+
}
1807+
#else
1808+
static inline void dynamic_printk_setup(Elf_Shdr *sechdrs,
1809+
unsigned int verboseindex)
1810+
{
1811+
}
1812+
#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
1813+
17861814
static void *module_alloc_update_bounds(unsigned long size)
17871815
{
17881816
void *ret = module_alloc(size);
@@ -1831,6 +1859,7 @@ static noinline struct module *load_module(void __user *umod,
18311859
#endif
18321860
unsigned int markersindex;
18331861
unsigned int markersstringsindex;
1862+
unsigned int verboseindex;
18341863
struct module *mod;
18351864
long err = 0;
18361865
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
@@ -2117,6 +2146,7 @@ static noinline struct module *load_module(void __user *umod,
21172146
markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
21182147
markersstringsindex = find_sec(hdr, sechdrs, secstrings,
21192148
"__markers_strings");
2149+
verboseindex = find_sec(hdr, sechdrs, secstrings, "__verbose");
21202150

21212151
/* Now do relocations. */
21222152
for (i = 1; i < hdr->e_shnum; i++) {
@@ -2167,6 +2197,7 @@ static noinline struct module *load_module(void __user *umod,
21672197
marker_update_probe_range(mod->markers,
21682198
mod->markers + mod->num_markers);
21692199
#endif
2200+
dynamic_printk_setup(sechdrs, verboseindex);
21702201
err = module_finalize(hdr, sechdrs, mod);
21712202
if (err < 0)
21722203
goto cleanup;

lib/Kconfig.debug

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,61 @@ menuconfig BUILD_DOCSRC
807807

808808
Say N if you are unsure.
809809

810+
config DYNAMIC_PRINTK_DEBUG
811+
bool "Enable dynamic printk() call support"
812+
default n
813+
depends on PRINTK
814+
select PRINTK_DEBUG
815+
help
816+
817+
Compiles debug level messages into the kernel, which would not
818+
otherwise be available at runtime. These messages can then be
819+
enabled/disabled on a per module basis. This mechanism implicitly
820+
enables all pr_debug() and dev_dbg() calls. The impact of this
821+
compile option is a larger kernel text size of about 2%.
822+
823+
Usage:
824+
825+
Dynamic debugging is controlled by the debugfs file,
826+
dynamic_printk/modules. This file contains a list of the modules that
827+
can be enabled. The format of the file is the module name, followed
828+
by a set of flags that can be enabled. The first flag is always the
829+
'enabled' flag. For example:
830+
831+
<module_name> <enabled=0/1>
832+
.
833+
.
834+
.
835+
836+
<module_name> : Name of the module in which the debug call resides
837+
<enabled=0/1> : whether the messages are enabled or not
838+
839+
From a live system:
840+
841+
snd_hda_intel enabled=0
842+
fixup enabled=0
843+
driver enabled=0
844+
845+
Enable a module:
846+
847+
$echo "set enabled=1 <module_name>" > dynamic_printk/modules
848+
849+
Disable a module:
850+
851+
$echo "set enabled=0 <module_name>" > dynamic_printk/modules
852+
853+
Enable all modules:
854+
855+
$echo "set enabled=1 all" > dynamic_printk/modules
856+
857+
Disable all modules:
858+
859+
$echo "set enabled=0 all" > dynamic_printk/modules
860+
861+
Finally, passing "dynamic_printk" at the command line enables
862+
debugging for all modules. This mode can be turned off via the above
863+
disable command.
864+
810865
source "samples/Kconfig"
811866

812867
source "lib/Kconfig.kgdb"

lib/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ obj-$(CONFIG_HAVE_LMB) += lmb.o
8181

8282
obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o
8383

84+
obj-$(CONFIG_DYNAMIC_PRINTK_DEBUG) += dynamic_printk.o
85+
8486
hostprogs-y := gen_crc32table
8587
clean-files := crc32table.h
8688

0 commit comments

Comments
 (0)