diff options
Diffstat (limited to 'tools/testing/selftests/ftrace')
68 files changed, 3840 insertions, 0 deletions
diff --git a/tools/testing/selftests/ftrace/.gitignore b/tools/testing/selftests/ftrace/.gitignore new file mode 100644 index 000000000..98d8a5a63 --- /dev/null +++ b/tools/testing/selftests/ftrace/.gitignore @@ -0,0 +1 @@ +logs diff --git a/tools/testing/selftests/ftrace/Makefile b/tools/testing/selftests/ftrace/Makefile new file mode 100644 index 000000000..cd1f5b3a7 --- /dev/null +++ b/tools/testing/selftests/ftrace/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +all: + +TEST_PROGS := ftracetest +TEST_FILES := test.d +EXTRA_CLEAN := $(OUTPUT)/logs/* + +include ../lib.mk diff --git a/tools/testing/selftests/ftrace/README b/tools/testing/selftests/ftrace/README new file mode 100644 index 000000000..182e76fa4 --- /dev/null +++ b/tools/testing/selftests/ftrace/README @@ -0,0 +1,82 @@ +Linux Ftrace Testcases + +This is a collection of testcases for ftrace tracing feature in the Linux +kernel. Since ftrace exports interfaces via the debugfs, we just need +shell scripts for testing. Feel free to add new test cases. + +Running the ftrace testcases +============================ + +At first, you need to be the root user to run this script. +To run all testcases: + + $ sudo ./ftracetest + +To run specific testcases: + + # ./ftracetest test.d/basic3.tc + +Or you can also run testcases under given directory: + + # ./ftracetest test.d/kprobe/ + +Contributing new testcases +========================== + +Copy test.d/template to your testcase (whose filename must have *.tc +extension) and rewrite the test description line. + + * The working directory of the script is <debugfs>/tracing/. + + * Take care with side effects as the tests are run with root privilege. + + * The tests should not run for a long period of time (more than 1 min.) + These are to be unit tests. + + * You can add a directory for your testcases under test.d/ if needed. + + * The test cases should run on dash (busybox shell) for testing on + minimal cross-build environments. + + * Note that the tests are run with "set -e" (errexit) option. If any + command fails, the test will be terminated immediately. + + * The tests can return some result codes instead of pass or fail by + using exit_unresolved, exit_untested, exit_unsupported and exit_xfail. + +Result code +=========== + +Ftracetest supports following result codes. + + * PASS: The test succeeded as expected. The test which exits with 0 is + counted as passed test. + + * FAIL: The test failed, but was expected to succeed. The test which exits + with !0 is counted as failed test. + + * UNRESOLVED: The test produced unclear or intermidiate results. + for example, the test was interrupted + or the test depends on a previous test, which failed. + or the test was set up incorrectly + The test which is in above situation, must call exit_unresolved. + + * UNTESTED: The test was not run, currently just a placeholder. + In this case, the test must call exit_untested. + + * UNSUPPORTED: The test failed because of lack of feature. + In this case, the test must call exit_unsupported. + + * XFAIL: The test failed, and was expected to fail. + To return XFAIL, call exit_xfail from the test. + +There are some sample test scripts for result code under samples/. +You can also run samples as below: + + # ./ftracetest samples/ + +TODO +==== + + * Fancy colored output :) + diff --git a/tools/testing/selftests/ftrace/config b/tools/testing/selftests/ftrace/config new file mode 100644 index 000000000..07db5ab09 --- /dev/null +++ b/tools/testing/selftests/ftrace/config @@ -0,0 +1,9 @@ +CONFIG_KPROBES=y +CONFIG_FTRACE=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_TRACER_SNAPSHOT=y +CONFIG_STACK_TRACER=y +CONFIG_HIST_TRIGGERS=y +CONFIG_PREEMPT_TRACER=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_PREEMPTIRQ_DELAY_TEST=m diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest new file mode 100755 index 000000000..f9a9d424c --- /dev/null +++ b/tools/testing/selftests/ftrace/ftracetest @@ -0,0 +1,330 @@ +#!/bin/sh + +# ftracetest - Ftrace test shell scripts +# +# Copyright (C) Hitachi Ltd., 2014 +# Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> +# +# Released under the terms of the GPL v2. + +usage() { # errno [message] +[ ! -z "$2" ] && echo $2 +echo "Usage: ftracetest [options] [testcase(s)] [testcase-directory(s)]" +echo " Options:" +echo " -h|--help Show help message" +echo " -k|--keep Keep passed test logs" +echo " -v|--verbose Increase verbosity of test messages" +echo " -vv Alias of -v -v (Show all results in stdout)" +echo " -vvv Alias of -v -v -v (Show all commands immediately)" +echo " --fail-unsupported Treat UNSUPPORTED as a failure" +echo " -d|--debug Debug mode (trace all shell commands)" +echo " -l|--logdir <dir> Save logs on the <dir>" +echo " If <dir> is -, all logs output in console only" +exit $1 +} + +errexit() { # message + echo "Error: $1" 1>&2 + exit 1 +} + +# Ensuring user privilege +if [ `id -u` -ne 0 ]; then + errexit "this must be run by root user" +fi + +# Utilities +absdir() { # file_path + (cd `dirname $1`; pwd) +} + +abspath() { + echo `absdir $1`/`basename $1` +} + +find_testcases() { #directory + echo `find $1 -name \*.tc | sort` +} + +parse_opts() { # opts + local OPT_TEST_CASES= + local OPT_TEST_DIR= + + while [ ! -z "$1" ]; do + case "$1" in + --help|-h) + usage 0 + ;; + --keep|-k) + KEEP_LOG=1 + shift 1 + ;; + --verbose|-v|-vv|-vvv) + VERBOSE=$((VERBOSE + 1)) + [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1)) + [ $1 = '-vvv' ] && VERBOSE=$((VERBOSE + 2)) + shift 1 + ;; + --debug|-d) + DEBUG=1 + shift 1 + ;; + --fail-unsupported) + UNSUPPORTED_RESULT=1 + shift 1 + ;; + --logdir|-l) + LOG_DIR=$2 + shift 2 + ;; + *.tc) + if [ -f "$1" ]; then + OPT_TEST_CASES="$OPT_TEST_CASES `abspath $1`" + shift 1 + else + usage 1 "$1 is not a testcase" + fi + ;; + *) + if [ -d "$1" ]; then + OPT_TEST_DIR=`abspath $1` + OPT_TEST_CASES="$OPT_TEST_CASES `find_testcases $OPT_TEST_DIR`" + shift 1 + else + usage 1 "Invalid option ($1)" + fi + ;; + esac + done + if [ ! -z "$OPT_TEST_CASES" ]; then + TEST_CASES=$OPT_TEST_CASES + fi +} + +# Parameters +DEBUGFS_DIR=`grep debugfs /proc/mounts | cut -f2 -d' ' | head -1` +if [ -z "$DEBUGFS_DIR" ]; then + TRACING_DIR=`grep tracefs /proc/mounts | cut -f2 -d' ' | head -1` +else + TRACING_DIR=$DEBUGFS_DIR/tracing +fi + +TOP_DIR=`absdir $0` +TEST_DIR=$TOP_DIR/test.d +TEST_CASES=`find_testcases $TEST_DIR` +LOG_DIR=$TOP_DIR/logs/`date +%Y%m%d-%H%M%S`/ +KEEP_LOG=0 +DEBUG=0 +VERBOSE=0 +UNSUPPORTED_RESULT=0 +# Parse command-line options +parse_opts $* + +[ $DEBUG -ne 0 ] && set -x + +# Verify parameters +if [ -z "$TRACING_DIR" -o ! -d "$TRACING_DIR" ]; then + errexit "No ftrace directory found" +fi + +# Preparing logs +if [ "x$LOG_DIR" = "x-" ]; then + LOG_FILE= + date +else + LOG_FILE=$LOG_DIR/ftracetest.log + mkdir -p $LOG_DIR || errexit "Failed to make a log directory: $LOG_DIR" + date > $LOG_FILE +fi + +prlog() { # messages + [ -z "$LOG_FILE" ] && echo "$@" || echo "$@" | tee -a $LOG_FILE +} +catlog() { #file + [ -z "$LOG_FILE" ] && cat $1 || cat $1 | tee -a $LOG_FILE +} +prlog "=== Ftrace unit tests ===" + + +# Testcase management +# Test result codes - Dejagnu extended code +PASS=0 # The test succeeded. +FAIL=1 # The test failed, but was expected to succeed. +UNRESOLVED=2 # The test produced indeterminate results. (e.g. interrupted) +UNTESTED=3 # The test was not run, currently just a placeholder. +UNSUPPORTED=4 # The test failed because of lack of feature. +XFAIL=5 # The test failed, and was expected to fail. + +# Accumulations +PASSED_CASES= +FAILED_CASES= +UNRESOLVED_CASES= +UNTESTED_CASES= +UNSUPPORTED_CASES= +XFAILED_CASES= +UNDEFINED_CASES= +TOTAL_RESULT=0 + +INSTANCE= +CASENO=0 +testcase() { # testfile + CASENO=$((CASENO+1)) + desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:` + prlog -n "[$CASENO]$INSTANCE$desc" +} + +test_on_instance() { # testfile + grep -q "^#[ \t]*flags:.*instance" $1 +} + +eval_result() { # sigval + case $1 in + $PASS) + prlog " [PASS]" + PASSED_CASES="$PASSED_CASES $CASENO" + return 0 + ;; + $FAIL) + prlog " [FAIL]" + FAILED_CASES="$FAILED_CASES $CASENO" + return 1 # this is a bug. + ;; + $UNRESOLVED) + prlog " [UNRESOLVED]" + UNRESOLVED_CASES="$UNRESOLVED_CASES $CASENO" + return 1 # this is a kind of bug.. something happened. + ;; + $UNTESTED) + prlog " [UNTESTED]" + UNTESTED_CASES="$UNTESTED_CASES $CASENO" + return 0 + ;; + $UNSUPPORTED) + prlog " [UNSUPPORTED]" + UNSUPPORTED_CASES="$UNSUPPORTED_CASES $CASENO" + return $UNSUPPORTED_RESULT # depends on use case + ;; + $XFAIL) + prlog " [XFAIL]" + XFAILED_CASES="$XFAILED_CASES $CASENO" + return 0 + ;; + *) + prlog " [UNDEFINED]" + UNDEFINED_CASES="$UNDEFINED_CASES $CASENO" + return 1 # this must be a test bug + ;; + esac +} + +# Signal handling for result codes +SIG_RESULT= +SIG_BASE=36 # Use realtime signals +SIG_PID=$$ + +exit_pass () { + exit 0 +} + +SIG_FAIL=$((SIG_BASE + FAIL)) +exit_fail () { + exit 1 +} +trap 'SIG_RESULT=$FAIL' $SIG_FAIL + +SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED)) +exit_unresolved () { + kill -s $SIG_UNRESOLVED $SIG_PID + exit 0 +} +trap 'SIG_RESULT=$UNRESOLVED' $SIG_UNRESOLVED + +SIG_UNTESTED=$((SIG_BASE + UNTESTED)) +exit_untested () { + kill -s $SIG_UNTESTED $SIG_PID + exit 0 +} +trap 'SIG_RESULT=$UNTESTED' $SIG_UNTESTED + +SIG_UNSUPPORTED=$((SIG_BASE + UNSUPPORTED)) +exit_unsupported () { + kill -s $SIG_UNSUPPORTED $SIG_PID + exit 0 +} +trap 'SIG_RESULT=$UNSUPPORTED' $SIG_UNSUPPORTED + +SIG_XFAIL=$((SIG_BASE + XFAIL)) +exit_xfail () { + kill -s $SIG_XFAIL $SIG_PID + exit 0 +} +trap 'SIG_RESULT=$XFAIL' $SIG_XFAIL + +__run_test() { # testfile + # setup PID and PPID, $$ is not updated. + (cd $TRACING_DIR; read PID _ < /proc/self/stat; set -e; set -x; initialize_ftrace; . $1) + [ $? -ne 0 ] && kill -s $SIG_FAIL $SIG_PID +} + +# Run one test case +run_test() { # testfile + local testname=`basename $1` + if [ ! -z "$LOG_FILE" ] ; then + local testlog=`mktemp $LOG_DIR/${testname}-log.XXXXXX` + else + local testlog=/proc/self/fd/1 + fi + export TMPDIR=`mktemp -d /tmp/ftracetest-dir.XXXXXX` + testcase $1 + echo "execute$INSTANCE: "$1 > $testlog + SIG_RESULT=0 + if [ -z "$LOG_FILE" ]; then + __run_test $1 2>&1 + elif [ $VERBOSE -ge 3 ]; then + __run_test $1 | tee -a $testlog 2>&1 + elif [ $VERBOSE -eq 2 ]; then + __run_test $1 2>> $testlog | tee -a $testlog + else + __run_test $1 >> $testlog 2>&1 + fi + eval_result $SIG_RESULT + if [ $? -eq 0 ]; then + # Remove test log if the test was done as it was expected. + [ $KEEP_LOG -eq 0 -a ! -z "$LOG_FILE" ] && rm $testlog + else + [ $VERBOSE -eq 1 -o $VERBOSE -eq 2 ] && catlog $testlog + TOTAL_RESULT=1 + fi + rm -rf $TMPDIR +} + +# load in the helper functions +. $TEST_DIR/functions + +# Main loop +for t in $TEST_CASES; do + run_test $t +done + +# Test on instance loop +INSTANCE=" (instance) " +for t in $TEST_CASES; do + test_on_instance $t || continue + SAVED_TRACING_DIR=$TRACING_DIR + export TRACING_DIR=`mktemp -d $TRACING_DIR/instances/ftracetest.XXXXXX` + run_test $t + rmdir $TRACING_DIR + TRACING_DIR=$SAVED_TRACING_DIR +done + +prlog "" +prlog "# of passed: " `echo $PASSED_CASES | wc -w` +prlog "# of failed: " `echo $FAILED_CASES | wc -w` +prlog "# of unresolved: " `echo $UNRESOLVED_CASES | wc -w` +prlog "# of untested: " `echo $UNTESTED_CASES | wc -w` +prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w` +prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w` +prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w` + +# if no error, return 0 +exit $TOTAL_RESULT diff --git a/tools/testing/selftests/ftrace/samples/fail.tc b/tools/testing/selftests/ftrace/samples/fail.tc new file mode 100644 index 000000000..15e35b956 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/fail.tc @@ -0,0 +1,4 @@ +#!/bin/sh +# description: failure-case example +cat non-exist-file +echo "this is not executed" diff --git a/tools/testing/selftests/ftrace/samples/pass.tc b/tools/testing/selftests/ftrace/samples/pass.tc new file mode 100644 index 000000000..d01549370 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/pass.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: pass-case example +return 0 diff --git a/tools/testing/selftests/ftrace/samples/unresolved.tc b/tools/testing/selftests/ftrace/samples/unresolved.tc new file mode 100644 index 000000000..41e99d335 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/unresolved.tc @@ -0,0 +1,4 @@ +#!/bin/sh +# description: unresolved-case example +trap exit_unresolved INT +kill -INT $PID diff --git a/tools/testing/selftests/ftrace/samples/unsupported.tc b/tools/testing/selftests/ftrace/samples/unsupported.tc new file mode 100644 index 000000000..45910ff13 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/unsupported.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: unsupported-case example +exit_unsupported diff --git a/tools/testing/selftests/ftrace/samples/untested.tc b/tools/testing/selftests/ftrace/samples/untested.tc new file mode 100644 index 000000000..35a45946e --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/untested.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: untested-case example +exit_untested diff --git a/tools/testing/selftests/ftrace/samples/xfail.tc b/tools/testing/selftests/ftrace/samples/xfail.tc new file mode 100644 index 000000000..9dd395323 --- /dev/null +++ b/tools/testing/selftests/ftrace/samples/xfail.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: xfail-case example +cat non-exist-file || exit_xfail diff --git a/tools/testing/selftests/ftrace/settings b/tools/testing/selftests/ftrace/settings new file mode 100644 index 000000000..e7b941753 --- /dev/null +++ b/tools/testing/selftests/ftrace/settings @@ -0,0 +1 @@ +timeout=0 diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc new file mode 100644 index 000000000..9980ff14a --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/basic1.tc @@ -0,0 +1,3 @@ +#!/bin/sh +# description: Basic trace file check +test -f README -a -f trace -a -f tracing_on -a -f trace_pipe diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc new file mode 100644 index 000000000..531e47236 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/basic2.tc @@ -0,0 +1,9 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Basic test for tracers +# flags: instance +test -f available_tracers +for t in `cat available_tracers`; do + echo $t > current_tracer +done +echo nop > current_tracer diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc new file mode 100644 index 000000000..58a2506f7 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/basic3.tc @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Basic trace clock test +# flags: instance +test -f trace_clock +for c in `cat trace_clock | tr -d \[\]`; do + echo $c > trace_clock + grep '\['$c'\]' trace_clock +done +echo local > trace_clock diff --git a/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc new file mode 100644 index 000000000..0696098d6 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/basic4.tc @@ -0,0 +1,5 @@ +#!/bin/sh +# description: Basic event tracing check +test -f available_events -a -f set_event -a -d events +# check scheduler events are available +grep -q sched available_events && exit_pass || exit_fail diff --git a/tools/testing/selftests/ftrace/test.d/00basic/snapshot.tc b/tools/testing/selftests/ftrace/test.d/00basic/snapshot.tc new file mode 100644 index 000000000..3b1f45e13 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/snapshot.tc @@ -0,0 +1,28 @@ +#!/bin/sh +# description: Snapshot and tracing setting +# flags: instance + +[ ! -f snapshot ] && exit_unsupported + +echo "Set tracing off" +echo 0 > tracing_on + +echo "Allocate and take a snapshot" +echo 1 > snapshot + +# Since trace buffer is empty, snapshot is also empty, but allocated +grep -q "Snapshot is allocated" snapshot + +echo "Ensure keep tracing off" +test `cat tracing_on` -eq 0 + +echo "Set tracing on" +echo 1 > tracing_on + +echo "Take a snapshot again" +echo 1 > snapshot + +echo "Ensure keep tracing on" +test `cat tracing_on` -eq 1 + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/event/event-enable.tc b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc new file mode 100644 index 000000000..9daf03418 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/event/event-enable.tc @@ -0,0 +1,62 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event tracing - enable/disable with event level files +# flags: instance + +do_reset() { + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +yield() { + ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1 +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo 'sched:sched_switch' > set_event + +yield + +count=`cat trace | grep sched_switch | wc -l` +if [ $count -eq 0 ]; then + fail "sched_switch events are not recorded" +fi + +do_reset + +echo 1 > events/sched/sched_switch/enable + +yield + +count=`cat trace | grep sched_switch | wc -l` +if [ $count -eq 0 ]; then + fail "sched_switch events are not recorded" +fi + +do_reset + +echo 0 > events/sched/sched_switch/enable + +yield + +count=`cat trace | grep sched_switch | wc -l` +if [ $count -ne 0 ]; then + fail "sched_switch events should not be recorded" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/event/event-pid.tc b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc new file mode 100644 index 000000000..132478b30 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/event/event-pid.tc @@ -0,0 +1,74 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event tracing - restricts events based on pid +# flags: instance + +do_reset() { + echo > set_event + echo > set_event_pid + echo 0 > options/event-fork + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +yield() { + ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1 +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f set_event_pid ]; then + echo "event pid filtering is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo 1 > events/sched/sched_switch/enable + +yield + +count=`cat trace | grep sched_switch | wc -l` +if [ $count -eq 0 ]; then + fail "sched_switch events are not recorded" +fi + +do_reset + +read mypid rest < /proc/self/stat + +echo $mypid > set_event_pid +echo 'sched:sched_switch' > set_event + +yield + +count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l` +if [ $count -ne 0 ]; then + fail "sched_switch events from other task are recorded" +fi + +do_reset + +echo $mypid > set_event_pid +echo 1 > options/event-fork +echo 1 > events/sched/sched_switch/enable + +yield + +count=`cat trace | grep sched_switch | grep -v "pid=$mypid" | wc -l` +if [ $count -eq 0 ]; then + fail "sched_switch events from other task are not recorded" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc new file mode 100644 index 000000000..6a37a8642 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc @@ -0,0 +1,62 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event tracing - enable/disable with subsystem level files +# flags: instance + +do_reset() { + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +yield() { + ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1 +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo 'sched:*' > set_event + +yield + +count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` +if [ $count -lt 3 ]; then + fail "at least fork, exec and exit events should be recorded" +fi + +do_reset + +echo 1 > events/sched/enable + +yield + +count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` +if [ $count -lt 3 ]; then + fail "at least fork, exec and exit events should be recorded" +fi + +do_reset + +echo 0 > events/sched/enable + +yield + +count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` +if [ $count -ne 0 ]; then + fail "any of scheduler events should not be recorded" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc new file mode 100644 index 000000000..4e9b6e2c0 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc @@ -0,0 +1,65 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event tracing - enable/disable with top level files + +do_reset() { + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +yield() { + ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1 +} + +if [ ! -f available_events -o ! -f set_event -o ! -d events ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo '*:*' > set_event + +yield + +echo 0 > tracing_on + +count=`head -n 128 trace | grep -v ^# | wc -l` +if [ $count -eq 0 ]; then + fail "none of events are recorded" +fi + +do_reset + +echo 1 > events/enable +echo 1 > tracing_on + +yield + +echo 0 > tracing_on +count=`head -n 128 trace | grep -v ^# | wc -l` +if [ $count -eq 0 ]; then + fail "none of events are recorded" +fi + +do_reset + +echo 0 > events/enable + +yield + +count=`cat trace | grep -v ^# | wc -l` +if [ $count -ne 0 ]; then + fail "any of events should not be recorded" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc new file mode 100644 index 000000000..1aec99d10 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc @@ -0,0 +1,92 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - function graph filters with stack tracer + +# Make sure that function graph filtering works, and is not +# affected by other tracers enabled (like stack tracer) + +if ! grep -q function_graph available_tracers; then + echo "no function graph tracer configured" + exit_unsupported +fi + +if [ ! -f set_ftrace_filter ]; then + echo "set_ftrace_filter not found? Is dynamic ftrace not set?" + exit_unsupported +fi + +do_reset() { + reset_tracer + if [ -e /proc/sys/kernel/stack_tracer_enabled ]; then + echo 0 > /proc/sys/kernel/stack_tracer_enabled + fi + enable_tracing + clear_trace + echo > set_ftrace_filter +} + +fail() { # msg + do_reset + echo $1 + exit_fail +} + +disable_tracing +clear_trace; + +# filter something, schedule is always good +if ! echo "schedule" > set_ftrace_filter; then + # test for powerpc 64 + if ! echo ".schedule" > set_ftrace_filter; then + fail "can not enable schedule filter" + fi +fi + +echo function_graph > current_tracer + +if [ ! -f stack_trace ]; then + echo "Stack tracer not configured" + do_reset + exit_unsupported; +fi + +echo "Now testing with stack tracer" + +echo 1 > /proc/sys/kernel/stack_tracer_enabled + +disable_tracing +clear_trace +enable_tracing +sleep 1 + +count=`cat trace | grep '()' | grep -v schedule | wc -l` + +if [ $count -ne 0 ]; then + fail "Graph filtering not working with stack tracer?" +fi + +# Make sure we did find something +count=`cat trace | grep 'schedule()' | wc -l` +if [ $count -eq 0 ]; then + fail "No schedule traces found?" +fi + +echo 0 > /proc/sys/kernel/stack_tracer_enabled +clear_trace +sleep 1 + + +count=`cat trace | grep '()' | grep -v schedule | wc -l` + +if [ $count -ne 0 ]; then + fail "Graph filtering not working after stack tracer disabled?" +fi + +count=`cat trace | grep 'schedule()' | wc -l` +if [ $count -eq 0 ]; then + fail "No schedule traces found?" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc new file mode 100644 index 000000000..9f8d27ca3 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc @@ -0,0 +1,53 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - function graph filters + +# Make sure that function graph filtering works + +if ! grep -q function_graph available_tracers; then + echo "no function graph tracer configured" + exit_unsupported +fi + +do_reset() { + reset_tracer + enable_tracing + clear_trace +} + +fail() { # msg + do_reset + echo $1 + exit_fail +} + +disable_tracing +clear_trace + +# filter something, schedule is always good +if ! echo "schedule" > set_ftrace_filter; then + # test for powerpc 64 + if ! echo ".schedule" > set_ftrace_filter; then + fail "can not enable schedule filter" + fi +fi + +echo function_graph > current_tracer +enable_tracing +sleep 1 +# search for functions (has "()" on the line), and make sure +# that only the schedule function was found +count=`cat trace | grep '()' | grep -v schedule | wc -l` +if [ $count -ne 0 ]; then + fail "Graph filtering not working by itself?" +fi + +# Make sure we did find something +count=`cat trace | grep 'schedule()' | wc -l` +if [ $count -eq 0 ]; then + fail "No schedule traces found?" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc new file mode 100644 index 000000000..f4e92afab --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-glob.tc @@ -0,0 +1,62 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - function glob filters + +# Make sure that function glob matching filter works. + +if ! grep -q function available_tracers; then + echo "no function tracer configured" + exit_unsupported +fi + +disable_tracing +clear_trace + +ftrace_filter_check() { # glob grep + echo "$1" > set_ftrace_filter + cut -f1 -d" " set_ftrace_filter > $TMPDIR/actual + cut -f1 -d" " available_filter_functions | grep "$2" > $TMPDIR/expected + DIFF=`diff $TMPDIR/actual $TMPDIR/expected` + test -z "$DIFF" +} + +# filter by *, front match +ftrace_filter_check '*schedule' '^.*schedule$' + +# filter by *, middle match +ftrace_filter_check '*schedule*' '^.*schedule.*$' + +# filter by *, end match +ftrace_filter_check 'schedule*' '^schedule.*$' + +# filter by *mid*end +ftrace_filter_check '*pin*lock' '.*pin.*lock$' + +# filter by start*mid* +ftrace_filter_check 'mutex*try*' '^mutex.*try.*' + +# Advanced full-glob matching feature is recently supported. +# Skip the tests if we are sure the kernel does not support it. +if grep -q 'accepts: .* glob-matching-pattern' README ; then + +# filter by *, both side match +ftrace_filter_check 'sch*ule' '^sch.*ule$' + +# filter by char class. +ftrace_filter_check '[Ss]y[Ss]_*' '^[Ss]y[Ss]_.*$' + +# filter by ?, schedule is always good +if ! echo "sch?dule" > set_ftrace_filter; then + # test for powerpc 64 + if ! echo ".sch?dule" > set_ftrace_filter; then + fail "can not enable schedule filter" + fi + cat set_ftrace_filter | grep '^.schedule$' +else + cat set_ftrace_filter | grep '^schedule$' +fi + +fi + +echo > set_ftrace_filter +enable_tracing diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc new file mode 100644 index 000000000..524ce24b3 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc @@ -0,0 +1,118 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - function pid filters + +# Make sure that function pid matching filter works. +# Also test it on an instance directory + +if ! grep -q function available_tracers; then + echo "no function tracer configured" + exit_unsupported +fi + +if [ ! -f set_ftrace_pid ]; then + echo "set_ftrace_pid not found? Is function tracer not set?" + exit_unsupported +fi + +if [ ! -f set_ftrace_filter ]; then + echo "set_ftrace_filter not found? Is function tracer not set?" + exit_unsupported +fi + +do_function_fork=1 + +if [ ! -f options/function-fork ]; then + do_function_fork=0 + echo "no option for function-fork found. Option will not be tested." +fi + +read PID _ < /proc/self/stat + +if [ $do_function_fork -eq 1 ]; then + # default value of function-fork option + orig_value=`grep function-fork trace_options` +fi + +do_reset() { + reset_tracer + clear_trace + enable_tracing + echo > set_ftrace_filter + echo > set_ftrace_pid + + if [ $do_function_fork -eq 0 ]; then + return + fi + + echo $orig_value > trace_options +} + +fail() { # msg + do_reset + echo $1 + exit_fail +} + +yield() { + ping localhost -c 1 || sleep .001 || usleep 1 || sleep 1 +} + +do_test() { + disable_tracing + + echo do_execve* > set_ftrace_filter + echo *do_fork >> set_ftrace_filter + + echo $PID > set_ftrace_pid + echo function > current_tracer + + if [ $do_function_fork -eq 1 ]; then + # don't allow children to be traced + echo nofunction-fork > trace_options + fi + + enable_tracing + yield + + count_pid=`cat trace | grep -v ^# | grep $PID | wc -l` + count_other=`cat trace | grep -v ^# | grep -v $PID | wc -l` + + # count_other should be 0 + if [ $count_pid -eq 0 -o $count_other -ne 0 ]; then + fail "PID filtering not working?" + fi + + disable_tracing + clear_trace + + if [ $do_function_fork -eq 0 ]; then + return + fi + + # allow children to be traced + echo function-fork > trace_options + + enable_tracing + yield + + count_pid=`cat trace | grep -v ^# | grep $PID | wc -l` + count_other=`cat trace | grep -v ^# | grep -v $PID | wc -l` + + # count_other should NOT be 0 + if [ $count_pid -eq 0 -o $count_other -eq 0 ]; then + fail "PID filtering not following fork?" + fi +} + +do_test + +mkdir instances/foo +cd instances/foo +do_test +cd ../../ +rmdir instances/foo + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc new file mode 100644 index 000000000..6fed4cf2d --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc @@ -0,0 +1,123 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - test for function event triggers +# flags: instance +# +# Ftrace allows to add triggers to functions, such as enabling or disabling +# tracing, enabling or disabling trace events, or recording a stack trace +# within the ring buffer. +# +# This test is designed to test event triggers +# + +# The triggers are set within the set_ftrace_filter file +if [ ! -f set_ftrace_filter ]; then + echo "set_ftrace_filter not found? Is dynamic ftrace not set?" + exit_unsupported +fi + +do_reset() { + reset_ftrace_filter + reset_tracer + disable_events + clear_trace + enable_tracing +} + +fail() { # mesg + do_reset + echo $1 + exit_fail +} + +SLEEP_TIME=".1" + +do_reset + +echo "Testing function probes with events:" + +EVENT="sched:sched_switch" +EVENT_ENABLE="events/sched/sched_switch/enable" + +cnt_trace() { + grep -v '^#' trace | wc -l +} + +test_event_enabled() { + val=$1 + + e=`cat $EVENT_ENABLE` + if [ "$e" != $val ]; then + fail "Expected $val but found $e" + fi +} + +run_enable_disable() { + enable=$1 # enable + Enable=$2 # Enable + check_disable=$3 # 0 + check_enable_star=$4 # 1* + check_disable_star=$5 # 0* + + cnt=`cnt_trace` + if [ $cnt -ne 0 ]; then + fail "Found junk in trace file" + fi + + echo "$Enable event all the time" + + echo $check_disable > $EVENT_ENABLE + sleep $SLEEP_TIME + + test_event_enabled $check_disable + + echo "schedule:${enable}_event:$EVENT" > set_ftrace_filter + if [ -d ../../instances ]; then # Check instances + cur=`cat set_ftrace_filter` + top=`cat ../../set_ftrace_filter` + if [ "$cur" = "$top" ]; then + echo "This kernel is too old to support per instance filter" + reset_ftrace_filter + exit_unsupported + fi + fi + + echo " make sure it works 5 times" + + for i in `seq 5`; do + sleep $SLEEP_TIME + echo " test $i" + test_event_enabled $check_enable_star + + echo $check_disable > $EVENT_ENABLE + done + sleep $SLEEP_TIME + echo " make sure it's still works" + test_event_enabled $check_enable_star + + reset_ftrace_filter + + echo " make sure it only works 3 times" + + echo $check_disable > $EVENT_ENABLE + sleep $SLEEP_TIME + + echo "schedule:${enable}_event:$EVENT:3" > set_ftrace_filter + + for i in `seq 3`; do + sleep $SLEEP_TIME + echo " test $i" + test_event_enabled $check_enable_star + + echo $check_disable > $EVENT_ENABLE + done + + sleep $SLEEP_TIME + echo " make sure it stop working" + test_event_enabled $check_disable_star + + do_reset +} + +run_enable_disable enable Enable 0 "1*" "0*" +run_enable_disable disable Disable 1 "0*" "1*" diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc new file mode 100644 index 000000000..b2d5a8feb --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc @@ -0,0 +1,81 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - function profiler with function tracing + +# There was a bug after a rewrite of the ftrace infrastructure that +# caused the function_profiler not to be able to run with the function +# tracer, because the function_profiler used the function_graph tracer +# and it was assumed the two could not run simultaneously. +# +# There was another related bug where the solution to the first bug +# broke the way filtering of the function tracer worked. +# +# This test triggers those bugs on those kernels. +# +# We need function_graph and profiling to to run this test +if ! grep -q function_graph available_tracers; then + echo "no function graph tracer configured" + exit_unsupported; +fi + +if [ ! -f set_ftrace_filter ]; then + echo "set_ftrace_filter not found? Is dynamic ftrace not set?" + exit_unsupported +fi + +if [ ! -f function_profile_enabled ]; then + echo "function_profile_enabled not found, function profiling enabled?" + exit_unsupported +fi + +fail() { # mesg + reset_tracer + echo > set_ftrace_filter + echo $1 + exit_fail +} + +echo "Testing function tracer with profiler:" +echo "enable function tracer" +echo function > current_tracer +echo "enable profiler" +echo 1 > function_profile_enabled + +sleep 1 + +echo "Now filter on just schedule" +echo '*schedule' > set_ftrace_filter +clear_trace + +echo "Now disable function profiler" +echo 0 > function_profile_enabled + +sleep 1 + +# make sure only schedule functions exist + +echo "testing if only schedule is being traced" +if grep -v -e '^#' -e 'schedule' trace; then + fail "more than schedule was found" +fi + +echo "Make sure schedule was traced" +if ! grep -e 'schedule' trace > /dev/null; then + cat trace + fail "can not find schedule in trace" +fi + +echo > set_ftrace_filter +clear_trace + +sleep 1 + +echo "make sure something other than scheduler is being traced" +if ! grep -v -e '^#' -e 'schedule' trace > /dev/null; then + cat trace + fail "no other functions besides schedule was found" +fi + +reset_tracer + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc new file mode 100644 index 000000000..68e7a48f5 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc @@ -0,0 +1,170 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - test reading of set_ftrace_filter +# +# The set_ftrace_filter file of ftrace is used to list functions as well as +# triggers (probes) attached to functions. The code to read this file is not +# straight forward and has had various bugs in the past. This test is designed +# to add functions and triggers to that file in various ways and read that +# file in various ways (cat vs dd). +# + +# The triggers are set within the set_ftrace_filter file +if [ ! -f set_ftrace_filter ]; then + echo "set_ftrace_filter not found? Is dynamic ftrace not set?" + exit_unsupported +fi + +do_reset() { + reset_tracer + reset_ftrace_filter + disable_events + clear_trace + enable_tracing +} + +fail() { # mesg + do_reset + echo $1 + exit_fail +} + +do_reset + +FILTER=set_ftrace_filter +FUNC1="schedule" +FUNC2="do_softirq" + +ALL_FUNCS="#### all functions enabled ####" + +test_func() { + if ! echo "$1" | grep -q "^$2\$"; then + return 0 + fi + echo "$1" | grep -v "^$2\$" + return 1 +} + +check_set_ftrace_filter() { + cat=`cat $FILTER` + dd1=`dd if=$FILTER bs=1 | grep -v -e 'records in' -e 'records out' -e 'bytes copied'` + dd100=`dd if=$FILTER bs=100 | grep -v -e 'records in' -e 'records out' -e 'bytes copied'` + + echo "Testing '$@'" + + while [ $# -gt 0 ]; do + echo "test $1" + if cat=`test_func "$cat" "$1"`; then + return 0 + fi + if dd1=`test_func "$dd1" "$1"`; then + return 0 + fi + if dd100=`test_func "$dd100" "$1"`; then + return 0 + fi + shift + done + + if [ -n "$cat" ]; then + return 0 + fi + if [ -n "$dd1" ]; then + return 0 + fi + if [ -n "$dd100" ]; then + return 0 + fi + return 1; +} + +if check_set_ftrace_filter "$ALL_FUNCS"; then + fail "Expected only $ALL_FUNCS" +fi + +echo "$FUNC1:traceoff" > set_ftrace_filter +if check_set_ftrace_filter "$ALL_FUNCS" "$FUNC1:traceoff:unlimited"; then + fail "Expected $ALL_FUNCS and $FUNC1:traceoff:unlimited" +fi + +echo "$FUNC1" > set_ftrace_filter +if check_set_ftrace_filter "$FUNC1" "$FUNC1:traceoff:unlimited"; then + fail "Expected $FUNC1 and $FUNC1:traceoff:unlimited" +fi + +echo "$FUNC2" >> set_ftrace_filter +if check_set_ftrace_filter "$FUNC1" "$FUNC2" "$FUNC1:traceoff:unlimited"; then + fail "Expected $FUNC1 $FUNC2 and $FUNC1:traceoff:unlimited" +fi + +echo "$FUNC2:traceoff" >> set_ftrace_filter +if check_set_ftrace_filter "$FUNC1" "$FUNC2" "$FUNC1:traceoff:unlimited" "$FUNC2:traceoff:unlimited"; then + fail "Expected $FUNC1 $FUNC2 $FUNC1:traceoff:unlimited and $FUNC2:traceoff:unlimited" +fi + +echo "$FUNC1" > set_ftrace_filter +if check_set_ftrace_filter "$FUNC1" "$FUNC1:traceoff:unlimited" "$FUNC2:traceoff:unlimited"; then + fail "Expected $FUNC1 $FUNC1:traceoff:unlimited and $FUNC2:traceoff:unlimited" +fi + +echo > set_ftrace_filter +if check_set_ftrace_filter "$ALL_FUNCS" "$FUNC1:traceoff:unlimited" "$FUNC2:traceoff:unlimited"; then + fail "Expected $ALL_FUNCS $FUNC1:traceoff:unlimited and $FUNC2:traceoff:unlimited" +fi + +reset_ftrace_filter + +if check_set_ftrace_filter "$ALL_FUNCS"; then + fail "Expected $ALL_FUNCS" +fi + +echo "$FUNC1" > set_ftrace_filter +if check_set_ftrace_filter "$FUNC1" ; then + fail "Expected $FUNC1" +fi + +echo "$FUNC2" >> set_ftrace_filter +if check_set_ftrace_filter "$FUNC1" "$FUNC2" ; then + fail "Expected $FUNC1 and $FUNC2" +fi + +test_actual() { # Compares $TMPDIR/expected with set_ftrace_filter + cat set_ftrace_filter | grep -v '#' | cut -d' ' -f1 | cut -d':' -f1 | sort -u > $TMPDIR/actual + DIFF=`diff $TMPDIR/actual $TMPDIR/expected` + test -z "$DIFF" +} + +# Set traceoff trigger for all fuctions with "lock" in their name +cat available_filter_functions | cut -d' ' -f1 | grep 'lock' | sort -u > $TMPDIR/expected +echo '*lock*:traceoff' > set_ftrace_filter +test_actual + +# now remove all with 'try' in it, and end with lock +grep -v 'try.*lock$' $TMPDIR/expected > $TMPDIR/expected2 +mv $TMPDIR/expected2 $TMPDIR/expected +echo '!*try*lock:traceoff' >> set_ftrace_filter +test_actual + +# remove all that start with "m" and end with "lock" +grep -v '^m.*lock$' $TMPDIR/expected > $TMPDIR/expected2 +mv $TMPDIR/expected2 $TMPDIR/expected +echo '!m*lock:traceoff' >> set_ftrace_filter +test_actual + +# remove all that start with "c" and have "unlock" +grep -v '^c.*unlock' $TMPDIR/expected > $TMPDIR/expected2 +mv $TMPDIR/expected2 $TMPDIR/expected +echo '!c*unlock*:traceoff' >> set_ftrace_filter +test_actual + +# clear all the rest +> $TMPDIR/expected +echo '!*:traceoff' >> set_ftrace_filter +test_actual + +rm $TMPDIR/expected +rm $TMPDIR/actual + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc new file mode 100644 index 000000000..f6d9ac732 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc @@ -0,0 +1,186 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: ftrace - test for function traceon/off triggers +# flags: instance +# +# Ftrace allows to add triggers to functions, such as enabling or disabling +# tracing, enabling or disabling trace events, or recording a stack trace +# within the ring buffer. +# +# This test is designed to test enabling and disabling tracing triggers +# + +# The triggers are set within the set_ftrace_filter file +if [ ! -f set_ftrace_filter ]; then + echo "set_ftrace_filter not found? Is dynamic ftrace not set?" + exit_unsupported +fi + +do_reset() { + reset_ftrace_filter + reset_tracer + disable_events + clear_trace + enable_tracing +} + +fail() { # mesg + do_reset + echo $1 + exit_fail +} + +SLEEP_TIME=".1" + +do_reset + +echo "Testing function probes with enabling disabling tracing:" + +cnt_trace() { + grep -v '^#' trace | wc -l +} + +echo '** DISABLE TRACING' +disable_tracing +clear_trace + +cnt=`cnt_trace` +if [ $cnt -ne 0 ]; then + fail "Found junk in trace" +fi + + +echo '** ENABLE EVENTS' + +echo 1 > events/enable + +echo '** ENABLE TRACING' +enable_tracing + +cnt=`cnt_trace` +if [ $cnt -eq 0 ]; then + fail "Nothing found in trace" +fi + +# powerpc uses .schedule +func="schedule" +available_file=available_filter_functions +if [ -d ../../instances -a -f ../../available_filter_functions ]; then + available_file=../../available_filter_functions +fi +x=`grep '^\.schedule$' available_filter_functions | wc -l` +if [ "$x" -eq 1 ]; then + func=".schedule" +fi + +echo '** SET TRACEOFF' + +echo "$func:traceoff" > set_ftrace_filter +if [ -d ../../instances ]; then # Check instances + cur=`cat set_ftrace_filter` + top=`cat ../../set_ftrace_filter` + if [ "$cur" = "$top" ]; then + echo "This kernel is too old to support per instance filter" + reset_ftrace_filter + exit_unsupported + fi +fi + +cnt=`grep schedule set_ftrace_filter | wc -l` +if [ $cnt -ne 1 ]; then + fail "Did not find traceoff trigger" +fi + +cnt=`cnt_trace` +sleep $SLEEP_TIME +cnt2=`cnt_trace` + +if [ $cnt -ne $cnt2 ]; then + fail "Tracing is not stopped" +fi + +on=`cat tracing_on` +if [ $on != "0" ]; then + fail "Tracing is not off" +fi + +csum1=`md5sum trace` +sleep $SLEEP_TIME +csum2=`md5sum trace` + +if [ "$csum1" != "$csum2" ]; then + fail "Tracing file is still changing" +fi + +clear_trace + +cnt=`cnt_trace` +if [ $cnt -ne 0 ]; then + fail "Tracing is still happeing" +fi + +echo "!$func:traceoff" >> set_ftrace_filter + +cnt=`grep schedule set_ftrace_filter | wc -l` +if [ $cnt -ne 0 ]; then + fail "traceoff trigger still exists" +fi + +on=`cat tracing_on` +if [ $on != "0" ]; then + fail "Tracing is started again" +fi + +echo "$func:traceon" > set_ftrace_filter + +cnt=`grep schedule set_ftrace_filter | wc -l` +if [ $cnt -ne 1 ]; then + fail "traceon trigger not found" +fi + +cnt=`cnt_trace` +if [ $cnt -eq 0 ]; then + fail "Tracing did not start" +fi + +on=`cat tracing_on` +if [ $on != "1" ]; then + fail "Tracing was not enabled" +fi + + +echo "!$func:traceon" >> set_ftrace_filter + +cnt=`grep schedule set_ftrace_filter | wc -l` +if [ $cnt -ne 0 ]; then + fail "traceon trigger still exists" +fi + +check_sleep() { + val=$1 + sleep $SLEEP_TIME + cat set_ftrace_filter + on=`cat tracing_on` + if [ $on != "$val" ]; then + fail "Expected tracing_on to be $val, but it was $on" + fi +} + + +echo "$func:traceoff:3" > set_ftrace_filter +check_sleep "0" +echo 1 > tracing_on +check_sleep "0" +echo 1 > tracing_on +check_sleep "0" +echo 1 > tracing_on +check_sleep "1" +echo "!$func:traceoff:0" > set_ftrace_filter + +if grep -e traceon -e traceoff set_ftrace_filter; then + fail "Tracing on and off triggers still exist" +fi + +disable_events + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions new file mode 100644 index 000000000..e4645d5e3 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/functions @@ -0,0 +1,100 @@ + +clear_trace() { # reset trace output + echo > trace +} + +disable_tracing() { # stop trace recording + echo 0 > tracing_on +} + +enable_tracing() { # start trace recording + echo 1 > tracing_on +} + +reset_tracer() { # reset the current tracer + echo nop > current_tracer +} + +reset_trigger_file() { + # remove action triggers first + grep -H ':on[^:]*(' $@ | + while read line; do + cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["` + file=`echo $line | cut -f1 -d:` + echo "!$cmd" >> $file + done + grep -Hv ^# $@ | + while read line; do + cmd=`echo $line | cut -f2- -d: | cut -f1 -d"["` + file=`echo $line | cut -f1 -d:` + echo "!$cmd" > $file + done +} + +reset_trigger() { # reset all current setting triggers + if [ -d events/synthetic ]; then + reset_trigger_file events/synthetic/*/trigger + fi + reset_trigger_file events/*/*/trigger +} + +reset_events_filter() { # reset all current setting filters + grep -v ^none events/*/*/filter | + while read line; do + echo 0 > `echo $line | cut -f1 -d:` + done +} + +reset_ftrace_filter() { # reset all triggers in set_ftrace_filter + echo > set_ftrace_filter + grep -v '^#' set_ftrace_filter | while read t; do + tr=`echo $t | cut -d: -f2` + if [ "$tr" = "" ]; then + continue + fi + if ! grep -q "$t" set_ftrace_filter; then + continue; + fi + name=`echo $t | cut -d: -f1 | cut -d' ' -f1` + if [ $tr = "enable_event" -o $tr = "disable_event" ]; then + tr=`echo $t | cut -d: -f2-4` + limit=`echo $t | cut -d: -f5` + else + tr=`echo $t | cut -d: -f2` + limit=`echo $t | cut -d: -f3` + fi + if [ "$limit" != "unlimited" ]; then + tr="$tr:$limit" + fi + echo "!$name:$tr" > set_ftrace_filter + done +} + +disable_events() { + echo 0 > events/enable +} + +clear_synthetic_events() { # reset all current synthetic events + grep -v ^# synthetic_events | + while read line; do + echo "!$line" >> synthetic_events + done +} + +initialize_ftrace() { # Reset ftrace to initial-state +# As the initial state, ftrace will be set to nop tracer, +# no events, no triggers, no filters, no function filters, +# no probes, and tracing on. + disable_tracing + reset_tracer + reset_trigger + reset_events_filter + disable_events + echo > set_event_pid # event tracer is always on + [ -f set_ftrace_filter ] && echo | tee set_ftrace_* + [ -f set_graph_function ] && echo | tee set_graph_* + [ -f stack_trace_filter ] && echo > stack_trace_filter + [ -f kprobe_events ] && echo > kprobe_events + [ -f uprobe_events ] && echo > uprobe_events + enable_tracing +} diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc new file mode 100644 index 000000000..4fa0f7914 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/instances/instance-event.tc @@ -0,0 +1,146 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Test creation and deletion of trace instances while setting an event + +if [ ! -d instances ] ; then + echo "no instance directory with this kernel" + exit_unsupported; +fi + +fail() { # mesg + rmdir foo 2>/dev/null + echo $1 + set -e + exit_fail +} + +cd instances + +# we don't want to fail on error +set +e + +mkdir x +rmdir x +result=$? + +if [ $result -ne 0 ]; then + echo "instance rmdir not supported" + exit_unsupported +fi + +instance_slam() { + while :; do + mkdir foo 2> /dev/null + rmdir foo 2> /dev/null + done +} + +instance_read() { + while :; do + cat foo/trace 1> /dev/null 2>&1 + done +} + +instance_set() { + while :; do + echo 1 > foo/events/sched/sched_switch + done 2> /dev/null +} + +instance_slam & +p1=$! +echo $p1 + +instance_set & +p2=$! +echo $p2 + +instance_read & +p3=$! +echo $p3 + +sleep 1 + +kill -1 $p3 +kill -1 $p2 +kill -1 $p1 + +echo "Wait for processes to finish" +wait $p1 $p2 $p3 +echo "all processes finished, wait for cleanup" +sleep 1 + +mkdir foo +ls foo > /dev/null +rmdir foo +if [ -d foo ]; then + fail "foo still exists" +fi + +mkdir foo +echo "schedule:enable_event:sched:sched_switch" > foo/set_ftrace_filter +rmdir foo +if [ -d foo ]; then + fail "foo still exists" +fi +if grep -q "schedule:enable_event:sched:sched_switch" ../set_ftrace_filter; then + echo "Older kernel detected. Cleanup filter" + echo '!schedule:enable_event:sched:sched_switch' > ../set_ftrace_filter +fi + +instance_slam() { + while :; do + mkdir x + mkdir y + mkdir z + rmdir x + rmdir y + rmdir z + done 2>/dev/null +} + +instance_slam & +p1=$! +echo $p1 + +instance_slam & +p2=$! +echo $p2 + +instance_slam & +p3=$! +echo $p3 + +instance_slam & +p4=$! +echo $p4 + +instance_slam & +p5=$! +echo $p5 + +ls -lR >/dev/null +sleep 1 + +kill -1 $p1 +kill -1 $p2 +kill -1 $p3 +kill -1 $p4 +kill -1 $p5 + +echo "Wait for processes to finish" +wait $p1 $p2 $p3 $p4 $p5 +echo "all processes finished, wait for cleanup" + +mkdir x y z +ls x y z +rmdir x y z +for d in x y z; do + if [ -d $d ]; then + fail "instance $d still exists" + fi +done + +set -e + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/instances/instance.tc b/tools/testing/selftests/ftrace/test.d/instances/instance.tc new file mode 100644 index 000000000..b84651283 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/instances/instance.tc @@ -0,0 +1,86 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Test creation and deletion of trace instances + +if [ ! -d instances ] ; then + echo "no instance directory with this kernel" + exit_unsupported; +fi + +fail() { # mesg + rmdir x y z 2>/dev/null + echo $1 + set -e + exit_fail +} + +cd instances + +# we don't want to fail on error +set +e + +mkdir x +rmdir x +result=$? + +if [ $result -ne 0 ]; then + echo "instance rmdir not supported" + exit_unsupported +fi + +instance_slam() { + while :; do + mkdir x + mkdir y + mkdir z + rmdir x + rmdir y + rmdir z + done 2>/dev/null +} + +instance_slam & +p1=$! +echo $p1 + +instance_slam & +p2=$! +echo $p2 + +instance_slam & +p3=$! +echo $p3 + +instance_slam & +p4=$! +echo $p4 + +instance_slam & +p5=$! +echo $p5 + +ls -lR >/dev/null +sleep 1 + +kill -1 $p1 +kill -1 $p2 +kill -1 $p3 +kill -1 $p4 +kill -1 $p5 + +echo "Wait for processes to finish" +wait $p1 $p2 $p3 $p4 $p5 +echo "all processes finished, wait for cleanup" + +mkdir x y z +ls x y z +rmdir x y z +for d in x y z; do + if [ -d $d ]; then + fail "instance $d still exists" + fi +done + +set -e + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc new file mode 100644 index 000000000..4604d2103 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/add_and_remove.tc @@ -0,0 +1,13 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe dynamic event - adding and removing + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +echo 0 > events/enable +echo > kprobe_events +echo p:myevent _do_fork > kprobe_events +grep myevent kprobe_events +test -d events/kprobes/myevent +echo > kprobe_events +clear_trace diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc new file mode 100644 index 000000000..bbc443a91 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc @@ -0,0 +1,15 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe dynamic event - busy event check + +[ -f kprobe_events ] || exit_unsupported + +echo 0 > events/enable +echo > kprobe_events +echo p:myevent _do_fork > kprobe_events +test -d events/kprobes/myevent +echo 1 > events/kprobes/myevent/enable +echo > kprobe_events && exit_fail # this must fail +echo 0 > events/kprobes/myevent/enable +echo > kprobe_events # this must succeed +clear_trace diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc new file mode 100644 index 000000000..8b43c6804 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc @@ -0,0 +1,18 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe dynamic event with arguments + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +echo 0 > events/enable +echo > kprobe_events +echo 'p:testprobe _do_fork $stack $stack0 +0($stack)' > kprobe_events +grep testprobe kprobe_events +test -d events/kprobes/testprobe +echo 1 > events/kprobes/testprobe/enable +( echo "forked") +echo 0 > events/kprobes/testprobe/enable +echo "-:testprobe" >> kprobe_events +clear_trace +test -d events/kprobes/testprobe && exit_fail || exit_pass + diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc new file mode 100644 index 000000000..1ad70cdaf --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc @@ -0,0 +1,48 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe event string type argument + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +echo 0 > events/enable +echo > kprobe_events + +case `uname -m` in +x86_64) + ARG1=%di +;; +i[3456]86) + ARG1=%ax +;; +aarch64) + ARG1=%x0 +;; +arm*) + ARG1=%r0 +;; +ppc64*) + ARG1=%r3 +;; +ppc*) + ARG1=%r3 +;; +*) + echo "Please implement other architecture here" + exit_untested +esac + +: "Test get argument (1)" +echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):string" > kprobe_events +echo 1 > events/kprobes/testprobe/enable +echo "p:test _do_fork" >> kprobe_events +grep -qe "testprobe.* arg1=\"test\"" trace + +echo 0 > events/kprobes/testprobe/enable +: "Test get argument (2)" +echo "p:testprobe tracefs_create_dir arg1=+0(${ARG1}):string arg2=+0(${ARG1}):string" > kprobe_events +echo 1 > events/kprobes/testprobe/enable +echo "p:test _do_fork" >> kprobe_events +grep -qe "testprobe.* arg1=\"test\" arg2=\"test\"" trace + +echo 0 > events/enable +echo > kprobe_events diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc new file mode 100644 index 000000000..92ffb3bd3 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc @@ -0,0 +1,107 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe event argument syntax + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +grep "x8/16/32/64" README > /dev/null || exit_unsupported # version issue + +echo 0 > events/enable +echo > kprobe_events + +PROBEFUNC="vfs_read" +GOODREG= +BADREG= +GOODSYM="_sdata" +if ! grep -qw ${GOODSYM} /proc/kallsyms ; then + GOODSYM=$PROBEFUNC +fi +BADSYM="deaqswdefr" +SYMADDR=0x`grep -w ${GOODSYM} /proc/kallsyms | cut -f 1 -d " "` +GOODTYPE="x16" +BADTYPE="y16" + +case `uname -m` in +x86_64|i[3456]86) + GOODREG=%ax + BADREG=%ex +;; +aarch64) + GOODREG=%x0 + BADREG=%ax +;; +arm*) + GOODREG=%r0 + BADREG=%ax +;; +ppc*) + GOODREG=%r3 + BADREG=%msr +;; +*) + echo "Please implement other architecture here" + exit_untested +esac + +test_goodarg() # Good-args +{ + while [ "$1" ]; do + echo "p ${PROBEFUNC} $1" > kprobe_events + shift 1 + done; +} + +test_badarg() # Bad-args +{ + while [ "$1" ]; do + ! echo "p ${PROBEFUNC} $1" > kprobe_events + shift 1 + done; +} + +echo > kprobe_events + +: "Register access" +test_goodarg ${GOODREG} +test_badarg ${BADREG} + +: "Symbol access" +test_goodarg "@${GOODSYM}" "@${SYMADDR}" "@${GOODSYM}+10" "@${GOODSYM}-10" +test_badarg "@" "@${BADSYM}" "@${GOODSYM}*10" "@${GOODSYM}/10" \ + "@${GOODSYM}%10" "@${GOODSYM}&10" "@${GOODSYM}|10" + +: "Stack access" +test_goodarg "\$stack" "\$stack0" "\$stack1" +test_badarg "\$stackp" "\$stack0+10" "\$stack1-10" + +: "Retval access" +echo "r ${PROBEFUNC} \$retval" > kprobe_events +! echo "p ${PROBEFUNC} \$retval" > kprobe_events + +# $comm was introduced in 4.8, older kernels reject it. +if grep -A1 "fetcharg:" README | grep -q '\$comm' ; then +: "Comm access" +test_goodarg "\$comm" +fi + +: "Indirect memory access" +test_goodarg "+0(${GOODREG})" "-0(${GOODREG})" "+10(\$stack)" \ + "+0(\$stack1)" "+10(@${GOODSYM}-10)" "+0(+10(+20(\$stack)))" +test_badarg "+(${GOODREG})" "(${GOODREG}+10)" "-(${GOODREG})" "(${GOODREG})" \ + "+10(\$comm)" "+0(${GOODREG})+10" + +: "Name assignment" +test_goodarg "varname=${GOODREG}" +test_badarg "varname=varname2=${GOODREG}" + +: "Type syntax" +test_goodarg "${GOODREG}:${GOODTYPE}" +test_badarg "${GOODREG}::${GOODTYPE}" "${GOODREG}:${BADTYPE}" \ + "${GOODTYPE}:${GOODREG}" + +: "Combination check" + +test_goodarg "\$comm:string" "+0(\$stack):string" +test_badarg "\$comm:x64" "\$stack:string" "${GOODREG}:string" + +echo > kprobe_events diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc new file mode 100644 index 000000000..2a1755bfc --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc @@ -0,0 +1,38 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobes event arguments with types + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +grep "x8/16/32/64" README > /dev/null || exit_unsupported # version issue + +echo 0 > events/enable +echo > kprobe_events +enable_tracing + +echo 'p:testprobe _do_fork $stack0:s32 $stack0:u32 $stack0:x32 $stack0:b8@4/32' > kprobe_events +grep testprobe kprobe_events +test -d events/kprobes/testprobe + +echo 1 > events/kprobes/testprobe/enable +( echo "forked") +echo 0 > events/kprobes/testprobe/enable +ARGS=`tail -n 1 trace | sed -e 's/.* arg1=\(.*\) arg2=\(.*\) arg3=\(.*\) arg4=\(.*\)/\1 \2 \3 \4/'` + +check_types() { + X1=`printf "%x" $1 | tail -c 8` + X2=`printf "%x" $2` + X3=`printf "%x" $3` + test $X1 = $X2 + test $X2 = $X3 + test 0x$X3 = $3 + + B4=`printf "%02x" $4` + B3=`echo -n $X3 | tail -c 3 | head -c 2` + test $B3 = $B4 +} +check_types $ARGS + +echo "-:testprobe" >> kprobe_events +clear_trace +test -d events/kprobes/testprobe && exit_fail || exit_pass diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc new file mode 100644 index 000000000..2724a1068 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_eventname.tc @@ -0,0 +1,37 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe event auto/manual naming + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +disable_events +echo > kprobe_events + +:;: "Add an event on function without name" ;: + +FUNC=`grep " [tT] .*vfs_read$" /proc/kallsyms | tail -n 1 | cut -f 3 -d " "` +[ "x" != "x$FUNC" ] || exit_unresolved +echo "p $FUNC" > kprobe_events +PROBE_NAME=`echo $FUNC | tr ".:" "_"` +test -d events/kprobes/p_${PROBE_NAME}_0 || exit_failure + +:;: "Add an event on function with new name" ;: + +echo "p:event1 $FUNC" > kprobe_events +test -d events/kprobes/event1 || exit_failure + +:;: "Add an event on function with new name and group" ;: + +echo "p:kprobes2/event2 $FUNC" > kprobe_events +test -d events/kprobes2/event2 || exit_failure + +:;: "Add an event on dot function without name" ;: + +FUNC=`grep -m 10 " [tT] .*\.isra\..*$" /proc/kallsyms | tail -n 1 | cut -f 3 -d " "` +[ "x" != "x$FUNC" ] || exit_unresolved +echo "p $FUNC" > kprobe_events +EVENT=`grep $FUNC kprobe_events | cut -f 1 -d " " | cut -f 2 -d:` +[ "x" != "x$EVENT" ] || exit_failure +test -d events/$EVENT || exit_failure + +echo > kprobe_events diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc new file mode 100644 index 000000000..cc4cac0e6 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_ftrace.tc @@ -0,0 +1,56 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe dynamic event with function tracer + +[ -f kprobe_events ] || exit_unsupported # this is configurable +grep function available_tracers || exit_unsupported # this is configurable + +# prepare +echo nop > current_tracer +echo _do_fork > set_ftrace_filter +echo 0 > events/enable +echo > kprobe_events +echo 'p:testprobe _do_fork' > kprobe_events + +# kprobe on / ftrace off +echo 1 > events/kprobes/testprobe/enable +echo > trace +( echo "forked") +grep testprobe trace +! grep '_do_fork <-' trace + +# kprobe on / ftrace on +echo function > current_tracer +echo > trace +( echo "forked") +grep testprobe trace +grep '_do_fork <-' trace + +# kprobe off / ftrace on +echo 0 > events/kprobes/testprobe/enable +echo > trace +( echo "forked") +! grep testprobe trace +grep '_do_fork <-' trace + +# kprobe on / ftrace on +echo 1 > events/kprobes/testprobe/enable +echo function > current_tracer +echo > trace +( echo "forked") +grep testprobe trace +grep '_do_fork <-' trace + +# kprobe on / ftrace off +echo nop > current_tracer +echo > trace +( echo "forked") +grep testprobe trace +! grep '_do_fork <-' trace + +# cleanup +echo nop > current_tracer +echo > set_ftrace_filter +echo 0 > events/kprobes/testprobe/enable +echo > kprobe_events +echo > trace diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc new file mode 100644 index 000000000..1e9f75f7a --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_module.tc @@ -0,0 +1,29 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe dynamic event - probing module + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +disable_events +echo > kprobe_events + +:;: "Add an event on a module function without specifying event name" ;: + +MOD=`lsmod | head -n 2 | tail -n 1 | cut -f1 -d" "` +FUNC=`grep -m 1 ".* t .*\\[$MOD\\]" /proc/kallsyms | xargs | cut -f3 -d" "` +[ "x" != "x$MOD" -a "y" != "y$FUNC" ] || exit_unresolved +echo "p $MOD:$FUNC" > kprobe_events +PROBE_NAME=`echo $MOD:$FUNC | tr ".:" "_"` +test -d events/kprobes/p_${PROBE_NAME}_0 || exit_failure + +:;: "Add an event on a module function with new event name" ;: + +echo "p:event1 $MOD:$FUNC" > kprobe_events +test -d events/kprobes/event1 || exit_failure + +:;: "Add an event on a module function with new event and group name" ;: + +echo "p:kprobes1/event1 $MOD:$FUNC" > kprobe_events +test -d events/kprobes1/event1 || exit_failure + +echo > kprobe_events diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc new file mode 100644 index 000000000..321954683 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc @@ -0,0 +1,17 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kretprobe dynamic event with arguments + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +echo 0 > events/enable +echo > kprobe_events +echo 'r:testprobe2 _do_fork $retval' > kprobe_events +grep testprobe2 kprobe_events +test -d events/kprobes/testprobe2 +echo 1 > events/kprobes/testprobe2/enable +( echo "forked") +echo 0 > events/kprobes/testprobe2/enable +echo '-:testprobe2' >> kprobe_events +clear_trace +test -d events/kprobes/testprobe2 && exit_fail || exit_pass diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc new file mode 100644 index 000000000..7c0290684 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_maxactive.tc @@ -0,0 +1,41 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kretprobe dynamic event with maxactive + +[ -f kprobe_events ] || exit_unsupported # this is configurable +grep -q 'r\[maxactive\]' README || exit_unsupported # this is older version + +echo > kprobe_events + +# Test if we successfully reject unknown messages +if echo 'a:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi + +# Test if we successfully reject too big maxactive +if echo 'r1000000:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi + +# Test if we successfully reject unparsable numbers for maxactive +if echo 'r10fuzz:myprobeaccept inet_csk_accept' > kprobe_events; then false; else true; fi + +# Test for kretprobe with event name without maxactive +echo 'r:myprobeaccept inet_csk_accept' > kprobe_events +grep myprobeaccept kprobe_events +test -d events/kprobes/myprobeaccept +echo '-:myprobeaccept' >> kprobe_events + +# Test for kretprobe with event name with a small maxactive +echo 'r10:myprobeaccept inet_csk_accept' > kprobe_events +grep myprobeaccept kprobe_events +test -d events/kprobes/myprobeaccept +echo '-:myprobeaccept' >> kprobe_events + +# Test for kretprobe without event name without maxactive +echo 'r inet_csk_accept' > kprobe_events +grep inet_csk_accept kprobe_events +echo > kprobe_events + +# Test for kretprobe without event name with a small maxactive +echo 'r10 inet_csk_accept' > kprobe_events +grep inet_csk_accept kprobe_events +echo > kprobe_events + +clear_trace diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc new file mode 100644 index 000000000..da298f191 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc @@ -0,0 +1,39 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Register/unregister many kprobe events + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +# ftrace fentry skip size depends on the machine architecture. +# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le +case `uname -m` in + x86_64|i[3456]86) OFFS=5;; + ppc64le) OFFS=8;; + *) OFFS=0;; +esac + +if [ -d events/kprobes ]; then + echo 0 > events/kprobes/enable + echo > kprobe_events +fi + +N=0 +echo "Setup up kprobes on first available 256 text symbols" +grep -i " t " /proc/kallsyms | cut -f3 -d" " | grep -v .*\\..* | \ +while read i; do + echo p ${i}+${OFFS} >> kprobe_events && N=$((N+1)) ||: + test $N -eq 256 && break +done + +L=`cat kprobe_events | wc -l` +if [ $L -ne 256 ]; then + echo "The number of kprobes events ($L) is not 256" + exit_fail +fi + +echo 1 > events/kprobes/enable +echo 0 > events/kprobes/enable +echo > kprobe_events +echo "Waiting for unoptimizing & freeing" +sleep 5 +echo "Done" diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc b/tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc new file mode 100644 index 000000000..519d2763f --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/kprobe/probepoint.tc @@ -0,0 +1,43 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: Kprobe events - probe points + +[ -f kprobe_events ] || exit_unsupported # this is configurable + +TARGET_FUNC=tracefs_create_dir + +dec_addr() { # hexaddr + printf "%d" "0x"`echo $1 | tail -c 8` +} + +set_offs() { # prev target next + A1=`dec_addr $1` + A2=`dec_addr $2` + A3=`dec_addr $3` + TARGET="0x$2" # an address + PREV=`expr $A1 - $A2` # offset to previous symbol + NEXT=+`expr $A3 - $A2` # offset to next symbol + OVERFLOW=+`printf "0x%x" ${PREV}` # overflow offset to previous symbol +} + +# We have to decode symbol addresses to get correct offsets. +# If the offset is not an instruction boundary, it cause -EILSEQ. +set_offs `grep -A1 -B1 ${TARGET_FUNC} /proc/kallsyms | cut -f 1 -d " " | xargs` + +UINT_TEST=no +# printf "%x" -1 returns (unsigned long)-1. +if [ `printf "%x" -1 | wc -c` != 9 ]; then + UINT_TEST=yes +fi + +echo 0 > events/enable +echo > kprobe_events +echo "p:testprobe ${TARGET_FUNC}" > kprobe_events +echo "p:testprobe ${TARGET}" > kprobe_events +echo "p:testprobe ${TARGET_FUNC}${NEXT}" > kprobe_events +! echo "p:testprobe ${TARGET_FUNC}${PREV}" > kprobe_events +if [ "${UINT_TEST}" = yes ]; then +! echo "p:testprobe ${TARGET_FUNC}${OVERFLOW}" > kprobe_events +fi +echo > kprobe_events +clear_trace diff --git a/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc b/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc new file mode 100644 index 000000000..cbd174334 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc @@ -0,0 +1,73 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: test for the preemptirqsoff tracer + +MOD=preemptirq_delay_test + +fail() { + reset_tracer + rmmod $MOD || true + exit_fail +} + +unsup() { #msg + reset_tracer + rmmod $MOD || true + echo $1 + exit_unsupported +} + +modprobe $MOD || unsup "$MOD module not available" +rmmod $MOD + +grep -q "preemptoff" available_tracers || unsup "preemptoff tracer not enabled" +grep -q "irqsoff" available_tracers || unsup "irqsoff tracer not enabled" + +reset_tracer + +# Simulate preemptoff section for half a second couple of times +echo preemptoff > current_tracer +sleep 1 +modprobe $MOD test_mode=preempt delay=500000 || fail +rmmod $MOD || fail +modprobe $MOD test_mode=preempt delay=500000 || fail +rmmod $MOD || fail +modprobe $MOD test_mode=preempt delay=500000 || fail +rmmod $MOD || fail + +cat trace + +# Confirm which tracer +grep -q "tracer: preemptoff" trace || fail + +# Check the end of the section +egrep -q "5.....us : <stack trace>" trace || fail + +# Check for 500ms of latency +egrep -q "latency: 5..... us" trace || fail + +reset_tracer + +# Simulate irqsoff section for half a second couple of times +echo irqsoff > current_tracer +sleep 1 +modprobe $MOD test_mode=irq delay=500000 || fail +rmmod $MOD || fail +modprobe $MOD test_mode=irq delay=500000 || fail +rmmod $MOD || fail +modprobe $MOD test_mode=irq delay=500000 || fail +rmmod $MOD || fail + +cat trace + +# Confirm which tracer +grep -q "tracer: irqsoff" trace || fail + +# Check the end of the section +egrep -q "5.....us : <stack trace>" trace || fail + +# Check for 500ms of latency +egrep -q "latency: 5..... us" trace || fail + +reset_tracer +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/template b/tools/testing/selftests/ftrace/test.d/template new file mode 100644 index 000000000..5c39ceb18 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/template @@ -0,0 +1,10 @@ +#!/bin/sh +# description: %HERE DESCRIBE WHAT THIS DOES% +# you have to add ".tc" extention for your testcase file +# Note that all tests are run with "errexit" option. + +exit 0 # Return 0 if the test is passed, otherwise return !0 +# Or you can call exit_pass for passed test, and exit_fail for failed test. +# If the test could not run because of lack of feature, call exit_unsupported +# If the test returned unclear results, call exit_unresolved +# If the test is a dummy, or a placeholder, call exit_untested diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc new file mode 100644 index 000000000..2aabab363 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-extended-error-support.tc @@ -0,0 +1,39 @@ +#!/bin/sh +# description: event trigger - test extended error support + + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo "Test extended error support" +echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_wakeup/trigger +! echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' >> events/sched/sched_wakeup/trigger 2> /dev/null +if ! grep -q "ERROR:" events/sched/sched_wakeup/hist; then + fail "Failed to generate extended error in histogram" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc new file mode 100644 index 000000000..7fd5b4a8f --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc @@ -0,0 +1,54 @@ +#!/bin/sh +# description: event trigger - test field variable support + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +clear_synthetic_events +reset_tracer +do_reset + +echo "Test field variable support" + +echo 'wakeup_latency u64 lat; pid_t pid; int prio; char comm[16]' > synthetic_events +echo 'hist:keys=comm:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_waking/trigger +echo 'hist:keys=next_comm:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,sched.sched_waking.prio,next_comm) if next_comm=="ping"' > events/sched/sched_switch/trigger +echo 'hist:keys=pid,prio,comm:vals=lat:sort=pid,prio' > events/synthetic/wakeup_latency/trigger + +ping localhost -c 3 +if ! grep -q "ping" events/synthetic/wakeup_latency/hist; then + fail "Failed to create inter-event histogram" +fi + +if ! grep -q "synthetic_prio=prio" events/sched/sched_waking/hist; then + fail "Failed to create histogram with field variable" +fi + +echo '!hist:keys=next_comm:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).wakeup_latency($wakeup_lat,next_pid,sched.sched_waking.prio,next_comm) if next_comm=="ping"' >> events/sched/sched_switch/trigger + +if grep -q "synthetic_prio=prio" events/sched/sched_waking/hist; then + fail "Failed to remove histogram with field variable" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc new file mode 100644 index 000000000..c93dbe38b --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc @@ -0,0 +1,58 @@ +#!/bin/sh +# description: event trigger - test inter-event combined histogram trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +reset_tracer +do_reset +clear_synthetic_events + +echo "Test create synthetic event" + +echo 'waking_latency u64 lat pid_t pid' > synthetic_events +if [ ! -d events/synthetic/waking_latency ]; then + fail "Failed to create waking_latency synthetic event" +fi + +echo "Test combined histogram" + +echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_waking/trigger +echo 'hist:keys=pid:waking_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).waking_latency($waking_lat,pid) if comm=="ping"' > events/sched/sched_wakeup/trigger +echo 'hist:keys=pid,lat:sort=pid,lat' > events/synthetic/waking_latency/trigger + +echo 'wakeup_latency u64 lat pid_t pid' >> synthetic_events +echo 'hist:keys=pid:ts1=common_timestamp.usecs if comm=="ping"' >> events/sched/sched_wakeup/trigger +echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts1:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid) if next_comm=="ping"' > events/sched/sched_switch/trigger + +echo 'waking+wakeup_latency u64 lat; pid_t pid' >> synthetic_events +echo 'hist:keys=pid,lat:sort=pid,lat:ww_lat=$waking_lat+$wakeup_lat:onmatch(synthetic.wakeup_latency).waking+wakeup_latency($ww_lat,pid)' >> events/synthetic/wakeup_latency/trigger +echo 'hist:keys=pid,lat:sort=pid,lat' >> events/synthetic/waking+wakeup_latency/trigger + +ping localhost -c 3 +if ! grep -q "pid:" events/synthetic/waking+wakeup_latency/hist; then + fail "Failed to create combined histogram" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc new file mode 100644 index 000000000..c193dce61 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-multi-actions-accept.tc @@ -0,0 +1,44 @@ +#!/bin/sh +# description: event trigger - test multiple actions on hist trigger + + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +clear_synthetic_events +reset_tracer +do_reset + +echo "Test multiple actions on hist trigger" +echo 'wakeup_latency u64 lat; pid_t pid' >> synthetic_events +TRIGGER1=events/sched/sched_wakeup/trigger +TRIGGER2=events/sched/sched_switch/trigger + +echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="cyclictest"' > $TRIGGER1 +echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0 if next_comm=="cyclictest"' >> $TRIGGER2 +echo 'hist:keys=next_pid:onmatch(sched.sched_wakeup).wakeup_latency(sched.sched_switch.$wakeup_lat,next_pid) if next_comm=="cyclictest"' >> $TRIGGER2 +echo 'hist:keys=next_pid:onmatch(sched.sched_wakeup).wakeup_latency(sched.sched_switch.$wakeup_lat,prev_pid) if next_comm=="cyclictest"' >> $TRIGGER2 +echo 'hist:keys=next_pid if next_comm=="cyclictest"' >> $TRIGGER2 + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc new file mode 100644 index 000000000..e84e7d048 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc @@ -0,0 +1,50 @@ +#!/bin/sh +# description: event trigger - test inter-event histogram trigger onmatch action + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +clear_synthetic_events +reset_tracer +do_reset + +echo "Test create synthetic event" + +echo 'wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events +if [ ! -d events/synthetic/wakeup_latency ]; then + fail "Failed to create wakeup_latency synthetic event" +fi + +echo "Test create histogram for synthetic event" +echo "Test histogram variables,simple expression support and onmatch action" + +echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_wakeup/trigger +echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid,next_comm) if next_comm=="ping"' > events/sched/sched_switch/trigger +echo 'hist:keys=comm,pid,lat:wakeup_lat=lat:sort=lat' > events/synthetic/wakeup_latency/trigger +ping localhost -c 5 +if ! grep -q "ping" events/synthetic/wakeup_latency/hist; then + fail "Failed to create onmatch action inter-event histogram" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc new file mode 100644 index 000000000..7907d8aac --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc @@ -0,0 +1,50 @@ +#!/bin/sh +# description: event trigger - test inter-event histogram trigger onmatch-onmax action + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +clear_synthetic_events +reset_tracer +do_reset + +echo "Test create synthetic event" + +echo 'wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events +if [ ! -d events/synthetic/wakeup_latency ]; then + fail "Failed to create wakeup_latency synthetic event" +fi + +echo "Test create histogram for synthetic event" +echo "Test histogram variables,simple expression support and onmatch-onmax action" + +echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' > events/sched/sched_wakeup/trigger +echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_wakeup).wakeup_latency($wakeup_lat,next_pid,next_comm):onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm) if next_comm=="ping"' >> events/sched/sched_switch/trigger +echo 'hist:keys=comm,pid,lat:wakeup_lat=lat:sort=lat' > events/synthetic/wakeup_latency/trigger +ping localhost -c 5 +if [ ! grep -q "ping" events/synthetic/wakeup_latency/hist -o ! grep -q "max:" events/sched/sched_switch/hist]; then + fail "Failed to create onmatch-onmax action inter-event histogram" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc new file mode 100644 index 000000000..38b7ed624 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc @@ -0,0 +1,48 @@ +#!/bin/sh +# description: event trigger - test inter-event histogram trigger onmax action + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +clear_synthetic_events +reset_tracer +do_reset + +echo "Test create synthetic event" + +echo 'wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events +if [ ! -d events/synthetic/wakeup_latency ]; then + fail "Failed to create wakeup_latency synthetic event" +fi + +echo "Test onmax action" + +echo 'hist:keys=pid:ts0=common_timestamp.usecs if comm=="ping"' >> events/sched/sched_waking/trigger +echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:onmax($wakeup_lat).save(next_comm,prev_pid,prev_prio,prev_comm) if next_comm=="ping"' >> events/sched/sched_switch/trigger +ping localhost -c 3 +if ! grep -q "max:" events/sched/sched_switch/hist; then + fail "Failed to create onmax action inter-event histogram" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc new file mode 100644 index 000000000..c604438df --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-createremove.tc @@ -0,0 +1,54 @@ +#!/bin/sh +# description: event trigger - test synthetic event create remove +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +clear_synthetic_events +reset_tracer +do_reset + +echo "Test create synthetic event" + +echo 'wakeup_latency u64 lat pid_t pid char comm[16]' > synthetic_events +if [ ! -d events/synthetic/wakeup_latency ]; then + fail "Failed to create wakeup_latency synthetic event" +fi + +reset_trigger + +echo "Test remove synthetic event" +echo '!wakeup_latency u64 lat pid_t pid char comm[16]' >> synthetic_events +if [ -d events/synthetic/wakeup_latency ]; then + fail "Failed to delete wakeup_latency synthetic event" +fi + +reset_trigger + +echo "Test create synthetic event with an error" +echo 'wakeup_latency u64 lat pid_t pid char' > synthetic_events > /dev/null +if [ -d events/synthetic/wakeup_latency ]; then + fail "Created wakeup_latency synthetic event with an invalid format" +fi + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc new file mode 100644 index 000000000..88e6c3f43 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-syntax.tc @@ -0,0 +1,80 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test synthetic_events syntax parser + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic event is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo "Test synthetic_events syntax parser" + +echo > synthetic_events + +# synthetic event must have a field +! echo "myevent" >> synthetic_events +echo "myevent u64 var1" >> synthetic_events + +# synthetic event must be found in synthetic_events +grep "myevent[[:space:]]u64 var1" synthetic_events + +# it is not possible to add same name event +! echo "myevent u64 var2" >> synthetic_events + +# Non-append open will cleanup all events and add new one +echo "myevent u64 var2" > synthetic_events + +# multiple fields with different spaces +echo "myevent u64 var1; u64 var2;" > synthetic_events +grep "myevent[[:space:]]u64 var1; u64 var2" synthetic_events +echo "myevent u64 var1 ; u64 var2 ;" > synthetic_events +grep "myevent[[:space:]]u64 var1; u64 var2" synthetic_events +echo "myevent u64 var1 ;u64 var2" > synthetic_events +grep "myevent[[:space:]]u64 var1; u64 var2" synthetic_events + +# test field types +echo "myevent u32 var" > synthetic_events +echo "myevent u16 var" > synthetic_events +echo "myevent u8 var" > synthetic_events +echo "myevent s64 var" > synthetic_events +echo "myevent s32 var" > synthetic_events +echo "myevent s16 var" > synthetic_events +echo "myevent s8 var" > synthetic_events + +echo "myevent char var" > synthetic_events +echo "myevent int var" > synthetic_events +echo "myevent long var" > synthetic_events +echo "myevent pid_t var" > synthetic_events + +echo "myevent unsigned char var" > synthetic_events +echo "myevent unsigned int var" > synthetic_events +echo "myevent unsigned long var" > synthetic_events +grep "myevent[[:space:]]unsigned long var" synthetic_events + +# test string type +echo "myevent char var[10]" > synthetic_events +grep "myevent[[:space:]]char\[10\] var" synthetic_events + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc new file mode 100644 index 000000000..28cc355a3 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc @@ -0,0 +1,66 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test event enable/disable trigger +# flags: instance + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep enable_event events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "event enable/disable trigger is not supported" + exit_unsupported +fi + +echo "Test enable_event trigger" +echo 0 > events/sched/sched_switch/enable +echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat events/sched/sched_switch/enable` != '1*' ]; then + fail "enable_event trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test disable_event trigger" +echo 1 > events/sched/sched_switch/enable +echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat events/sched/sched_switch/enable` != '0*' ]; then + fail "disable_event trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test semantic error for event enable/disable trigger" +! echo 'enable_event:nogroup:noevent' > events/sched/sched_process_fork/trigger +! echo 'disable_event+1' > events/sched/sched_process_fork/trigger +echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger +! echo 'enable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger +! echo 'disable_event:sched:sched_switch' > events/sched/sched_process_fork/trigger + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc new file mode 100644 index 000000000..a48e23eb8 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc @@ -0,0 +1,61 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test trigger filter +# flags: instance + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo "Test trigger filter" +echo 1 > tracing_on +echo 'traceoff if child_pid == 0' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat tracing_on` -ne 1 ]; then + fail "traceoff trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test semantic error for trigger filter" +! echo 'traceoff if a' > events/sched/sched_process_fork/trigger +! echo 'traceoff if common_pid=0' > events/sched/sched_process_fork/trigger +! echo 'traceoff if common_pid==b' > events/sched/sched_process_fork/trigger +echo 'traceoff if common_pid == 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger +! echo 'traceoff if common_pid == child_pid' > events/sched/sched_process_fork/trigger +echo 'traceoff if common_pid <= 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger +echo 'traceoff if common_pid >= 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger +echo 'traceoff if parent_pid >= 0 && child_pid >= 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger +echo 'traceoff if parent_pid >= 0 || child_pid >= 0' > events/sched/sched_process_fork/trigger +echo '!traceoff' > events/sched/sched_process_fork/trigger + + + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc new file mode 100644 index 000000000..8da80efc4 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc @@ -0,0 +1,76 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test histogram modifiers +# flags: instance + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/hist ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo "Test histogram with execname modifier" + +echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +COMM=`cat /proc/$$/comm` +grep "common_pid: $COMM" events/sched/sched_process_fork/hist > /dev/null || \ + fail "execname modifier on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with hex modifier" + +echo 'hist:keys=parent_pid.hex' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +# Note that $$ is the parent pid. $PID is current PID. +HEX=`printf %x $PID` +grep "parent_pid: $HEX" events/sched/sched_process_fork/hist > /dev/null || \ + fail "hex modifier on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with syscall modifier" + +echo 'hist:keys=id.syscall' > events/raw_syscalls/sys_exit/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep "id: \(unknown_\|sys_\)" events/raw_syscalls/sys_exit/hist > /dev/null || \ + fail "syscall modifier on raw_syscalls/sys_exit did not work" + + +reset_trigger + +echo "Test histgram with log2 modifier" + +echo 'hist:keys=bytes_req.log2' > events/kmem/kmalloc/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep 'bytes_req: ~ 2^[0-9]*' events/kmem/kmalloc/hist > /dev/null || \ + fail "log2 modifier on kmem/kmalloc did not work" + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc new file mode 100644 index 000000000..449fe9ff9 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc @@ -0,0 +1,84 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test histogram trigger +# flags: instance + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/hist ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo "Test histogram basic tigger" + +echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \ + fail "hist trigger on sched_process_fork did not work" +grep child events/sched/sched_process_fork/hist > /dev/null || \ + fail "hist trigger on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with compound keys" + +echo 'hist:keys=parent_pid,child_pid' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep '^{ parent_pid:.*, child_pid:.*}' events/sched/sched_process_fork/hist > /dev/null || \ + fail "compound keys on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with string key" + +echo 'hist:keys=parent_comm' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +COMM=`cat /proc/$$/comm` +grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \ + fail "string key on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with sort key" + +echo 'hist:keys=parent_pid,child_pid:sort=child_pid.ascending' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done + +check_inc() { + while [ $# -gt 1 ]; do + [ $1 -gt $2 ] && return 1 + shift 1 + done + return 0 +} +check_inc `grep -o "child_pid:[[:space:]]*[[:digit:]]*" \ + events/sched/sched_process_fork/hist | cut -d: -f2 ` || + fail "sort param on sched_process_fork did not work" + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc new file mode 100644 index 000000000..c5ef8b9d0 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc @@ -0,0 +1,74 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test multiple histogram triggers +# flags: instance + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/hist ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +reset_trigger + +echo "Test histogram multiple tiggers" + +echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger +echo 'hist:keys=parent_comm:vals=child_pid' >> events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep parent_pid events/sched/sched_process_fork/hist > /dev/null || \ + fail "hist trigger on sched_process_fork did not work" +grep child events/sched/sched_process_fork/hist > /dev/null || \ + fail "hist trigger on sched_process_fork did not work" +COMM=`cat /proc/$$/comm` +grep "parent_comm: $COMM" events/sched/sched_process_fork/hist > /dev/null || \ + fail "string key on sched_process_fork did not work" + +reset_trigger + +echo "Test histogram with its name" + +echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_fork/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep test_hist events/sched/sched_process_fork/hist > /dev/null || \ + fail "named event on sched_process_fork did not work" + +echo "Test same named histogram on different events" + +echo 'hist:name=test_hist:keys=common_pid' > events/sched/sched_process_exit/trigger +for i in `seq 1 10` ; do ( echo "forked" > /dev/null); done +grep test_hist events/sched/sched_process_exit/hist > /dev/null || \ + fail "named event on sched_process_fork did not work" + +diffs=`diff events/sched/sched_process_exit/hist events/sched/sched_process_fork/hist | wc -l` +test $diffs -eq 0 || fail "Same name histograms are not same" + +reset_trigger + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc new file mode 100644 index 000000000..ed38f0050 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc @@ -0,0 +1,62 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test snapshot-trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +if [ ! -f snapshot ]; then + echo "snapshot is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep snapshot events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "snapshot trigger is not supported" + exit_unsupported +fi + +echo "Test snapshot tigger" +echo 0 > snapshot +echo 1 > events/sched/sched_process_fork/enable +( echo "forked") +echo 'snapshot:1' > events/sched/sched_process_fork/trigger +( echo "forked") +grep sched_process_fork snapshot > /dev/null || \ + fail "snapshot trigger on sched_process_fork did not work" + +reset_trigger +echo 0 > snapshot +echo 0 > events/sched/sched_process_fork/enable + +echo "Test snapshot semantic errors" + +! echo "snapshot+1" > events/sched/sched_process_fork/trigger +echo "snapshot" > events/sched/sched_process_fork/trigger +! echo "snapshot" > events/sched/sched_process_fork/trigger + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc new file mode 100644 index 000000000..3121d795a --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc @@ -0,0 +1,54 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test stacktrace-trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +FEATURE=`grep stacktrace events/sched/sched_process_fork/trigger` +if [ -z "$FEATURE" ]; then + echo "stacktrace trigger is not supported" + exit_unsupported +fi + +echo "Test stacktrace tigger" +echo 0 > trace +echo 0 > options/stacktrace +echo 'stacktrace' > events/sched/sched_process_fork/trigger +( echo "forked") +grep "<stack trace>" trace > /dev/null || \ + fail "stacktrace trigger on sched_process_fork did not work" + +reset_trigger + +echo "Test stacktrace semantic errors" + +! echo "stacktrace:foo" > events/sched/sched_process_fork/trigger +echo "stacktrace" > events/sched/sched_process_fork/trigger +! echo "stacktrace" > events/sched/sched_process_fork/trigger + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-hist.tc new file mode 100644 index 000000000..2acbfe2c0 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-hist.tc @@ -0,0 +1,49 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: trace_marker trigger - test histogram trigger +# flags: instance + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -d events/ftrace/print ]; then + echo "event trace_marker is not supported" + exit_unsupported +fi + +if [ ! -f events/ftrace/print/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +if [ ! -f events/ftrace/print/hist ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +do_reset + +echo "Test histogram trace_marker tigger" + +echo 'hist:keys=common_pid' > events/ftrace/print/trigger +for i in `seq 1 10` ; do echo "hello" > trace_marker; done +grep 'hitcount: *10$' events/ftrace/print/hist > /dev/null || \ + fail "hist trigger did not trigger correct times on trace_marker" + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-snapshot.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-snapshot.tc new file mode 100644 index 000000000..6748e8cb4 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-snapshot.tc @@ -0,0 +1,74 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: trace_marker trigger - test snapshot trigger +# flags: instance + +do_reset() { + reset_trigger + echo > set_event + echo 0 > snapshot + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f snapshot ]; then + echo "snapshot is not supported" + exit_unsupported +fi + +if [ ! -d events/ftrace/print ]; then + echo "event trace_marker is not supported" + exit_unsupported +fi + +if [ ! -f events/ftrace/print/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +test_trace() { + file=$1 + x=$2 + + cat $file | while read line; do + comment=`echo $line | sed -e 's/^#//'` + if [ "$line" != "$comment" ]; then + continue + fi + echo "testing $line for >$x<" + match=`echo $line | sed -e "s/>$x<//"` + if [ "$line" == "$match" ]; then + fail "$line does not have >$x< in it" + fi + let x=$x+2 + done +} + +do_reset + +echo "Test snapshot trace_marker tigger" + +echo 'snapshot' > events/ftrace/print/trigger + +# make sure the snapshot is allocated + +grep -q 'Snapshot is allocated' snapshot + +for i in `seq 1 10` ; do echo "hello >$i<" > trace_marker; done + +test_trace trace 1 +test_trace snapshot 2 + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-synthetic-kernel.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-synthetic-kernel.tc new file mode 100644 index 000000000..0a69c5d1c --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-synthetic-kernel.tc @@ -0,0 +1,68 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: trace_marker trigger - test histogram with synthetic event against kernel event +# flags: + +do_reset() { + reset_trigger + echo > set_event + echo > synthetic_events + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic events not supported" + exit_unsupported +fi + +if [ ! -d events/ftrace/print ]; then + echo "event trace_marker is not supported" + exit_unsupported +fi + +if [ ! -d events/sched/sched_waking ]; then + echo "event sched_waking is not supported" + exit_unsupported +fi + +if [ ! -f events/ftrace/print/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +if [ ! -f events/ftrace/print/hist ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +do_reset + +echo "Test histogram kernel event to trace_marker latency histogram trigger" + +echo 'latency u64 lat' > synthetic_events +echo 'hist:keys=pid:ts0=common_timestamp.usecs' > events/sched/sched_waking/trigger +echo 'hist:keys=common_pid:lat=common_timestamp.usecs-$ts0:onmatch(sched.sched_waking).latency($lat)' > events/ftrace/print/trigger +echo 'hist:keys=common_pid,lat:sort=lat' > events/synthetic/latency/trigger +sleep 1 +echo "hello" > trace_marker + +grep 'hitcount: *1$' events/ftrace/print/hist > /dev/null || \ + fail "hist trigger did not trigger correct times on trace_marker" + +grep 'hitcount: *1$' events/synthetic/latency/hist > /dev/null || \ + fail "hist trigger did not trigger " + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-synthetic.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-synthetic.tc new file mode 100644 index 000000000..3666dd6ab --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-trace-marker-synthetic.tc @@ -0,0 +1,66 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: trace_marker trigger - test histogram with synthetic event +# flags: + +do_reset() { + reset_trigger + echo > set_event + echo > synthetic_events + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f synthetic_events ]; then + echo "synthetic events not supported" + exit_unsupported +fi + +if [ ! -d events/ftrace/print ]; then + echo "event trace_marker is not supported" + exit_unsupported +fi + +if [ ! -f events/ftrace/print/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +if [ ! -f events/ftrace/print/hist ]; then + echo "hist trigger is not supported" + exit_unsupported +fi + +do_reset + +echo "Test histogram trace_marker to trace_marker latency histogram trigger" + +echo 'latency u64 lat' > synthetic_events +echo 'hist:keys=common_pid:ts0=common_timestamp.usecs if buf == "start"' > events/ftrace/print/trigger +echo 'hist:keys=common_pid:lat=common_timestamp.usecs-$ts0:onmatch(ftrace.print).latency($lat) if buf == "end"' >> events/ftrace/print/trigger +echo 'hist:keys=common_pid,lat:sort=lat' > events/synthetic/latency/trigger +echo -n "start" > trace_marker +echo -n "end" > trace_marker + +cnt=`grep 'hitcount: *1$' events/ftrace/print/hist | wc -l` + +if [ $cnt -ne 2 ]; then + fail "hist trace_marker trigger did not trigger correctly" +fi + +grep 'hitcount: *1$' events/synthetic/latency/hist > /dev/null || \ + fail "hist trigger did not trigger " + +do_reset + +exit 0 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc new file mode 100644 index 000000000..c59d9eb54 --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc @@ -0,0 +1,59 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event trigger - test traceon/off trigger + +do_reset() { + reset_trigger + echo > set_event + clear_trace +} + +fail() { #msg + do_reset + echo $1 + exit_fail +} + +if [ ! -f set_event -o ! -d events/sched ]; then + echo "event tracing is not supported" + exit_unsupported +fi + +if [ ! -f events/sched/sched_process_fork/trigger ]; then + echo "event trigger is not supported" + exit_unsupported +fi + +reset_tracer +do_reset + +echo "Test traceoff trigger" +echo 1 > tracing_on +echo 'traceoff' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat tracing_on` -ne 0 ]; then + fail "traceoff trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test traceon trigger" +echo 0 > tracing_on +echo 'traceon' > events/sched/sched_process_fork/trigger +( echo "forked") +if [ `cat tracing_on` -ne 1 ]; then + fail "traceoff trigger on sched_process_fork did not work" +fi + +reset_trigger + +echo "Test semantic error for traceoff/on trigger" +! echo 'traceoff:badparam' > events/sched/sched_process_fork/trigger +! echo 'traceoff+0' > events/sched/sched_process_fork/trigger +echo 'traceon' > events/sched/sched_process_fork/trigger +! echo 'traceon' > events/sched/sched_process_fork/trigger +! echo 'traceoff' > events/sched/sched_process_fork/trigger + +do_reset + +exit 0 |