Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
e9d376f0 JB |
2 | #ifndef _DYNAMIC_DEBUG_H |
3 | #define _DYNAMIC_DEBUG_H | |
4 | ||
9049fc74 JB |
5 | #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL) |
6 | #include <linux/jump_label.h> | |
7 | #endif | |
8 | ||
e9d376f0 JB |
9 | /* |
10 | * An instance of this structure is created in a special | |
11 | * ELF section at every dynamic debug callsite. At runtime, | |
12 | * the special section is treated as an array of these. | |
13 | */ | |
14 | struct _ddebug { | |
15 | /* | |
16 | * These fields are used to drive the user interface | |
17 | * for selecting and displaying debug callsites. | |
18 | */ | |
19 | const char *modname; | |
20 | const char *function; | |
21 | const char *filename; | |
22 | const char *format; | |
e703ddae | 23 | unsigned int lineno:18; |
e9d376f0 | 24 | /* |
3faa2860 JC |
25 | * The flags field controls the behaviour at the callsite. |
26 | * The bits here are changed dynamically when the user | |
2b2f68b5 | 27 | * writes commands to <debugfs>/dynamic_debug/control |
e9d376f0 | 28 | */ |
5ca7d2a6 JC |
29 | #define _DPRINTK_FLAGS_NONE 0 |
30 | #define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */ | |
8ba6ebf5 BVA |
31 | #define _DPRINTK_FLAGS_INCL_MODNAME (1<<1) |
32 | #define _DPRINTK_FLAGS_INCL_FUNCNAME (1<<2) | |
33 | #define _DPRINTK_FLAGS_INCL_LINENO (1<<3) | |
34 | #define _DPRINTK_FLAGS_INCL_TID (1<<4) | |
b558c96f JC |
35 | #if defined DEBUG |
36 | #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT | |
37 | #else | |
e9d376f0 | 38 | #define _DPRINTK_FLAGS_DEFAULT 0 |
b558c96f | 39 | #endif |
e9d376f0 | 40 | unsigned int flags:8; |
9049fc74 JB |
41 | #ifdef HAVE_JUMP_LABEL |
42 | union { | |
43 | struct static_key_true dd_key_true; | |
44 | struct static_key_false dd_key_false; | |
45 | } key; | |
46 | #endif | |
e9d376f0 JB |
47 | } __attribute__((aligned(8))); |
48 | ||
49 | ||
50 | int ddebug_add_module(struct _ddebug *tab, unsigned int n, | |
51 | const char *modname); | |
52 | ||
53 | #if defined(CONFIG_DYNAMIC_DEBUG) | |
ff49d74a | 54 | extern int ddebug_remove_module(const char *mod_name); |
b9075fa9 | 55 | extern __printf(2, 3) |
906d2015 | 56 | void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...); |
e9d376f0 | 57 | |
b48420c1 JC |
58 | extern int ddebug_dyndbg_module_param_cb(char *param, char *val, |
59 | const char *modname); | |
60 | ||
cbc46635 JP |
61 | struct device; |
62 | ||
b9075fa9 | 63 | extern __printf(3, 4) |
906d2015 JP |
64 | void __dynamic_dev_dbg(struct _ddebug *descriptor, const struct device *dev, |
65 | const char *fmt, ...); | |
cbc46635 | 66 | |
ffa10cb4 JB |
67 | struct net_device; |
68 | ||
b9075fa9 | 69 | extern __printf(3, 4) |
906d2015 JP |
70 | void __dynamic_netdev_dbg(struct _ddebug *descriptor, |
71 | const struct net_device *dev, | |
72 | const char *fmt, ...); | |
ffa10cb4 | 73 | |
9049fc74 | 74 | #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init) \ |
c0d2af63 | 75 | static struct _ddebug __aligned(8) \ |
07613b0b JB |
76 | __attribute__((section("__verbose"))) name = { \ |
77 | .modname = KBUILD_MODNAME, \ | |
78 | .function = __func__, \ | |
79 | .filename = __FILE__, \ | |
80 | .format = (fmt), \ | |
81 | .lineno = __LINE__, \ | |
9049fc74 JB |
82 | .flags = _DPRINTK_FLAGS_DEFAULT, \ |
83 | dd_key_init(key, init) \ | |
07613b0b JB |
84 | } |
85 | ||
9049fc74 JB |
86 | #ifdef HAVE_JUMP_LABEL |
87 | ||
88 | #define dd_key_init(key, init) key = (init) | |
89 | ||
90 | #ifdef DEBUG | |
91 | #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \ | |
92 | DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_true, \ | |
93 | (STATIC_KEY_TRUE_INIT)) | |
94 | ||
95 | #define DYNAMIC_DEBUG_BRANCH(descriptor) \ | |
96 | static_branch_likely(&descriptor.key.dd_key_true) | |
97 | #else | |
98 | #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \ | |
99 | DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_false, \ | |
100 | (STATIC_KEY_FALSE_INIT)) | |
101 | ||
102 | #define DYNAMIC_DEBUG_BRANCH(descriptor) \ | |
103 | static_branch_unlikely(&descriptor.key.dd_key_false) | |
104 | #endif | |
105 | ||
106 | #else | |
107 | ||
108 | #define dd_key_init(key, init) | |
109 | ||
110 | #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \ | |
111 | DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, 0, 0) | |
112 | ||
113 | #ifdef DEBUG | |
114 | #define DYNAMIC_DEBUG_BRANCH(descriptor) \ | |
115 | likely(descriptor.flags & _DPRINTK_FLAGS_PRINT) | |
116 | #else | |
117 | #define DYNAMIC_DEBUG_BRANCH(descriptor) \ | |
118 | unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT) | |
119 | #endif | |
120 | ||
121 | #endif | |
122 | ||
07613b0b JB |
123 | #define dynamic_pr_debug(fmt, ...) \ |
124 | do { \ | |
125 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ | |
9049fc74 | 126 | if (DYNAMIC_DEBUG_BRANCH(descriptor)) \ |
07613b0b JB |
127 | __dynamic_pr_debug(&descriptor, pr_fmt(fmt), \ |
128 | ##__VA_ARGS__); \ | |
129 | } while (0) | |
130 | ||
131 | #define dynamic_dev_dbg(dev, fmt, ...) \ | |
132 | do { \ | |
87e6f968 | 133 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ |
9049fc74 | 134 | if (DYNAMIC_DEBUG_BRANCH(descriptor)) \ |
07613b0b JB |
135 | __dynamic_dev_dbg(&descriptor, dev, fmt, \ |
136 | ##__VA_ARGS__); \ | |
137 | } while (0) | |
138 | ||
139 | #define dynamic_netdev_dbg(dev, fmt, ...) \ | |
140 | do { \ | |
141 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ | |
9049fc74 | 142 | if (DYNAMIC_DEBUG_BRANCH(descriptor)) \ |
07613b0b JB |
143 | __dynamic_netdev_dbg(&descriptor, dev, fmt, \ |
144 | ##__VA_ARGS__); \ | |
145 | } while (0) | |
ffa10cb4 | 146 | |
7a555613 VK |
147 | #define dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ |
148 | groupsize, buf, len, ascii) \ | |
149 | do { \ | |
150 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \ | |
151 | __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\ | |
9049fc74 | 152 | if (DYNAMIC_DEBUG_BRANCH(descriptor)) \ |
7a555613 VK |
153 | print_hex_dump(KERN_DEBUG, prefix_str, \ |
154 | prefix_type, rowsize, groupsize, \ | |
155 | buf, len, ascii); \ | |
156 | } while (0) | |
157 | ||
e9d376f0 JB |
158 | #else |
159 | ||
b48420c1 JC |
160 | #include <linux/string.h> |
161 | #include <linux/errno.h> | |
162 | ||
ff49d74a | 163 | static inline int ddebug_remove_module(const char *mod) |
e9d376f0 JB |
164 | { |
165 | return 0; | |
166 | } | |
167 | ||
b48420c1 JC |
168 | static inline int ddebug_dyndbg_module_param_cb(char *param, char *val, |
169 | const char *modname) | |
170 | { | |
171 | if (strstr(param, "dyndbg")) { | |
516cf1be JC |
172 | /* avoid pr_warn(), which wants pr_fmt() fully defined */ |
173 | printk(KERN_WARNING "dyndbg param is supported only in " | |
b48420c1 JC |
174 | "CONFIG_DYNAMIC_DEBUG builds\n"); |
175 | return 0; /* allow and ignore */ | |
176 | } | |
177 | return -EINVAL; | |
178 | } | |
179 | ||
00b55864 JP |
180 | #define dynamic_pr_debug(fmt, ...) \ |
181 | do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0) | |
be70e267 | 182 | #define dynamic_dev_dbg(dev, fmt, ...) \ |
00b55864 | 183 | do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0) |
e9d376f0 JB |
184 | #endif |
185 | ||
186 | #endif |