DECLARE_DYNDBG_CLASSMAP lets modules declare a set of classnames, this opt-in authorizes dyndbg to allow enabling of prdbgs by their class: :#> echo class DRM_UT_KMS +p > /proc/dynamic_debug/control This is just the setup; following commits deliver. The macro declares and initializes a static struct ddebug_class_map: - maps approved class-names to class_ids used in module, by array order. forex: DRM_UT_* - class-name vals allow validation of "class FOO" queries using macro is opt-in - enum class_map_type - determines interface, behavior Each module has its own .class_id space, and only known class-names will be authorized for a manipulation. Only DRM stuff should know this: :#> echo class DRM_UT_CORE +p > control # across all modules pr_debugs (with default class_id) are still controllable as before. DECLARE_DYNDBG_CLASSMAP(_var, _maptype, _base, classes...) is:: _var: name of the static struct var. user passes to module_param_cb() if they want a sysfs node. (ive only done it this way). _maptype: this is hard-coded to DD_CLASS_TYPE_DISJOINT for now. _base: usually 0, it allows splitting 31 classes into subranges, so that multiple classes / sysfs-nodes can share the module's class-id space. classes: list of class_name strings, these are mapped to class-ids starting at _base. This class-names list must have a corresponding ENUM, with SYMBOLS that match the literals, and 1st enum val = _base. enum class_map_type has 4 values, on 2 factors:: - classes are disjoint/independent vs relative/x<y/verbosity. disjoint is basis, verbosity by overlay. - input NUMBERS vs [+-]CLASS_NAMES uints, ideally hex. vs +DRM_UT_CORE,-DRM_UT_KMS DD_CLASS_TYPE_DISJOINT: classes are separate, one per bit. expecting hex input. basis for others. DD_CLASS_TYPE_SYMBOLIC: input is a CSV of [+-]CLASS_NAMES, classes are independent, like DISJOINT DD_CLASS_TYPE_VERBOSE: input is numeric level, 0-N. 0 implies silence. use printk to break that. relative levels applied on bitmaps. DD_CLASS_TYPE_LEVELS: input is a CSV of [+-]CLASS_NAMES, names like: ERR,WARNING,NOTICE,INFO,DEBUG avoiding EMERG,ALERT,CRIT,ERR - no point. NOTES: The macro places the initialized struct ddebug_class_map into the __dyndbg_classes section. That draws a 'orphan' warning which we handle in next commit. The struct attributes are necessary: __aligned(8) stopped null-ptr derefs (why?), __used is needed by drm drivers, which declare class-maps, but don't also declare a sysfs-param, and thus dont ref the classmap; __used insures that the linkage is made, then the class-map is found at load-time. While its possible to handle both NAMES and NUMBERS in the same sys-interface, there is ambiguity to avoid, by disallowing them together. Later, if ambiguities are resolved, 2 new enums can permit both inputs, on verbose & independent types separately, and authors can select the interface they like. RFC: My plan is to implement LEVELS in the callbacks, outside of ddebug_exec_query(), which for simplicity will treat the CLASSES in the map as disjoint. This should handle most situations. The callbacks can see map-type, and apply ++/-- loops (or bitops) to force the relative meanings across the class-bitmap. That leaves 2 issues: 1. doing LEVELs in callbacks means that the native >control interface doesn't enforce the LEVELS relationship, so you could confusingly have V3 enabled, but V1 disabled. OTOH, the control iface already allows infinite variety in the underlying callsites, despite the veneer of uniformity suggested by the bitmap overlay, and LEVELS over that. 2. All dyndbg >control reduces to a query/command, includes +/-, which is at-root a kernel patching operation with +/- semantics. And the symbolic sys-node handling exposes it to the user: Consider whether these are/should-be 'exactly' the same: # force both 2 "half-duplex" relations echo +V3,-V4 > /sys/module/test_dynamic_debug/p_VX # should these both do the same ? echo +V3 > /sys/module/test_dynamic_debug/p_VX echo -V4 > /sys/module/test_dynamic_debug/p_VX IOW, half relations are suggested by the +/-, and enum control of individual behaviors leaves some room for this, especially wrt handling [+-]SYMBOLIC inputs from the user. Signed-off-by: Jim Cromie <jim.cromie@xxxxxxxxx> --- include/linux/dynamic_debug.h | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 0f7ad6cecf05..84e97cd0e8c4 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -56,7 +56,62 @@ struct _ddebug { #endif } __attribute__((aligned(8))); +enum class_map_type { + DD_CLASS_TYPE_DISJOINT, + /** + * DD_CLASS_TYPE_DISJOINT: classes are independent, one per bit. + * expecting hex input. basis for others. + */ + DD_CLASS_TYPE_VERBOSE, + /** + * DD_CLASS_TYPE_VERBOSE: input is numeric level, 0-N. + * 0 should be silent, use printk to break that. + * (x<y) relationship on bitpos + */ + DD_CLASS_TYPE_SYMBOLIC, + /** + * DD_CLASS_TYPE_SYMBOLIC: input is a CSV of [+-]CLASS_NAMES, + * classes are independent, like DISJOINT + */ + DD_CLASS_TYPE_LEVELS, + /** + * DD_CLASS_TYPE_LEVELS: input is a CSV of [+-]CLASS_NAMES, + * intended for names like: ERR,WARNING,NOTICE,INFO,DEBUG + * avoid ? EMERG,ALERT,CRIT,ERR,WARNING ?? + */ +}; + +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)) #if defined(CONFIG_DYNAMIC_DEBUG_CORE) -- 2.36.1