perf test: Introduce script for Arm CoreSight testing

We need a simple method to test Perf with ARM CoreSight drivers, this
could be used for smoke testing when new patch is coming for perf or
CoreSight drivers, and we also can use the test to confirm if the
CoreSight has been enabled successfully on new platforms.

This patch introduces the shell script test_arm_coresight.sh which is
under the 'pert test' framework.  This script provides three testing
scenarios:

Test scenario 1: traverse all possible paths between source and sink

For traversing possible paths, simply to say, the testing rationale is
source oriented testing, it traverses every source (now only refers to
ETM device) and test its all possible sinks.  To search the complete
paths from one specific source to its sinks, this patch relies on the
sysfs '/sys/bus/coresight/devices/devX/out:Y' for depth-first search
(DFS) for iteration connected device nodes, if the output device is
detected as a sink device (the script will exclude TPIU device which can
not be supported for perf PMU), then it will test trace data recording
and decoding for it.

The script runs three output testings for every trace data:

- Test branch samples dumping with 'perf script' command;

- Test branch samples reporting with 'perf report' command;

- Use option '--itrace=i1000i' to insert synthesized instructions events
  and the script will check if perf can output the percentage value
  successfully based on the instruction samples.

Test scenario 2: system-wide test

For system-wide testing, it passes option '-a' to perf tool to enable
tracing on all CPUs, so it's hard to say which program will be traced.
But perf tool itself contributes much overload in this case, so it will
parse trace data and check if process 'perf' can be detected or not.

Test scenario 3: snapshot mode test.

For snapshot mode testing, it uses 'dd' command to launch a long running
program, so this can give chance to send signal -USR2; it will check the
captured trace data contains 'dd' related thread info or not.

If any test fails, it will report failure and directly exit with error.
This test will be only applied on a platform with PMU event 'cs_etm//',
otherwise will skip the testing.

Below is detailed usage for it:

  # cd $linux/tools/perf  -> This is important so can use shell script
  # perf test list
    [...]
    70: probe libc's inet_pton & backtrace it with ping
    71: Check Arm CoreSight trace data recording and synthesized samples
    72: Check open filename arg using perf trace + vfs_getname
    73: Zstd perf.data compression/decompression
    74: Add vfs_getname probe to get syscall args filenames
    75: Use vfs_getname probe to get syscall args filenames

  # perf test 71
    71: Check Arm CoreSight trace data recording and branch samples: Ok

Signed-off-by: Leo Yan <leo.yan@linaro.org>
Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Reviewed-by: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20200907130154.9601-1-leo.yan@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Leo Yan 2020-09-07 21:01:54 +08:00 committed by Arnaldo Carvalho de Melo
parent 9e34c1c87e
commit fe0aed19b2

View file

