xref: /linux-6.15/include/linux/dynamic_debug.h (revision ca90fca7)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2e9d376f0SJason Baron #ifndef _DYNAMIC_DEBUG_H
3e9d376f0SJason Baron #define _DYNAMIC_DEBUG_H
4e9d376f0SJason Baron 
5e9666d10SMasahiro Yamada #if defined(CONFIG_JUMP_LABEL)
69049fc74SJason Baron #include <linux/jump_label.h>
79049fc74SJason Baron #endif
89049fc74SJason Baron 
9*ca90fca7SJim Cromie #include <linux/build_bug.h>
10*ca90fca7SJim Cromie 
11e9d376f0SJason Baron /*
12e9d376f0SJason Baron  * An instance of this structure is created in a special
13e9d376f0SJason Baron  * ELF section at every dynamic debug callsite.  At runtime,
14e9d376f0SJason Baron  * the special section is treated as an array of these.
15e9d376f0SJason Baron  */
16e9d376f0SJason Baron struct _ddebug {
17e9d376f0SJason Baron 	/*
18e9d376f0SJason Baron 	 * These fields are used to drive the user interface
19e9d376f0SJason Baron 	 * for selecting and displaying debug callsites.
20e9d376f0SJason Baron 	 */
21e9d376f0SJason Baron 	const char *modname;
22e9d376f0SJason Baron 	const char *function;
23e9d376f0SJason Baron 	const char *filename;
24e9d376f0SJason Baron 	const char *format;
25e703ddaeSJim Cromie 	unsigned int lineno:18;
26*ca90fca7SJim Cromie #define CLS_BITS 6
27*ca90fca7SJim Cromie 	unsigned int class_id:CLS_BITS;
28*ca90fca7SJim Cromie #define _DPRINTK_CLASS_DFLT		((1 << CLS_BITS) - 1)
29e9d376f0SJason Baron 	/*
30e9d376f0SJason Baron 	 * The flags field controls the behaviour at the callsite.
31e9d376f0SJason Baron 	 * The bits here are changed dynamically when the user
322b2f68b5SFlorian Ragwitz 	 * writes commands to <debugfs>/dynamic_debug/control
33e9d376f0SJason Baron 	 */
345ca7d2a6SJim Cromie #define _DPRINTK_FLAGS_NONE	0
35e9d376f0SJason Baron #define _DPRINTK_FLAGS_PRINT	(1<<0) /* printk() a message using the format */
368ba6ebf5SBart Van Assche #define _DPRINTK_FLAGS_INCL_MODNAME	(1<<1)
378ba6ebf5SBart Van Assche #define _DPRINTK_FLAGS_INCL_FUNCNAME	(1<<2)
388ba6ebf5SBart Van Assche #define _DPRINTK_FLAGS_INCL_LINENO	(1<<3)
398ba6ebf5SBart Van Assche #define _DPRINTK_FLAGS_INCL_TID		(1<<4)
40640d1eafSJim Cromie 
41640d1eafSJim Cromie #define _DPRINTK_FLAGS_INCL_ANY		\
42640d1eafSJim Cromie 	(_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
43640d1eafSJim Cromie 	 _DPRINTK_FLAGS_INCL_LINENO  | _DPRINTK_FLAGS_INCL_TID)
44640d1eafSJim Cromie 
45b558c96fSJim Cromie #if defined DEBUG
46b558c96fSJim Cromie #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
47b558c96fSJim Cromie #else
48e9d376f0SJason Baron #define _DPRINTK_FLAGS_DEFAULT 0
49b558c96fSJim Cromie #endif
50e9d376f0SJason Baron 	unsigned int flags:8;
51e9666d10SMasahiro Yamada #ifdef CONFIG_JUMP_LABEL
529049fc74SJason Baron 	union {
539049fc74SJason Baron 		struct static_key_true dd_key_true;
549049fc74SJason Baron 		struct static_key_false dd_key_false;
559049fc74SJason Baron 	} key;
569049fc74SJason Baron #endif
57e9d376f0SJason Baron } __attribute__((aligned(8)));
58e9d376f0SJason Baron 
59b7b4eebdSJim Cromie /* encapsulate linker provided built-in (or module) dyndbg data */
60b7b4eebdSJim Cromie struct _ddebug_info {
61b7b4eebdSJim Cromie 	struct _ddebug *descs;
62b7b4eebdSJim Cromie 	unsigned int num_descs;
63b7b4eebdSJim Cromie };
64e9d376f0SJason Baron 
65ceabef7dSOrson Zhai #if defined(CONFIG_DYNAMIC_DEBUG_CORE)
66a2d375edSJim Cromie 
67b7b4eebdSJim Cromie int ddebug_add_module(struct _ddebug_info *dyndbg, const char *modname);
68b7b4eebdSJim Cromie 
69ff49d74aSYehuda Sadeh extern int ddebug_remove_module(const char *mod_name);
70b9075fa9SJoe Perches extern __printf(2, 3)
71906d2015SJoe Perches void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
72e9d376f0SJason Baron 
73b48420c1SJim Cromie extern int ddebug_dyndbg_module_param_cb(char *param, char *val,
74b48420c1SJim Cromie 					const char *modname);
75b48420c1SJim Cromie 
76cbc46635SJoe Perches struct device;
77cbc46635SJoe Perches 
78b9075fa9SJoe Perches extern __printf(3, 4)
79906d2015SJoe Perches void __dynamic_dev_dbg(struct _ddebug *descriptor, const struct device *dev,
80b9075fa9SJoe Perches 		       const char *fmt, ...);
81cbc46635SJoe Perches 
82ffa10cb4SJason Baron struct net_device;
83ffa10cb4SJason Baron 
84b9075fa9SJoe Perches extern __printf(3, 4)
85906d2015SJoe Perches void __dynamic_netdev_dbg(struct _ddebug *descriptor,
86ffa10cb4SJason Baron 			  const struct net_device *dev,
87b9075fa9SJoe Perches 			  const char *fmt, ...);
88ffa10cb4SJason Baron 
89923abb9dSGal Pressman struct ib_device;
90923abb9dSGal Pressman 
91923abb9dSGal Pressman extern __printf(3, 4)
92923abb9dSGal Pressman void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
93923abb9dSGal Pressman 			 const struct ib_device *ibdev,
94923abb9dSGal Pressman 			 const char *fmt, ...);
95923abb9dSGal Pressman 
96*ca90fca7SJim Cromie #define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt)	\
97c0d2af63SJoe Perches 	static struct _ddebug  __aligned(8)			\
9833def849SJoe Perches 	__section("__dyndbg") name = {				\
9907613b0bSJason Baron 		.modname = KBUILD_MODNAME,			\
10007613b0bSJason Baron 		.function = __func__,				\
10107613b0bSJason Baron 		.filename = __FILE__,				\
10207613b0bSJason Baron 		.format = (fmt),				\
10307613b0bSJason Baron 		.lineno = __LINE__,				\
10407613b0bSJason Baron 		.flags = _DPRINTK_FLAGS_DEFAULT,		\
105*ca90fca7SJim Cromie 		.class_id = cls,				\
1062bdde670SRasmus Villemoes 		_DPRINTK_KEY_INIT				\
107*ca90fca7SJim Cromie 	};							\
108*ca90fca7SJim Cromie 	BUILD_BUG_ON_MSG(cls > _DPRINTK_CLASS_DFLT,		\
109*ca90fca7SJim Cromie 			 "classid value overflow")
110*ca90fca7SJim Cromie 
111*ca90fca7SJim Cromie #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)		\
112*ca90fca7SJim Cromie 	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_CLASS_DFLT, fmt)
11307613b0bSJason Baron 
114e9666d10SMasahiro Yamada #ifdef CONFIG_JUMP_LABEL
1159049fc74SJason Baron 
1169049fc74SJason Baron #ifdef DEBUG
1172bdde670SRasmus Villemoes 
1182bdde670SRasmus Villemoes #define _DPRINTK_KEY_INIT .key.dd_key_true = (STATIC_KEY_TRUE_INIT)
1199049fc74SJason Baron 
1209049fc74SJason Baron #define DYNAMIC_DEBUG_BRANCH(descriptor) \
1219049fc74SJason Baron 	static_branch_likely(&descriptor.key.dd_key_true)
1229049fc74SJason Baron #else
1232bdde670SRasmus Villemoes #define _DPRINTK_KEY_INIT .key.dd_key_false = (STATIC_KEY_FALSE_INIT)
1249049fc74SJason Baron 
1259049fc74SJason Baron #define DYNAMIC_DEBUG_BRANCH(descriptor) \
1269049fc74SJason Baron 	static_branch_unlikely(&descriptor.key.dd_key_false)
1279049fc74SJason Baron #endif
1289049fc74SJason Baron 
129a2d375edSJim Cromie #else /* !CONFIG_JUMP_LABEL */
1309049fc74SJason Baron 
1312bdde670SRasmus Villemoes #define _DPRINTK_KEY_INIT
1329049fc74SJason Baron 
1339049fc74SJason Baron #ifdef DEBUG
1349049fc74SJason Baron #define DYNAMIC_DEBUG_BRANCH(descriptor) \
1359049fc74SJason Baron 	likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
1369049fc74SJason Baron #else
1379049fc74SJason Baron #define DYNAMIC_DEBUG_BRANCH(descriptor) \
1389049fc74SJason Baron 	unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
1399049fc74SJason Baron #endif
1409049fc74SJason Baron 
141a2d375edSJim Cromie #endif /* CONFIG_JUMP_LABEL */
1429049fc74SJason Baron 
143*ca90fca7SJim Cromie /*
144*ca90fca7SJim Cromie  * Factory macros: ($prefix)dynamic_func_call($suffix)
145*ca90fca7SJim Cromie  *
146*ca90fca7SJim Cromie  * Lower layer (with __ prefix) gets the callsite metadata, and wraps
147*ca90fca7SJim Cromie  * the func inside a debug-branch/static-key construct.  Upper layer
148*ca90fca7SJim Cromie  * (with _ prefix) does the UNIQUE_ID once, so that lower can ref the
149*ca90fca7SJim Cromie  * name/label multiple times, and tie the elements together.
150*ca90fca7SJim Cromie  * Multiple flavors:
151*ca90fca7SJim Cromie  * (|_cls):	adds in _DPRINT_CLASS_DFLT as needed
152*ca90fca7SJim Cromie  * (|_no_desc):	former gets callsite descriptor as 1st arg (for prdbgs)
153*ca90fca7SJim Cromie  */
154*ca90fca7SJim Cromie #define __dynamic_func_call_cls(id, cls, fmt, func, ...) do {	\
155*ca90fca7SJim Cromie 	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);	\
15647cdd64bSRasmus Villemoes 	if (DYNAMIC_DEBUG_BRANCH(id))				\
15747cdd64bSRasmus Villemoes 		func(&id, ##__VA_ARGS__);			\
158e9d376f0SJason Baron } while (0)
159*ca90fca7SJim Cromie #define __dynamic_func_call(id, fmt, func, ...)				\
160*ca90fca7SJim Cromie 	__dynamic_func_call_cls(id, _DPRINTK_CLASS_DFLT, fmt,		\
161*ca90fca7SJim Cromie 				func, ##__VA_ARGS__)
162e9d376f0SJason Baron 
163*ca90fca7SJim Cromie #define __dynamic_func_call_cls_no_desc(id, cls, fmt, func, ...) do {	\
164*ca90fca7SJim Cromie 	DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt);		\
16547cdd64bSRasmus Villemoes 	if (DYNAMIC_DEBUG_BRANCH(id))					\
16647cdd64bSRasmus Villemoes 		func(__VA_ARGS__);					\
16747cdd64bSRasmus Villemoes } while (0)
168*ca90fca7SJim Cromie #define __dynamic_func_call_no_desc(id, fmt, func, ...)			\
169*ca90fca7SJim Cromie 	__dynamic_func_call_cls_no_desc(id, _DPRINTK_CLASS_DFLT,	\
170*ca90fca7SJim Cromie 					fmt, func, ##__VA_ARGS__)
17147cdd64bSRasmus Villemoes 
17247cdd64bSRasmus Villemoes /*
17347cdd64bSRasmus Villemoes  * "Factory macro" for generating a call to func, guarded by a
174e5ebffe1SJim Cromie  * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be
17547cdd64bSRasmus Villemoes  * initialized using the fmt argument. The function will be called with
17647cdd64bSRasmus Villemoes  * the address of the descriptor as first argument, followed by all
17747cdd64bSRasmus Villemoes  * the varargs. Note that fmt is repeated in invocations of this
17847cdd64bSRasmus Villemoes  * macro.
17947cdd64bSRasmus Villemoes  */
180*ca90fca7SJim Cromie #define _dynamic_func_call_cls(cls, fmt, func, ...)			\
181*ca90fca7SJim Cromie 	__dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)
18247cdd64bSRasmus Villemoes #define _dynamic_func_call(fmt, func, ...)				\
183*ca90fca7SJim Cromie 	_dynamic_func_call_cls(_DPRINTK_CLASS_DFLT, fmt, func, ##__VA_ARGS__)
184*ca90fca7SJim Cromie 
18547cdd64bSRasmus Villemoes /*
18647cdd64bSRasmus Villemoes  * A variant that does the same, except that the descriptor is not
18747cdd64bSRasmus Villemoes  * passed as the first argument to the function; it is only called
18847cdd64bSRasmus Villemoes  * with precisely the macro's varargs.
18947cdd64bSRasmus Villemoes  */
190*ca90fca7SJim Cromie #define _dynamic_func_call_cls_no_desc(cls, fmt, func, ...)		\
191*ca90fca7SJim Cromie 	__dynamic_func_call_cls_no_desc(__UNIQUE_ID(ddebug), cls, fmt,	\
192*ca90fca7SJim Cromie 					func, ##__VA_ARGS__)
19347cdd64bSRasmus Villemoes #define _dynamic_func_call_no_desc(fmt, func, ...)			\
194*ca90fca7SJim Cromie 	_dynamic_func_call_cls_no_desc(_DPRINTK_CLASS_DFLT, fmt,	\
195*ca90fca7SJim Cromie 				       func, ##__VA_ARGS__)
196*ca90fca7SJim Cromie 
197*ca90fca7SJim Cromie #define dynamic_pr_debug_cls(cls, fmt, ...)				\
198*ca90fca7SJim Cromie 	_dynamic_func_call_cls(cls, fmt, __dynamic_pr_debug,		\
199*ca90fca7SJim Cromie 			   pr_fmt(fmt), ##__VA_ARGS__)
20047cdd64bSRasmus Villemoes 
20147cdd64bSRasmus Villemoes #define dynamic_pr_debug(fmt, ...)				\
20247cdd64bSRasmus Villemoes 	_dynamic_func_call(fmt, __dynamic_pr_debug,		\
20347cdd64bSRasmus Villemoes 			   pr_fmt(fmt), ##__VA_ARGS__)
20447cdd64bSRasmus Villemoes 
20507613b0bSJason Baron #define dynamic_dev_dbg(dev, fmt, ...)				\
20647cdd64bSRasmus Villemoes 	_dynamic_func_call(fmt, __dynamic_dev_dbg, 		\
20747cdd64bSRasmus Villemoes 			   dev, fmt, ##__VA_ARGS__)
208e9d376f0SJason Baron 
20907613b0bSJason Baron #define dynamic_netdev_dbg(dev, fmt, ...)			\
21047cdd64bSRasmus Villemoes 	_dynamic_func_call(fmt, __dynamic_netdev_dbg,		\
21147cdd64bSRasmus Villemoes 			   dev, fmt, ##__VA_ARGS__)
212ffa10cb4SJason Baron 
213923abb9dSGal Pressman #define dynamic_ibdev_dbg(dev, fmt, ...)			\
214923abb9dSGal Pressman 	_dynamic_func_call(fmt, __dynamic_ibdev_dbg,		\
215923abb9dSGal Pressman 			   dev, fmt, ##__VA_ARGS__)
216923abb9dSGal Pressman 
2177a555613SVladimir Kondratiev #define dynamic_hex_dump(prefix_str, prefix_type, rowsize,		\
2187a555613SVladimir Kondratiev 			 groupsize, buf, len, ascii)			\
21947cdd64bSRasmus Villemoes 	_dynamic_func_call_no_desc(__builtin_constant_p(prefix_str) ? prefix_str : "hexdump", \
22047cdd64bSRasmus Villemoes 				   print_hex_dump,			\
22147cdd64bSRasmus Villemoes 				   KERN_DEBUG, prefix_str, prefix_type,	\
22247cdd64bSRasmus Villemoes 				   rowsize, groupsize, buf, len, ascii)
2237a555613SVladimir Kondratiev 
224a2d375edSJim Cromie #else /* !CONFIG_DYNAMIC_DEBUG_CORE */
225e9d376f0SJason Baron 
226b48420c1SJim Cromie #include <linux/string.h>
227b48420c1SJim Cromie #include <linux/errno.h>
228a2d375edSJim Cromie #include <linux/printk.h>
229b48420c1SJim Cromie 
230b7b4eebdSJim Cromie static inline int ddebug_add_module(struct _ddebug_info *dinfo, const char *modname)
231a4507fedSRasmus Villemoes {
232a4507fedSRasmus Villemoes 	return 0;
233a4507fedSRasmus Villemoes }
234a4507fedSRasmus Villemoes 
235ff49d74aSYehuda Sadeh static inline int ddebug_remove_module(const char *mod)
236e9d376f0SJason Baron {
237e9d376f0SJason Baron 	return 0;
238e9d376f0SJason Baron }
239e9d376f0SJason Baron 
240b48420c1SJim Cromie static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
241b48420c1SJim Cromie 						const char *modname)
242b48420c1SJim Cromie {
24385d6b66dSJim Cromie 	if (!strcmp(param, "dyndbg")) {
244516cf1beSJim Cromie 		/* avoid pr_warn(), which wants pr_fmt() fully defined */
245516cf1beSJim Cromie 		printk(KERN_WARNING "dyndbg param is supported only in "
246b48420c1SJim Cromie 			"CONFIG_DYNAMIC_DEBUG builds\n");
247b48420c1SJim Cromie 		return 0; /* allow and ignore */
248b48420c1SJim Cromie 	}
249b48420c1SJim Cromie 	return -EINVAL;
250b48420c1SJim Cromie }
251b48420c1SJim Cromie 
25200b55864SJoe Perches #define dynamic_pr_debug(fmt, ...)					\
25300b55864SJoe Perches 	do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
254be70e267SPhilipp Reisner #define dynamic_dev_dbg(dev, fmt, ...)					\
25500b55864SJoe Perches 	do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
256011c7289SArnd Bergmann #define dynamic_hex_dump(prefix_str, prefix_type, rowsize,		\
257011c7289SArnd Bergmann 			 groupsize, buf, len, ascii)			\
258011c7289SArnd Bergmann 	do { if (0)							\
259011c7289SArnd Bergmann 		print_hex_dump(KERN_DEBUG, prefix_str, prefix_type,	\
260011c7289SArnd Bergmann 				rowsize, groupsize, buf, len, ascii);	\
261011c7289SArnd Bergmann 	} while (0)
262a2d375edSJim Cromie 
263a2d375edSJim Cromie #endif /* !CONFIG_DYNAMIC_DEBUG_CORE */
264e9d376f0SJason Baron 
265e9d376f0SJason Baron #endif
266