Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366/* SPDX-License-Identifier: GPL-2.0 */#ifndef _DYNAMIC_DEBUG_H#define _DYNAMIC_DEBUG_H
#if defined(CONFIG_JUMP_LABEL)#include <linux/jump_label.h>#endif
#include <linux/build_bug.h>
/* * 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; unsigned int lineno:18;#define CLS_BITS 6 unsigned int class_id:CLS_BITS;#define _DPRINTK_CLASS_DFLT ((1 << CLS_BITS) - 1) /* * The flags field controls the behaviour at the callsite. * The bits here are changed dynamically when the user * writes commands to <debugfs>/dynamic_debug/control */#define _DPRINTK_FLAGS_NONE 0#define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */#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)#define _DPRINTK_FLAGS_INCL_SOURCENAME (1<<5)#define _DPRINTK_FLAGS_INCL_STACK (1<<6)
#define _DPRINTK_FLAGS_INCL_ANY \ (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\ _DPRINTK_FLAGS_INCL_LINENO | _DPRINTK_FLAGS_INCL_TID |\ _DPRINTK_FLAGS_INCL_SOURCENAME | _DPRINTK_FLAGS_INCL_STACK)
#if defined DEBUG#define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT#else#define _DPRINTK_FLAGS_DEFAULT 0#endif unsigned int flags:8;#ifdef CONFIG_JUMP_LABEL union { struct static_key_true dd_key_true; struct static_key_false dd_key_false; } key;#endif} __attribute__((aligned(8)));
enum class_map_type { DD_CLASS_TYPE_DISJOINT_BITS, /** * DD_CLASS_TYPE_DISJOINT_BITS: classes are independent, one per bit. * expecting hex input. Built for drm.debug, basis for other types. */ DD_CLASS_TYPE_LEVEL_NUM, /** * DD_CLASS_TYPE_LEVEL_NUM: input is numeric level, 0-N. * N turns on just bits N-1 .. 0, so N=0 turns all bits off. */ DD_CLASS_TYPE_DISJOINT_NAMES, /** * DD_CLASS_TYPE_DISJOINT_NAMES: input is a CSV of [+-]CLASS_NAMES, * classes are independent, like _DISJOINT_BITS. */ DD_CLASS_TYPE_LEVEL_NAMES, /** * DD_CLASS_TYPE_LEVEL_NAMES: input is a CSV of [+-]CLASS_NAMES, * intended for names like: INFO,DEBUG,TRACE, with a module prefix * avoid EMERG,ALERT,CRIT,ERR,WARNING: they're not debug */};
struct ddebug_class_map { struct list_head link; struct module *mod; const char *mod_name; /* needed for builtins */ const char **class_names; const int length; const int base; /* index of 1st .class_id, allows split/shared space */ enum class_map_type map_type;};
/** * DECLARE_DYNDBG_CLASSMAP - declare classnames known by a module * @_var: a struct ddebug_class_map, passed to module_param_cb * @_type: enum class_map_type, chooses bits/verbose, numeric/symbolic * @_base: offset of 1st class-name. splits .class_id space * @classes: class-names used to control class'd prdbgs */#define DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, ...) \ static const char *_var##_classnames[] = { __VA_ARGS__ }; \ static struct ddebug_class_map __aligned(8) __used \ __section("__dyndbg_classes") _var = { \ .mod = THIS_MODULE, \ .mod_name = KBUILD_MODNAME, \ .base = _base, \ .map_type = _maptype, \ .length = NUM_TYPE_ARGS(char*, __VA_ARGS__), \ .class_names = _var##_classnames, \ }#define NUM_TYPE_ARGS(eltype, ...) \ (sizeof((eltype[]){__VA_ARGS__}) / sizeof(eltype))
/* encapsulate linker provided built-in (or module) dyndbg data */struct _ddebug_info { struct _ddebug *descs; struct ddebug_class_map *classes; unsigned int num_descs; unsigned int num_classes;};
struct ddebug_class_param { union { unsigned long *bits; unsigned int *lvl; }; char flags[8]; const struct ddebug_class_map *map;};
/* * pr_debug() and friends are globally enabled or modules have selectively * enabled them. */#if defined(CONFIG_DYNAMIC_DEBUG) || \ (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
extern __printf(2, 3)void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
struct device;
extern __printf(3, 4)void __dynamic_dev_dbg(struct _ddebug *descriptor, const struct device *dev, const char *fmt, ...);
struct net_device;
extern __printf(3, 4)void __dynamic_netdev_dbg(struct _ddebug *descriptor, const struct net_device *dev, const char *fmt, ...);
struct ib_device;
extern __printf(3, 4)void __dynamic_ibdev_dbg(struct _ddebug *descriptor, const struct ib_device *ibdev, const char *fmt, ...);
#define __dynamic_dump_stack(desc) \{ \ if (desc.flags & _DPRINTK_FLAGS_INCL_STACK) \ dump_stack(); \}
#define DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, cls, fmt) \ static struct _ddebug __aligned(8) \ __section("__dyndbg") name = { \ .modname = KBUILD_MODNAME, \ .function = __func__, \ .filename = __FILE__, \ .format = (fmt), \ .lineno = __LINE__, \ .flags = _DPRINTK_FLAGS_DEFAULT, \ .class_id = cls, \ _DPRINTK_KEY_INIT \ }; \ BUILD_BUG_ON_MSG(cls > _DPRINTK_CLASS_DFLT, \ "classid value overflow")
#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \ DEFINE_DYNAMIC_DEBUG_METADATA_CLS(name, _DPRINTK_CLASS_DFLT, fmt)
#ifdef CONFIG_JUMP_LABEL
#ifdef DEBUG
#define _DPRINTK_KEY_INIT .key.dd_key_true = (STATIC_KEY_TRUE_INIT)
#define DYNAMIC_DEBUG_BRANCH(descriptor) \ static_branch_likely(&descriptor.key.dd_key_true)#else#define _DPRINTK_KEY_INIT .key.dd_key_false = (STATIC_KEY_FALSE_INIT)
#define DYNAMIC_DEBUG_BRANCH(descriptor) \ static_branch_unlikely(&descriptor.key.dd_key_false)#endif
#else /* !CONFIG_JUMP_LABEL */
#define _DPRINTK_KEY_INIT
#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 /* CONFIG_JUMP_LABEL */
/* * Factory macros: ($prefix)dynamic_func_call($suffix) * * Lower layer (with __ prefix) gets the callsite metadata, and wraps * the func inside a debug-branch/static-key construct. Upper layer * (with _ prefix) does the UNIQUE_ID once, so that lower can ref the * name/label multiple times, and tie the elements together. * Multiple flavors: * (|_cls): adds in _DPRINT_CLASS_DFLT as needed * (|_no_desc): former gets callsite descriptor as 1st arg (for prdbgs) */#define __dynamic_func_call_cls(id, cls, fmt, func, ...) do { \ DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt); \ if (DYNAMIC_DEBUG_BRANCH(id)) { \ func(&id, ##__VA_ARGS__); \ __dynamic_dump_stack(id); \ } \} while (0)#define __dynamic_func_call(id, fmt, func, ...) \ __dynamic_func_call_cls(id, _DPRINTK_CLASS_DFLT, fmt, \ func, ##__VA_ARGS__)
#define __dynamic_func_call_cls_no_desc(id, cls, fmt, func, ...) do { \ DEFINE_DYNAMIC_DEBUG_METADATA_CLS(id, cls, fmt); \ if (DYNAMIC_DEBUG_BRANCH(id)) { \ func(__VA_ARGS__); \ __dynamic_dump_stack(id); \ } \} while (0)#define __dynamic_func_call_no_desc(id, fmt, func, ...) \ __dynamic_func_call_cls_no_desc(id, _DPRINTK_CLASS_DFLT, \ fmt, func, ##__VA_ARGS__)
/* * "Factory macro" for generating a call to func, guarded by a * DYNAMIC_DEBUG_BRANCH. The dynamic debug descriptor will be * initialized using the fmt argument. The function will be called with * the address of the descriptor as first argument, followed by all * the varargs. Note that fmt is repeated in invocations of this * macro. */#define _dynamic_func_call_cls(cls, fmt, func, ...) \ __dynamic_func_call_cls(__UNIQUE_ID(ddebug), cls, fmt, func, ##__VA_ARGS__)#define _dynamic_func_call(fmt, func, ...) \ _dynamic_func_call_cls(_DPRINTK_CLASS_DFLT, fmt, func, ##__VA_ARGS__)
/* * A variant that does the same, except that the descriptor is not * passed as the first argument to the function; it is only called * with precisely the macro's varargs. */#define _dynamic_func_call_cls_no_desc(cls, fmt, func, ...) \ __dynamic_func_call_cls_no_desc(__UNIQUE_ID(ddebug), cls, fmt, \ func, ##__VA_ARGS__)#define _dynamic_func_call_no_desc(fmt, func, ...) \ _dynamic_func_call_cls_no_desc(_DPRINTK_CLASS_DFLT, fmt, \ func, ##__VA_ARGS__)
#define dynamic_pr_debug_cls(cls, fmt, ...) \ _dynamic_func_call_cls(cls, fmt, __dynamic_pr_debug, \ pr_fmt(fmt), ##__VA_ARGS__)
#define dynamic_pr_debug(fmt, ...) \ _dynamic_func_call(fmt, __dynamic_pr_debug, \ pr_fmt(fmt), ##__VA_ARGS__)
#define dynamic_dev_dbg(dev, fmt, ...) \ _dynamic_func_call(fmt, __dynamic_dev_dbg, \ dev, fmt, ##__VA_ARGS__)
#define dynamic_netdev_dbg(dev, fmt, ...) \ _dynamic_func_call(fmt, __dynamic_netdev_dbg, \ dev, fmt, ##__VA_ARGS__)
#define dynamic_ibdev_dbg(dev, fmt, ...) \ _dynamic_func_call(fmt, __dynamic_ibdev_dbg, \ dev, fmt, ##__VA_ARGS__)
#define dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ groupsize, buf, len, ascii) \ _dynamic_func_call_no_desc(__builtin_constant_p(prefix_str) ? prefix_str : "hexdump", \ print_hex_dump, \ KERN_DEBUG, prefix_str, prefix_type, \ rowsize, groupsize, buf, len, ascii)
/* for test only, generally expect drm.debug style macro wrappers */#define __pr_debug_cls(cls, fmt, ...) do { \ BUILD_BUG_ON_MSG(!__builtin_constant_p(cls), \ "expecting constant class int/enum"); \ dynamic_pr_debug_cls(cls, fmt, ##__VA_ARGS__); \ } while (0)
#else /* !(CONFIG_DYNAMIC_DEBUG || (CONFIG_DYNAMIC_DEBUG_CORE && DYNAMIC_DEBUG_MODULE)) */
#include <linux/string.h>#include <linux/errno.h>#include <linux/printk.h>
#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)#define DYNAMIC_DEBUG_BRANCH(descriptor) false
#define dynamic_pr_debug(fmt, ...) \ no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)#define dynamic_dev_dbg(dev, fmt, ...) \ dev_no_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__)#define dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ groupsize, buf, len, ascii) \ do { if (0) \ print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, \ rowsize, groupsize, buf, len, ascii); \ } while (0)
#endif /* CONFIG_DYNAMIC_DEBUG || (CONFIG_DYNAMIC_DEBUG_CORE && DYNAMIC_DEBUG_MODULE) */
#ifdef CONFIG_DYNAMIC_DEBUG_CORE
extern int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *modname);struct kernel_param;int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp);int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp);
#else
static inline int ddebug_dyndbg_module_param_cb(char *param, char *val, const char *modname){ if (!strcmp(param, "dyndbg")) { /* avoid pr_warn(), which wants pr_fmt() fully defined */ printk(KERN_WARNING "dyndbg param is supported only in " "CONFIG_DYNAMIC_DEBUG builds\n"); return 0; /* allow and ignore */ } return -EINVAL;}
struct kernel_param;static inline int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp){ return 0; }static inline int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp){ return 0; }
#endif
extern const struct kernel_param_ops param_ops_dyndbg_classes;
#endif /* _DYNAMIC_DEBUG_H */