@ -0,0 +1,183 @@
#!/bin/sh
# Check Arm CoreSight trace data recording and synthesized samples
# Uses the 'perf record' to record trace data with Arm CoreSight sinks;
# then verify if there have any branch samples and instruction samples
# are generated by CoreSight with 'perf script' and 'perf report'
# commands.
# SPDX-License-Identifier: GPL-2.0
# Leo Yan <leo.yan@linaro.org>, 2020
perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
file=$(mktemp /tmp/temporary_file.XXXXX)
skip_if_no_cs_etm_event() {
perf list | grep -q 'cs_etm//' && return 0
# cs_etm event doesn't exist
return 2
}
skip_if_no_cs_etm_event || exit 2
cleanup_files()
{
rm -f ${perfdata}
rm -f ${file}
}
trap cleanup_files exit
record_touch_file() {
echo "Recording trace (only user mode) with path: CPU$2 => $1"
rm -f $file
perf record -o ${perfdata} -e cs_etm/@$1/u --per-thread \
-- taskset -c $2 touch $file
}
perf_script_branch_samples() {
echo "Looking at perf.data file for dumping branch samples:"
# Below is an example of the branch samples dumping:
# touch 6512 1 branches:u: ffffb220824c strcmp+0xc (/lib/aarch64-linux-gnu/ld-2.27.so)
# touch 6512 1 branches:u: ffffb22082e0 strcmp+0xa0 (/lib/aarch64-linux-gnu/ld-2.27.so)
# touch 6512 1 branches:u: ffffb2208320 strcmp+0xe0 (/lib/aarch64-linux-gnu/ld-2.27.so)
perf script -F,-time -i ${perfdata} | \
egrep " +$1 +[0-9]+ .* +branches:([u|k]:)? +"
}
perf_report_branch_samples() {
echo "Looking at perf.data file for reporting branch samples:"
# Below is an example of the branch samples reporting:
# 73.04% 73.04% touch libc-2.27.so [.] _dl_addr
# 7.71% 7.71% touch libc-2.27.so [.] getenv
# 2.59% 2.59% touch ld-2.27.so [.] strcmp
perf report --stdio -i ${perfdata} | \
egrep " +[0-9]+\.[0-9]+% +[0-9]+\.[0-9]+% +$1 "
}
perf_report_instruction_samples() {
echo "Looking at perf.data file for instruction samples:"
# Below is an example of the instruction samples reporting:
# 68.12% touch libc-2.27.so [.] _dl_addr
# 5.80% touch libc-2.27.so [.] getenv
# 4.35% touch ld-2.27.so [.] _dl_fixup
perf report --itrace=i1000i --stdio -i ${perfdata} | \
egrep " +[0-9]+\.[0-9]+% +$1"
}
is_device_sink() {
# If the node of "enable_sink" is existed under the device path, this
# means the device is a sink device. Need to exclude 'tpiu' since it
# cannot support perf PMU.
echo "$1" | egrep -q -v "tpiu"
if [ $? -eq 0 -a -e "$1/enable_sink" ]; then
pmu_dev="/sys/bus/event_source/devices/cs_etm/sinks/$2"
# Warn if the device is not supported by PMU
if ! [ -f $pmu_dev ]; then
echo "PMU doesn't support $pmu_dev"
fi
return 0
fi
# Otherwise, it's not a sink device
return 1
}
arm_cs_iterate_devices() {
for dev in $1/connections/out\:*; do
# Skip testing if it's not a directory
! [ -d $dev ] && continue;
# Read out its symbol link file name
path=`readlink -f $dev`
# Extract device name from path, e.g.
# path = '/sys/devices/platform/20010000.etf/tmc_etf0'
# `> device_name = 'tmc_etf0'
device_name=$(basename $path)
if is_device_sink $path $devce_name; then
record_touch_file $device_name $2 &&
perf_script_branch_samples touch &&
perf_report_branch_samples touch &&
perf_report_instruction_samples touch
err=$?
# Exit when find failure
[ $err != 0 ] && exit $err
fi
arm_cs_iterate_devices $dev $2
done
}
arm_cs_etm_traverse_path_test() {
# Iterate for every ETM device
for dev in /sys/bus/coresight/devices/etm*; do
# Find the ETM device belonging to which CPU
cpu=`cat $dev/cpu`
echo $dev
echo $cpu
# Use depth-first search (DFS) to iterate outputs
arm_cs_iterate_devices $dev $cpu
done
}
arm_cs_etm_system_wide_test() {
echo "Recording trace with system wide mode"
perf record -o ${perfdata} -e cs_etm// -a -- ls
perf_script_branch_samples perf &&
perf_report_branch_samples perf &&
perf_report_instruction_samples perf
err=$?
# Exit when find failure
[ $err != 0 ] && exit $err
}
arm_cs_etm_snapshot_test() {
echo "Recording trace with snapshot mode"
perf record -o ${perfdata} -e cs_etm// -S \
-- dd if=/dev/zero of=/dev/null &
PERFPID=$!
# Wait for perf program
sleep 1
# Send signal to snapshot trace data
kill -USR2 $PERFPID
# Stop perf program
kill $PERFPID
wait $PERFPID
perf_script_branch_samples dd &&
perf_report_branch_samples dd &&
perf_report_instruction_samples dd
err=$?
# Exit when find failure
[ $err != 0 ] && exit $err
}
arm_cs_etm_traverse_path_test
arm_cs_etm_system_wide_test
arm_cs_etm_snapshot_test
exit 0