On Tue, Apr 15, 2025 at 4:02 AM Louis Chauvet <louis.chau...@bootlin.com> wrote: > > > > Le 02/04/2025 à 19:41, Jim Cromie a écrit : > > Add a selftest script for dynamic-debug. The config requires > > CONFIG_TEST_DYNAMIC_DEBUG=m and CONFIG_TEST_DYNAMIC_DEBUG_SUBMOD=m, > > which tacitly requires either CONFIG_DYNAMIC_DEBUG=y or > > CONFIG_DYNAMIC_DEBUG_CORE=y > > > > ATM this has just basic_tests(), which modify pr_debug() flags in the > > builtin params module. This means they're available to manipulate and > > observe the effects in "cat control". > > > > This is backported from another feature branch; the support-fns (thx > > Lukas) have unused features at the moment, they'll get used shortly. > > > > The script enables simple virtme-ng testing: > > > > [jimc@gandalf b0-ftrace]$ vrun_t > > virtme-ng 1.32+115.g07b109d > > doing: vng --name v6.14-rc4-60-gd5f48427de0c \ > > --user root -v -p 4 -a dynamic_debug.verbose=3 V=1 \ > > -- ../tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh > > virtme: waiting for virtiofsd to start > > .. > > > > And add dynamic_debug to TARGETS, so `make run_tests` sees it properly > > > > For the impatient, set TARGETS explicitly: > > > > bash-5.2# make TARGETS=dynamic_debug run_tests > > make[1]: ... > > TAP version 13 > > 1..1 > > [ 35.552922] dyndbg: read 3 bytes from userspace > > [ 35.553099] dyndbg: query 0: "=_" mod:* > > [ 35.553544] dyndbg: processed 1 queries, with 1778 matches, 0 errs > > > > Signed-off-by: Jim Cromie <jim.cro...@gmail.com> > > Co-developed-by: Łukasz Bartosik <uka...@chromium.org> > > Signed-off-by: Łukasz Bartosik <uka...@chromium.org> > > --- > > -r3 turn off green at end > > drop config dep on TEST_DYNAMIC_DEBUG, > > since basic-test uses builtin params > > > > - check KCONFIG_CONFIG to avoid silly fails > > > > Several tests are dependent upon config choices. Lets avoid failing > > where that is noise. > > > > The KCONFIG_CONFIG var exists to convey the config-file around. If > > the var names a file, read it and extract the relevant CONFIG items, > > and use them to skip the dependent tests, thus avoiding the fails that > > would follow, and the disruption to whatever CI is running these > > selftests. > > > > If the envar doesn't name a config-file, ".config" is assumed. > > > > CONFIG_DYNAMIC_DEBUG=y: > > > > basic-tests() and comma-terminator-tests() test for the presence of > > the builtin pr_debugs in module/main.c, which I deemed stable and > > therefore safe to count. That said, the test fails if only > > CONFIG_DYNAMIC_DEBUG_CORE=y is set. It could be rewritten to test > > against test-dynamic-debug.ko, but that just trades one config > > dependence for another. > > > > CONFIG_TEST_DYNAMIC_DEBUG=m > > > > As written, test_percent_splitting() modprobes test_dynamic_debug, > > enables several classes, and count them. It could be re-written to > > work for the builtin module also, but builtin test modules are not a > > common or desirable build/config. > > > > CONFIG_TEST_DYNAMIC_DEBUG=m && CONFIG_TEST_DYNAMIC_DEBUG_SUBMOD=m > > > > test_mod_submod() recaps the bug found in DRM-CI where drivers werent > > enabled by drm.debug=<bits>. It modprobes both test_dynamic_debug & > > test_dynamic_debug_submod, so it depends on a loadable modules config. > > > > It could be rewritten to work in a builtin parent config; DRM=y is > > common enough to be pertinent, but testing that config also wouldn't > > really test anything more fully than all-loadable modules, since they > > default together. > > > > generalize-test-env > > --- > > MAINTAINERS | 1 + > > tools/testing/selftests/Makefile | 1 + > > .../testing/selftests/dynamic_debug/Makefile | 9 + > > tools/testing/selftests/dynamic_debug/config | 7 + > > .../dynamic_debug/dyndbg_selftest.sh | 257 ++++++++++++++++++ > > 5 files changed, 275 insertions(+) > > create mode 100644 tools/testing/selftests/dynamic_debug/Makefile > > create mode 100644 tools/testing/selftests/dynamic_debug/config > > create mode 100755 > > tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh > > > > diff --git a/MAINTAINERS b/MAINTAINERS > > index 1c5fcbd9e408..1192ad6c65c1 100644 > > --- a/MAINTAINERS > > +++ b/MAINTAINERS > > @@ -8140,6 +8140,7 @@ S: Maintained > > F: include/linux/dynamic_debug.h > > F: lib/dynamic_debug.c > > F: lib/test_dynamic_debug*.c > > +F: tools/testing/selftests/dynamic_debug/* > > > > DYNAMIC INTERRUPT MODERATION > > M: Tal Gilboa <ta...@nvidia.com> > > diff --git a/tools/testing/selftests/Makefile > > b/tools/testing/selftests/Makefile > > index 8daac70c2f9d..b6a323c7f986 100644 > > --- a/tools/testing/selftests/Makefile > > +++ b/tools/testing/selftests/Makefile > > @@ -26,6 +26,7 @@ TARGETS += drivers/net/team > > TARGETS += drivers/net/virtio_net > > TARGETS += drivers/platform/x86/intel/ifs > > TARGETS += dt > > +TARGETS += dynamic_debug > > TARGETS += efivarfs > > TARGETS += exec > > TARGETS += fchmodat2 > > diff --git a/tools/testing/selftests/dynamic_debug/Makefile > > b/tools/testing/selftests/dynamic_debug/Makefile > > new file mode 100644 > > index 000000000000..6d06fa7f1040 > > --- /dev/null > > +++ b/tools/testing/selftests/dynamic_debug/Makefile > > @@ -0,0 +1,9 @@ > > +# SPDX-License-Identifier: GPL-2.0-only > > +# borrowed from Makefile for user memory selftests > > + > > +# No binaries, but make sure arg-less "make" doesn't trigger "run_tests" > > +all: > > + > > +TEST_PROGS := dyndbg_selftest.sh > > + > > +include ../lib.mk > > diff --git a/tools/testing/selftests/dynamic_debug/config > > b/tools/testing/selftests/dynamic_debug/config > > new file mode 100644 > > index 000000000000..0f906ff53908 > > --- /dev/null > > +++ b/tools/testing/selftests/dynamic_debug/config > > @@ -0,0 +1,7 @@ > > + > > +# basic tests ref the builtin params module > > +CONFIG_DYNAMIC_DEBUG=m > > + > > +# more testing is possible with these > > +# CONFIG_TEST_DYNAMIC_DEBUG=m > > +# CONFIG_TEST_DYNAMIC_DEBUG_SUBMOD=m > > diff --git a/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh > > b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh > > new file mode 100755 > > index 000000000000..465fad3f392c > > --- /dev/null > > +++ b/tools/testing/selftests/dynamic_debug/dyndbg_selftest.sh > > @@ -0,0 +1,257 @@ > > +#!/bin/bash > > +# SPDX-License-Identifier: GPL-2.0-only > > + > > +V=${V:=0} # invoke as V=1 $0 for global verbose > > +RED="\033[0;31m" > > +GREEN="\033[0;32m" > > +YELLOW="\033[0;33m" > > +BLUE="\033[0;34m" > > +MAGENTA="\033[0;35m" > > +CYAN="\033[0;36m" > > +NC="\033[0;0m" > > +error_msg="" > > + > > +[ -e /proc/dynamic_debug/control ] || { > > + echo -e "${RED}: this test requires CONFIG_DYNAMIC_DEBUG=y ${NC}" > > + exit 0 # nothing to test here, no good reason to fail. > > +} > > + > > +# need info to avoid failures due to untestable configs > > + > > +[ -f "$KCONFIG_CONFIG" ] || KCONFIG_CONFIG=".config" > > +if [ -f "$KCONFIG_CONFIG" ]; then > > + echo "# consulting KCONFIG_CONFIG: $KCONFIG_CONFIG" > > + grep -q "CONFIG_DYNAMIC_DEBUG=y" $KCONFIG_CONFIG ; LACK_DD_BUILTIN=$? > > + grep -q "CONFIG_TEST_DYNAMIC_DEBUG=m" $KCONFIG_CONFIG ; LACK_TMOD=$? > > + grep -q "CONFIG_TEST_DYNAMIC_DEBUG_SUBMOD=m" $KCONFIG_CONFIG ; > > LACK_TMOD_SUBMOD=$? > > + if [ $V -eq 1 ]; then > > + echo LACK_DD_BUILTIN: $LACK_DD_BUILTIN > > + echo LACK_TMOD: $LACK_TMOD > > + echo LACK_TMOD_SUBMOD: $LACK_TMOD_SUBMOD > > + fi > > +else > > + LACK_DD_BUILTIN=0 > > + LACK_TMOD=0 > > + LACK_TMOD_SUBMOD=0 > > +fi > > Nitpick for the sh file: is it normal to have inconsistent indenting ?(4 > space, tabs, 8 spaces) >
hmm. I just checked scripts/bpf_doc.py it uses 4 space indents, I didnt check for tabs. But I will go look for inconsistencies and mixes of spaces & tabs > > +function vx () { > > + echo $1 > /sys/module/dynamic_debug/parameters/verbose > > +} > > + > > +function ddgrep () { > > + grep $1 /proc/dynamic_debug/control > > +} > > + > > +function doprints () { > > + cat /sys/module/test_dynamic_debug/parameters/do_prints > > +} > > + > > +function ddcmd () { > > + exp_exit_code=0 > > + num_args=$# > > + if [ "${@:$#}" = "pass" ]; then > > + num_args=$#-1 > > + elif [ "${@:$#}" = "fail" ]; then > > + num_args=$#-1 > > + exp_exit_code=1 > > + fi > > + args=${@:1:$num_args} > > + output=$((echo "$args" > /proc/dynamic_debug/control) 2>&1) > > + exit_code=$? > > + error_msg=$(echo $output | cut -d ":" -f 5 | sed -e > > 's/^[[:space:]]*//') > > + handle_exit_code $BASH_LINENO $FUNCNAME $exit_code $exp_exit_code > > +} > > + > > +function handle_exit_code() { > > + local exp_exit_code=0 > > + [ $# == 4 ] && exp_exit_code=$4 > > + if [ $3 -ne $exp_exit_code ]; then > > + echo -e "${RED}: $BASH_SOURCE:$1 $2() expected to exit with code > > $exp_exit_code" > > + [ $3 == 1 ] && echo "Error: '$error_msg'" > > + exit > > + fi > > +} > > + > > +# $1 - pattern to match, pattern in $1 is enclosed by spaces for a match > > ""\s$1\s" > > +# $2 - number of times the pattern passed in $1 is expected to match > > +# $3 - optional can be set either to "-r" or "-v" > > +# "-r" means relaxed matching in this case pattern provided in $1 is > > passed > > +# as is without enclosing it with spaces > > +# "-v" prints matching lines > > +# $4 - optional when $3 is set to "-r" then $4 can be used to pass "-v" > > +function check_match_ct { > > + pattern="\s$1\s" > > + exp_cnt=0 > > + > > + [ "$3" == "-r" ] && pattern="$1" > > + let cnt=$(ddgrep "$pattern" | wc -l) > > + if [ $V -eq 1 ] || [ "$3" == "-v" ] || [ "$4" == "-v" ]; then > > + echo -ne "${BLUE}" && ddgrep $pattern && echo -ne "${NC}" > > + fi > > + [ $# -gt 1 ] && exp_cnt=$2 > > + if [ $cnt -ne $exp_cnt ]; then > > + echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO check failed expected > > $exp_cnt on $1, got $cnt" > > + exit > > + else > > + echo ": $cnt matches on $1" > > + fi > > +} > > + > > +# $1 - trace instance name > > +# #2 - if > 0 then directory is expected to exist, if <= 0 then otherwise > > +# $3 - "-v" for verbose > > +function check_trace_instance_dir { > > + if [ -e /sys/kernel/tracing/instances/$1 ]; then > > + if [ "$3" == "-v" ] ; then > > + echo "ls -l /sys/kernel/tracing/instances/$1: " > > + ls -l /sys/kernel/tracing/instances/$1 > > + fi > > + if [ $2 -le 0 ]; then > > + echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO error trace > > instance \ > > + '/sys/kernel/tracing/instances/$1' does exist" > > + exit > > + fi > > + else > > + if [ $2 -gt 0 ]; then > > + echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO error trace > > instance \ > > + '/sys/kernel/tracing/instances/$1' does not exist" > > + exit > > + fi > > + fi > > +} > > + > > +function tmark { > > + echo $* > /sys/kernel/tracing/trace_marker > > +} > > + > > +# $1 - trace instance name > > +# $2 - line number > > +# $3 - if > 0 then the instance is expected to be opened, otherwise > > +# the instance is expected to be closed > > +function check_trace_instance { > > + output=$(tail -n9 /proc/dynamic_debug/control | grep ": Opened trace > > instances" \ > > + | xargs -n1 | grep $1) > > + if [ "$output" != $1 ] && [ $3 -gt 0 ]; then > > + echo -e "${RED}: $BASH_SOURCE:$2 trace instance $1 is not opened" > > + exit > > + fi > > + if [ "$output" == $1 ] && [ $3 -le 0 ]; then > > + echo -e "${RED}: $BASH_SOURCE:$2 trace instance $1 is not closed" > > + exit > > + fi > > +} > > + > > +function is_trace_instance_opened { > > + check_trace_instance $1 $BASH_LINENO 1 > > +} > > + > > +function is_trace_instance_closed { > > + check_trace_instance $1 $BASH_LINENO 0 > > +} > > + > > +# $1 - trace instance directory to delete > > +# $2 - if > 0 then directory is expected to be deleted successfully, if <= > > 0 then otherwise > > +function del_trace_instance_dir() { > > + exp_exit_code=1 > > + [ $2 -gt 0 ] && exp_exit_code=0 > > + output=$((rmdir /sys/kernel/debug/tracing/instances/$1) 2>&1) > > + exit_code=$? > > + error_msg=$(echo $output | cut -d ":" -f 3 | sed -e > > 's/^[[:space:]]*//') > > + handle_exit_code $BASH_LINENO $FUNCNAME $exit_code $exp_exit_code > > +} > > + > > +function error_log_ref { > > + # to show what I got > > + : echo "# error-log-ref: $1" > > + : echo cat \$2 > > +} > > + > > +function ifrmmod { > > + lsmod | grep $1 2>&1>/dev/null && rmmod $1 > > +} > > + > > +# $1 - text to search for > > +function search_trace() { > > + search_trace_name 0 1 $1 > > +} > > + > > +# $1 - trace instance name, 0 for global event trace > > +# $2 - line number counting from the bottom > > +# $3 - text to search for > > +function search_trace_name() { > > + if [ "$1" = "0" ]; then > > + buf=$(cat /sys/kernel/debug/tracing/trace) > > + line=$(tail -$2 /sys/kernel/debug/tracing/trace | head -1 | sed > > -e 's/^[[:space:]]*//') > > + else > > + buf=$(cat /sys/kernel/debug/tracing/instances/$1/trace) > > + line=$(tail -$2 /sys/kernel/debug/tracing/instances/$1/trace | > > head -1 | \ > > + sed -e 's/^[[:space:]]*//') > > + fi > > + if [ $2 = 0 ]; then > > + # whole-buf check > > + output=$(echo $buf | grep "$3") > > + else > > + output=$(echo $line | grep "$3") > > + fi > > + if [ "$output" = "" ]; then > > + echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO search for '$3' > > failed \ > > + in line '$line' or '$buf'" > > + exit > > + fi > > + if [ $V = 1 ]; then > > + echo -e "${MAGENTA}: search_trace_name in $1 found: \n$output > > \nin:${BLUE} $buf ${NC}" > > + fi > > +} > > + > > +# $1 - error message to check > > +function check_err_msg() { > > + if [ "$error_msg" != "$1" ]; then > > + echo -e "${RED}: $BASH_SOURCE:$BASH_LINENO error message > > '$error_msg' \ > > + does not match with '$1'" > > + exit > > + fi > > +} > > + > > +function basic_tests { > > + echo -e "${GREEN}# BASIC_TESTS ${NC}" > > + if [ $LACK_DD_BUILTIN -eq 1 ]; then > > + echo "SKIP" > > + return > > + fi > > + ddcmd =_ # zero everything > > + check_match_ct =p 0 > > + > > + # module params are builtin to handle boot args > > + check_match_ct '\[params\]' 4 -r > > + ddcmd module params +mpf > > + check_match_ct =pmf 4 > > + > > + # multi-cmd input, newline separated, with embedded comments > > + cat <<"EOF" > /proc/dynamic_debug/control > > + module params =_ # clear params > > + module params +mf # set flags > > + module params func parse_args +sl # other flags > > +EOF > > + check_match_ct =mf 3 > > + check_match_ct =mfsl 1 > > + ddcmd =_ > > +} > > + > > +tests_list=( > > + basic_tests > > +) > > + > > +# Run tests > > + > > +ifrmmod test_dynamic_debug_submod > > +ifrmmod test_dynamic_debug > > + > > +for test in "${tests_list[@]}" > > +do > > + $test > > + echo "" > > +done > > +echo -en "${GREEN}# Done on: " > > +date > > +echo -en "${NC}" > > -- > Louis Chauvet, Bootlin > Embedded Linux and Kernel engineering > https://bootlin.com > >