xref: /linux-6.15/include/linux/dynamic_debug.h (revision 9049fc74)
1e9d376f0SJason Baron #ifndef _DYNAMIC_DEBUG_H
2e9d376f0SJason Baron #define _DYNAMIC_DEBUG_H
3e9d376f0SJason Baron 
4*9049fc74SJason Baron #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
5*9049fc74SJason Baron #include <linux/jump_label.h>
6*9049fc74SJason Baron #endif
7*9049fc74SJason Baron 
8e9d376f0SJason Baron /*
9e9d376f0SJason Baron  * An instance of this structure is created in a special
10e9d376f0SJason Baron  * ELF section at every dynamic debug callsite.  At runtime,
11e9d376f0SJason Baron  * the special section is treated as an array of these.
12e9d376f0SJason Baron  */
13e9d376f0SJason Baron struct _ddebug {
14e9d376f0SJason Baron 	/*
15e9d376f0SJason Baron 	 * These fields are used to drive the user interface
16e9d376f0SJason Baron 	 * for selecting and displaying debug callsites.
17e9d376f0SJason Baron 	 */
18e9d376f0SJason Baron 	const char *modname;
19e9d376f0SJason Baron 	const char *function;
20e9d376f0SJason Baron 	const char *filename;
21e9d376f0SJason Baron 	const char *format;
22e703ddaeSJim Cromie 	unsigned int lineno:18;
23e9d376f0SJason Baron 	/*
24e9d376f0SJason Baron 	 * The flags field controls the behaviour at the callsite.
25e9d376f0SJason Baron 	 * The bits here are changed dynamically when the user
262b2f68b5SFlorian Ragwitz 	 * writes commands to <debugfs>/dynamic_debug/control
27e9d376f0SJason Baron 	 */
285ca7d2a6SJim Cromie #define _DPRINTK_FLAGS_NONE	0
29e9d376f0SJason Baron #define _DPRINTK_FLAGS_PRINT	(1<<0) /* printk() a message using the format */
308ba6ebf5SBart Van Assche #define _DPRINTK_FLAGS_INCL_MODNAME	(1<<1)
318ba6ebf5SBart Van Assche #define _DPRINTK_FLAGS_INCL_FUNCNAME	(1<<2)
328ba6ebf5SBart Van Assche #define _DPRINTK_FLAGS_INCL_LINENO	(1<<3)
338ba6ebf5SBart Van Assche #define _DPRINTK_FLAGS_INCL_TID		(1<<4)
34b558c96fSJim Cromie #if defined DEBUG
35b558c96fSJim Cromie #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
36b558c96fSJim Cromie #else
37e9d376f0SJason Baron #define _DPRINTK_FLAGS_DEFAULT 0
38b558c96fSJim Cromie #endif
39e9d376f0SJason Baron 	unsigned int flags:8;
40*9049fc74SJason Baron #ifdef HAVE_JUMP_LABEL
41*9049fc74SJason Baron 	union {
42*9049fc74SJason Baron 		struct static_key_true dd_key_true;
43*9049fc74SJason Baron 		struct static_key_false dd_key_false;
44*9049fc74SJason Baron 	} key;
45*9049fc74SJason Baron #endif
46e9d376f0SJason Baron } __attribute__((aligned(8)));
47e9d376f0SJason Baron 
48e9d376f0SJason Baron 
49e9d376f0SJason Baron int ddebug_add_module(struct _ddebug *tab, unsigned int n,
50e9d376f0SJason Baron 				const char *modname);
51e9d376f0SJason Baron 
52e9d376f0SJason Baron #if defined(CONFIG_DYNAMIC_DEBUG)
53ff49d74aSYehuda Sadeh extern int ddebug_remove_module(const char *mod_name);
54b9075fa9SJoe Perches extern __printf(2, 3)
55906d2015SJoe Perches void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
56e9d376f0SJason Baron 
57b48420c1SJim Cromie extern int ddebug_dyndbg_module_param_cb(char *param, char *val,
58b48420c1SJim Cromie 					const char *modname);
59b48420c1SJim Cromie 
60cbc46635SJoe Perches struct device;
61cbc46635SJoe Perches 
62b9075fa9SJoe Perches extern __printf(3, 4)
63906d2015SJoe Perches void __dynamic_dev_dbg(struct _ddebug *descriptor, const struct device *dev,
64b9075fa9SJoe Perches 		       const char *fmt, ...);
65cbc46635SJoe Perches 
66ffa10cb4SJason Baron struct net_device;
67ffa10cb4SJason Baron 
68b9075fa9SJoe Perches extern __printf(3, 4)
69906d2015SJoe Perches void __dynamic_netdev_dbg(struct _ddebug *descriptor,
70ffa10cb4SJason Baron 			  const struct net_device *dev,
71b9075fa9SJoe Perches 			  const char *fmt, ...);
72ffa10cb4SJason Baron 
73*9049fc74SJason Baron #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
74c0d2af63SJoe Perches 	static struct _ddebug  __aligned(8)			\
7507613b0bSJason Baron 	__attribute__((section("__verbose"))) name = {		\
7607613b0bSJason Baron 		.modname = KBUILD_MODNAME,			\
7707613b0bSJason Baron 		.function = __func__,				\
7807613b0bSJason Baron 		.filename = __FILE__,				\
7907613b0bSJason Baron 		.format = (fmt),				\
8007613b0bSJason Baron 		.lineno = __LINE__,				\
8107613b0bSJason Baron 		.flags = _DPRINTK_FLAGS_DEFAULT,		\
82*9049fc74SJason Baron 		dd_key_init(key, init)				\
8307613b0bSJason Baron 	}
8407613b0bSJason Baron 
85*9049fc74SJason Baron #ifdef HAVE_JUMP_LABEL
86*9049fc74SJason Baron 
87*9049fc74SJason Baron #define dd_key_init(key, init) key = (init)
88*9049fc74SJason Baron 
89*9049fc74SJason Baron #ifdef DEBUG
90*9049fc74SJason Baron #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
91*9049fc74SJason Baron 	DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_true, \
92*9049fc74SJason Baron 					  (STATIC_KEY_TRUE_INIT))
93*9049fc74SJason Baron 
94*9049fc74SJason Baron #define DYNAMIC_DEBUG_BRANCH(descriptor) \
95*9049fc74SJason Baron 	static_branch_likely(&descriptor.key.dd_key_true)
96*9049fc74SJason Baron #else
97*9049fc74SJason Baron #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
98*9049fc74SJason Baron 	DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_false, \
99*9049fc74SJason Baron 					  (STATIC_KEY_FALSE_INIT))
100*9049fc74SJason Baron 
101*9049fc74SJason Baron #define DYNAMIC_DEBUG_BRANCH(descriptor) \
102*9049fc74SJason Baron 	static_branch_unlikely(&descriptor.key.dd_key_false)
103*9049fc74SJason Baron #endif
104*9049fc74SJason Baron 
105*9049fc74SJason Baron #else
106*9049fc74SJason Baron 
107*9049fc74SJason Baron #define dd_key_init(key, init)
108*9049fc74SJason Baron 
109*9049fc74SJason Baron #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
110*9049fc74SJason Baron 	DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, 0, 0)
111*9049fc74SJason Baron 
112*9049fc74SJason Baron #ifdef DEBUG
113*9049fc74SJason Baron #define DYNAMIC_DEBUG_BRANCH(descriptor) \
114*9049fc74SJason Baron 	likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
115*9049fc74SJason Baron #else
116*9049fc74SJason Baron #define DYNAMIC_DEBUG_BRANCH(descriptor) \
117*9049fc74SJason Baron 	unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
118*9049fc74SJason Baron #endif
119*9049fc74SJason Baron 
120*9049fc74SJason Baron #endif
121*9049fc74SJason Baron 
12207613b0bSJason Baron #define dynamic_pr_debug(fmt, ...)				\
12307613b0bSJason Baron do {								\
12407613b0bSJason Baron 	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);		\
125*9049fc74SJason Baron 	if (DYNAMIC_DEBUG_BRANCH(descriptor))			\
12607613b0bSJason Baron 		__dynamic_pr_debug(&descriptor, pr_fmt(fmt),	\
12707613b0bSJason Baron 				   ##__VA_ARGS__);		\
128e9d376f0SJason Baron } while (0)
129e9d376f0SJason Baron 
13007613b0bSJason Baron #define dynamic_dev_dbg(dev, fmt, ...)				\
13107613b0bSJason Baron do {								\
13207613b0bSJason Baron 	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);		\
133*9049fc74SJason Baron 	if (DYNAMIC_DEBUG_BRANCH(descriptor))			\
13407613b0bSJason Baron 		__dynamic_dev_dbg(&descriptor, dev, fmt,	\
13507613b0bSJason Baron 				  ##__VA_ARGS__);		\
136e9d376f0SJason Baron } while (0)
137e9d376f0SJason Baron 
13807613b0bSJason Baron #define dynamic_netdev_dbg(dev, fmt, ...)			\
13907613b0bSJason Baron do {								\
14007613b0bSJason Baron 	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);		\
141*9049fc74SJason Baron 	if (DYNAMIC_DEBUG_BRANCH(descriptor))			\
14207613b0bSJason Baron 		__dynamic_netdev_dbg(&descriptor, dev, fmt,	\
14307613b0bSJason Baron 				     ##__VA_ARGS__);		\
144ffa10cb4SJason Baron } while (0)
145ffa10cb4SJason Baron 
1467a555613SVladimir Kondratiev #define dynamic_hex_dump(prefix_str, prefix_type, rowsize,	\
1477a555613SVladimir Kondratiev 			 groupsize, buf, len, ascii)		\
1487a555613SVladimir Kondratiev do {								\
1497a555613SVladimir Kondratiev 	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor,		\
1507a555613SVladimir Kondratiev 		__builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\
151*9049fc74SJason Baron 	if (DYNAMIC_DEBUG_BRANCH(descriptor))			\
1527a555613SVladimir Kondratiev 		print_hex_dump(KERN_DEBUG, prefix_str,		\
1537a555613SVladimir Kondratiev 			       prefix_type, rowsize, groupsize,	\
1547a555613SVladimir Kondratiev 			       buf, len, ascii);		\
1557a555613SVladimir Kondratiev } while (0)
1567a555613SVladimir Kondratiev 
157e9d376f0SJason Baron #else
158e9d376f0SJason Baron 
159b48420c1SJim Cromie #include <linux/string.h>
160b48420c1SJim Cromie #include <linux/errno.h>
161b48420c1SJim Cromie 
162ff49d74aSYehuda Sadeh static inline int ddebug_remove_module(const char *mod)
163e9d376f0SJason Baron {
164e9d376f0SJason Baron 	return 0;
165e9d376f0SJason Baron }
166e9d376f0SJason Baron 
167b48420c1SJim Cromie static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
168b48420c1SJim Cromie 						const char *modname)
169b48420c1SJim Cromie {
170b48420c1SJim Cromie 	if (strstr(param, "dyndbg")) {
171516cf1beSJim Cromie 		/* avoid pr_warn(), which wants pr_fmt() fully defined */
172516cf1beSJim Cromie 		printk(KERN_WARNING "dyndbg param is supported only in "
173b48420c1SJim Cromie 			"CONFIG_DYNAMIC_DEBUG builds\n");
174b48420c1SJim Cromie 		return 0; /* allow and ignore */
175b48420c1SJim Cromie 	}
176b48420c1SJim Cromie 	return -EINVAL;
177b48420c1SJim Cromie }
178b48420c1SJim Cromie 
17900b55864SJoe Perches #define dynamic_pr_debug(fmt, ...)					\
18000b55864SJoe Perches 	do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
181be70e267SPhilipp Reisner #define dynamic_dev_dbg(dev, fmt, ...)					\
18200b55864SJoe Perches 	do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
183e9d376f0SJason Baron #endif
184e9d376f0SJason Baron 
185e9d376f0SJason Baron #endif
186