perf test: Introduce script for data symbol testing
authorLeo Yan <leo.yan@linaro.org>
Thu, 6 Oct 2022 10:10:39 +0000 (18:10 +0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 6 Oct 2022 14:12:14 +0000 (11:12 -0300)
The test is designed with a data structure with 64-byte alignment, it
has two fields "data1" and "data2", and other fields are reserved.

Using the "perf mem" command, we can record and report memory samples
for a self-contained workload with 1 second duration.  If no samples are
obtained for the data structure "buf1", it reports failure;  and by
checking the offset in structure "buf1", if the memory samples aren't
for the "data1" and "data2" fields, it means wrong data symbol parsing
and returns failure.

Committer testing:

  [root@quaco ~]# grep -m1 "model name" /proc/cpuinfo
  model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz
  [root@quaco ~]#
  [root@quaco ~]# perf test -v "data symbol"
  104: Test data symbol                                                :
  --- start ---
  test child forked, pid 192318
  Compiling test program...
  Recording workload...
  [ perf record: Woken up 2 times to write data ]
  [ perf record: Captured and wrote 0.389 MB /tmp/__perf_test.perf.data.LIuQl (5570 samples) ]
  Cleaning up files...
  test child finished with 0
  ---- end ----
  Test data symbol: Ok
  [root@quaco ~]#

Signed-off-by: Leo Yan <leo.yan@linaro.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Link: https://lore.kernel.org/r/20221006101039.47870-1-leo.yan@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/tests/shell/test_data_symbol.sh [new file with mode: 0755]

diff --git a/tools/perf/tests/shell/test_data_symbol.sh b/tools/perf/tests/shell/test_data_symbol.sh
new file mode 100755 (executable)
index 0000000..cd6eb54
--- /dev/null
@@ -0,0 +1,93 @@
+#!/bin/bash
+# Test data symbol
+
+# SPDX-License-Identifier: GPL-2.0
+# Leo Yan <leo.yan@linaro.org>, 2022
+
+skip_if_no_mem_event() {
+       perf mem record -e list 2>&1 | egrep -q 'available' && return 0
+       return 2
+}
+
+skip_if_no_mem_event || exit 2
+
+# skip if there's no compiler
+if ! [ -x "$(command -v cc)" ]; then
+       echo "skip: no compiler, install gcc"
+       exit 2
+fi
+
+TEST_PROGRAM=$(mktemp /tmp/__perf_test.program.XXXXX)
+PERF_DATA=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
+
+check_result() {
+       # The memory report format is as below:
+       #    99.92%  ...  [.] buf1+0x38
+       result=$(perf mem report -i ${PERF_DATA} -s symbol_daddr -q 2>&1 |
+                awk '/buf1/ { print $4 }')
+
+       # Testing is failed if has no any sample for "buf1"
+       [ -z "$result" ] && return 1
+
+       while IFS= read -r line; do
+               # The "data1" and "data2" fields in structure "buf1" have
+               # offset "0x0" and "0x38", returns failure if detect any
+               # other offset value.
+               if [ "$line" != "buf1+0x0" ] && [ "$line" != "buf1+0x38" ]; then
+                       return 1
+               fi
+       done <<< "$result"
+
+       return 0
+}
+
+cleanup_files()
+{
+       echo "Cleaning up files..."
+       rm -f ${PERF_DATA}
+       rm -f ${TEST_PROGRAM}
+}
+
+trap cleanup_files exit term int
+
+# compile test program
+echo "Compiling test program..."
+cat << EOF | cc -o ${TEST_PROGRAM} -x c -
+typedef struct _buf {
+       char data1;
+       char reserved[55];
+       char data2;
+} buf __attribute__((aligned(64)));
+
+static buf buf1;
+
+int main(void) {
+       for (;;) {
+               buf1.data1++;
+               buf1.data2 += buf1.data1;
+       }
+       return 0;
+}
+EOF
+
+echo "Recording workload..."
+
+# perf mem/c2c internally uses IBS PMU on AMD CPU which doesn't support
+# user/kernel filtering and per-process monitoring, spin program on
+# specific CPU and test in per-CPU mode.
+is_amd=$(egrep -c 'vendor_id.*AuthenticAMD' /proc/cpuinfo)
+if (($is_amd >= 1)); then
+       perf mem record -o ${PERF_DATA} -C 0 -- taskset -c 0 $TEST_PROGRAM &
+else
+       perf mem record --all-user -o ${PERF_DATA} -- $TEST_PROGRAM &
+fi
+
+PERFPID=$!
+
+sleep 1
+
+kill $PERFPID
+wait $PERFPID
+
+check_result
+exit $?