Add DEFINE_DYNDBG_BITMAP(name, var, bitmap_desc, @bit_descs) to allow users to define a /sys/module/*/parameter/name, and a mapping from bits[0-N] to the debug-class-prefixes that the author wishes to control. DEFINE_DYNDBG_BITMAP(debug_gvt, __gvt_debug, "dyndbg bitmap desc", { "gvt:cmd: ", "command processing" }, { "gvt:core: ", "core help" }, { "gvt:dpy: ", "display help" }, { "gvt:el: ", "help" }, { "gvt:irq: ", "help" }, { "gvt:mm: ", "help" }, { "gvt:mmio: ", "help" }, { "gvt:render: ", "help" }, { "gvt:sched: ", "help" }); dynamic_debug.c: add 3 new elements: - int param_set_dyndbg() - not working yet, // __gvt_debug - int param_get_dyndbg() - struct param_ops_dyndbg Following the model of kernel/params.c STANDARD_PARAM_DEFS, All 3 are non-static and exported. dynamic_debug.h: extern the struct param_ops_dyndbg prototype. This appears to be needed to reference the var, forex in i915_params.c TBD: set_dyndbg() works to enable categories, but fails to disable them. This is because the code relied on having an old copy of the param (__gvt_debug) to detect +/- changes. Rewriting the loop is probably easier than stashing the old state for change detection. Signed-off-by: Jim Cromie <jim.cromie@xxxxxxxxx> --- include/linux/dynamic_debug.h | 36 +++++++++++++++++++++++ lib/dynamic_debug.c | 55 +++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index dce631e678dd..677ad176b167 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -2,6 +2,8 @@ #ifndef _DYNAMIC_DEBUG_H #define _DYNAMIC_DEBUG_H +#include <linux/moduleparam.h> + #if defined(CONFIG_JUMP_LABEL) #include <linux/jump_label.h> #endif @@ -227,6 +229,40 @@ static inline int dynamic_debug_exec_queries(const char *query, const char *modn return 0; } +static int param_set_dyndbg(const char *instr, struct kernel_param *kp) +{ return 0; } +static int param_get_dyndbg(char *buffer, struct kernel_param *kp) +{ return 0; } + #endif /* !CONFIG_DYNAMIC_DEBUG_CORE */ +struct dyndbg_bitdesc { + /* bitpos is inferred from index in containing array */ + char *prefix; + char *help; +}; + +/** + * DYNDBG_BITMAP_DESC(name, var, bitmap_desc, @bit_descs) + * @name: basename under /sys + * @var: C identifier to map + * @bitmap_desc: string summarizing dyndbg categories + * @bit_descs: list of struct dydbg_bitdesc initializations + * + * Defines the mapping of bits 0-N to categories/prefixes of + * debug-callsites to be controlled. + * + * Users should also call MODULE_PARM_DESC(name, bitmap_desc). + * Maybe we can invoke it on their behalf, but we want MOD-NAME to be + * correct, test soon. may also need modname in name - "debug" will + * not be unique. + */ +#define DEFINE_DYNDBG_BITMAP(name, value, bitmap_desc, ...) \ + struct dyndbg_bitdesc dyndbg_classes_##name[] = \ + { __VA_ARGS__, { NULL, NULL } }; \ + module_param_cbd(name, ¶m_ops_dyndbg, value, 0644, \ + &dyndbg_classes_##name); + +extern const struct kernel_param_ops param_ops_dyndbg; + #endif diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index cb5abb42c16a..045e1cf92c44 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -1154,3 +1154,58 @@ early_initcall(dynamic_debug_init); /* Debugfs setup must be done later */ fs_initcall(dynamic_debug_init_control); + +#include <linux/moduleparam.h> + +#define OUR_QUERY_SIZE 128 /* typically need <40 */ + +int param_set_dyndbg(const char *instr, const struct kernel_param *kp) +{ + unsigned int val; + unsigned long changes, result; + int rc, chgct = 0, totct = 0, bitpos, bitsmax; + char query[OUR_QUERY_SIZE]; + struct dyndbg_bitdesc *bitmap = (struct dyndbg_bitdesc *) kp->data; + + // pr_info("set_dyndbg: instr: %s curr: %d\n", instr, *kp->arg); + + rc = kstrtouint(instr, 0, &val); + if (rc) { + pr_err("set_dyndbg: failed\n"); + return -EINVAL; + } + result = val; + pr_info("set_dyndbg: result:0x%lx from %s\n", result, instr); + + changes = result; // ^ __gvt_debug; + + for (bitsmax = 0; bitmap[bitsmax].prefix; bitsmax++); + + for_each_set_bit(bitpos, &changes, min(--bitsmax, 64)) { + + sprintf(query, "format '^%s' %cp", bitmap[bitpos].prefix, + test_bit(bitpos, &result) ? '+' : '-'); + + chgct = dynamic_debug_exec_queries(query, "i915"); + + pr_info("bit-%d: %d changes on: %s\n", bitpos, chgct, query); + totct += chgct; + } + pr_info("total changes: %d\n", totct); + // __gvt_debug = result; + return 0; +} +EXPORT_SYMBOL(param_set_dyndbg); + +int param_get_dyndbg(char *buffer, const struct kernel_param *kp) +{ + return scnprintf(buffer, PAGE_SIZE, "%u\n", + *((unsigned int *)kp->arg)); +} +EXPORT_SYMBOL(param_get_dyndbg); + +const struct kernel_param_ops param_ops_dyndbg = { + .set = param_set_dyndbg, + .get = param_get_dyndbg, +}; +EXPORT_SYMBOL(param_ops_dyndbg); -- 2.31.1