dynamic_debug.h 5.08 KB
Newer Older
1
/* SPDX-License-Identifier: GPL-2.0 */
2 3 4
#ifndef _DYNAMIC_DEBUG_H
#define _DYNAMIC_DEBUG_H

5 6 7 8
#if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
#include <linux/jump_label.h>
#endif

9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * An instance of this structure is created in a special
 * ELF section at every dynamic debug callsite.  At runtime,
 * the special section is treated as an array of these.
 */
struct _ddebug {
	/*
	 * These fields are used to drive the user interface
	 * for selecting and displaying debug callsites.
	 */
	const char *modname;
	const char *function;
	const char *filename;
	const char *format;
23
	unsigned int lineno:18;
24
	/*
25 26
	 * The flags field controls the behaviour at the callsite.
	 * The bits here are changed dynamically when the user
27
	 * writes commands to <debugfs>/dynamic_debug/control
28
	 */
29 30
#define _DPRINTK_FLAGS_NONE	0
#define _DPRINTK_FLAGS_PRINT	(1<<0) /* printk() a message using the format */
31 32 33 34
#define _DPRINTK_FLAGS_INCL_MODNAME	(1<<1)
#define _DPRINTK_FLAGS_INCL_FUNCNAME	(1<<2)
#define _DPRINTK_FLAGS_INCL_LINENO	(1<<3)
#define _DPRINTK_FLAGS_INCL_TID		(1<<4)
35 36 37
#if defined DEBUG
#define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
#else
38
#define _DPRINTK_FLAGS_DEFAULT 0
39
#endif
40
	unsigned int flags:8;
41 42 43 44 45 46
#ifdef HAVE_JUMP_LABEL
	union {
		struct static_key_true dd_key_true;
		struct static_key_false dd_key_false;
	} key;
#endif
47 48 49 50 51 52 53
} __attribute__((aligned(8)));


int ddebug_add_module(struct _ddebug *tab, unsigned int n,
				const char *modname);

#if defined(CONFIG_DYNAMIC_DEBUG)
54
extern int ddebug_remove_module(const char *mod_name);
55
extern __printf(2, 3)
56
void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
57

58 59 60
extern int ddebug_dyndbg_module_param_cb(char *param, char *val,
					const char *modname);

61 62
struct device;

63
extern __printf(3, 4)
64 65
void __dynamic_dev_dbg(struct _ddebug *descriptor, const struct device *dev,
		       const char *fmt, ...);
66

67 68
struct net_device;

69
extern __printf(3, 4)
70 71 72
void __dynamic_netdev_dbg(struct _ddebug *descriptor,
			  const struct net_device *dev,
			  const char *fmt, ...);
73

74
#define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
75
	static struct _ddebug  __aligned(8)			\
76 77 78 79 80 81
	__attribute__((section("__verbose"))) name = {		\
		.modname = KBUILD_MODNAME,			\
		.function = __func__,				\
		.filename = __FILE__,				\
		.format = (fmt),				\
		.lineno = __LINE__,				\
82 83
		.flags = _DPRINTK_FLAGS_DEFAULT,		\
		dd_key_init(key, init)				\
84 85
	}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
#ifdef HAVE_JUMP_LABEL

#define dd_key_init(key, init) key = (init)

#ifdef DEBUG
#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
	DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_true, \
					  (STATIC_KEY_TRUE_INIT))

#define DYNAMIC_DEBUG_BRANCH(descriptor) \
	static_branch_likely(&descriptor.key.dd_key_true)
#else
#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
	DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, .key.dd_key_false, \
					  (STATIC_KEY_FALSE_INIT))

#define DYNAMIC_DEBUG_BRANCH(descriptor) \
	static_branch_unlikely(&descriptor.key.dd_key_false)
#endif

#else

#define dd_key_init(key, init)

#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
	DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, 0, 0)

#ifdef DEBUG
#define DYNAMIC_DEBUG_BRANCH(descriptor) \
	likely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
#else
#define DYNAMIC_DEBUG_BRANCH(descriptor) \
	unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)
#endif

#endif

123 124 125
#define dynamic_pr_debug(fmt, ...)				\
do {								\
	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);		\
126
	if (DYNAMIC_DEBUG_BRANCH(descriptor))			\
127 128 129 130 131 132
		__dynamic_pr_debug(&descriptor, pr_fmt(fmt),	\
				   ##__VA_ARGS__);		\
} while (0)

#define dynamic_dev_dbg(dev, fmt, ...)				\
do {								\
133
	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);		\
134
	if (DYNAMIC_DEBUG_BRANCH(descriptor))			\
135 136 137 138 139 140 141
		__dynamic_dev_dbg(&descriptor, dev, fmt,	\
				  ##__VA_ARGS__);		\
} while (0)

#define dynamic_netdev_dbg(dev, fmt, ...)			\
do {								\
	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt);		\
142
	if (DYNAMIC_DEBUG_BRANCH(descriptor))			\
143 144 145
		__dynamic_netdev_dbg(&descriptor, dev, fmt,	\
				     ##__VA_ARGS__);		\
} while (0)
146

147 148 149 150 151
#define dynamic_hex_dump(prefix_str, prefix_type, rowsize,	\
			 groupsize, buf, len, ascii)		\
do {								\
	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor,		\
		__builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\
152
	if (DYNAMIC_DEBUG_BRANCH(descriptor))			\
153 154 155 156 157
		print_hex_dump(KERN_DEBUG, prefix_str,		\
			       prefix_type, rowsize, groupsize,	\
			       buf, len, ascii);		\
} while (0)

158 159
#else

160 161 162
#include <linux/string.h>
#include <linux/errno.h>

163
static inline int ddebug_remove_module(const char *mod)
164 165 166 167
{
	return 0;
}

168 169 170 171
static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
						const char *modname)
{
	if (strstr(param, "dyndbg")) {
172 173
		/* avoid pr_warn(), which wants pr_fmt() fully defined */
		printk(KERN_WARNING "dyndbg param is supported only in "
174 175 176 177 178 179
			"CONFIG_DYNAMIC_DEBUG builds\n");
		return 0; /* allow and ignore */
	}
	return -EINVAL;
}

180 181
#define dynamic_pr_debug(fmt, ...)					\
	do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
182
#define dynamic_dev_dbg(dev, fmt, ...)					\
183
	do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
184 185 186
#endif

#endif