1fe0aed19SLeo Yan#!/bin/sh
2fe0aed19SLeo Yan# Check Arm CoreSight trace data recording and synthesized samples
3fe0aed19SLeo Yan
4fe0aed19SLeo Yan# Uses the 'perf record' to record trace data with Arm CoreSight sinks;
5fe0aed19SLeo Yan# then verify if there have any branch samples and instruction samples
6fe0aed19SLeo Yan# are generated by CoreSight with 'perf script' and 'perf report'
7fe0aed19SLeo Yan# commands.
8fe0aed19SLeo Yan
9fe0aed19SLeo Yan# SPDX-License-Identifier: GPL-2.0
10fe0aed19SLeo Yan# Leo Yan <leo.yan@linaro.org>, 2020
11fe0aed19SLeo Yan
1211d45d4fSLeo Yanglb_err=0
13fe0aed19SLeo Yan
14fe0aed19SLeo Yanskip_if_no_cs_etm_event() {
15fe0aed19SLeo Yan	perf list | grep -q 'cs_etm//' && return 0
16fe0aed19SLeo Yan
17fe0aed19SLeo Yan	# cs_etm event doesn't exist
18fe0aed19SLeo Yan	return 2
19fe0aed19SLeo Yan}
20fe0aed19SLeo Yan
21fe0aed19SLeo Yanskip_if_no_cs_etm_event || exit 2
22fe0aed19SLeo Yan
23133fe2e6SJames Clarkperfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
24133fe2e6SJames Clarkfile=$(mktemp /tmp/temporary_file.XXXXX)
25133fe2e6SJames Clark
26fe0aed19SLeo Yancleanup_files()
27fe0aed19SLeo Yan{
28fe0aed19SLeo Yan	rm -f ${perfdata}
29fe0aed19SLeo Yan	rm -f ${file}
30133fe2e6SJames Clark	rm -f "${perfdata}.old"
310ed4b531SAnushree Mathur	trap - EXIT TERM INT
32133fe2e6SJames Clark	exit $glb_err
33fe0aed19SLeo Yan}
34fe0aed19SLeo Yan
350ed4b531SAnushree Mathurtrap cleanup_files EXIT TERM INT
36fe0aed19SLeo Yan
37fe0aed19SLeo Yanrecord_touch_file() {
38fe0aed19SLeo Yan	echo "Recording trace (only user mode) with path: CPU$2 => $1"
39fe0aed19SLeo Yan	rm -f $file
40fe0aed19SLeo Yan	perf record -o ${perfdata} -e cs_etm/@$1/u --per-thread \
4146355e3dSLeo Yan		-- taskset -c $2 touch $file > /dev/null 2>&1
42fe0aed19SLeo Yan}
43fe0aed19SLeo Yan
44fe0aed19SLeo Yanperf_script_branch_samples() {
45fe0aed19SLeo Yan	echo "Looking at perf.data file for dumping branch samples:"
46fe0aed19SLeo Yan
47fe0aed19SLeo Yan	# Below is an example of the branch samples dumping:
48fe0aed19SLeo Yan	#   touch  6512          1         branches:u:      ffffb220824c strcmp+0xc (/lib/aarch64-linux-gnu/ld-2.27.so)
49fe0aed19SLeo Yan	#   touch  6512          1         branches:u:      ffffb22082e0 strcmp+0xa0 (/lib/aarch64-linux-gnu/ld-2.27.so)
50fe0aed19SLeo Yan	#   touch  6512          1         branches:u:      ffffb2208320 strcmp+0xe0 (/lib/aarch64-linux-gnu/ld-2.27.so)
5146355e3dSLeo Yan	perf script -F,-time -i ${perfdata} 2>&1 | \
52818448e9STiezhu Yang		grep -E " +$1 +[0-9]+ .* +branches:(.*:)? +" > /dev/null 2>&1
53fe0aed19SLeo Yan}
54fe0aed19SLeo Yan
55fe0aed19SLeo Yanperf_report_branch_samples() {
56fe0aed19SLeo Yan	echo "Looking at perf.data file for reporting branch samples:"
57fe0aed19SLeo Yan
58fe0aed19SLeo Yan	# Below is an example of the branch samples reporting:
59fe0aed19SLeo Yan	#   73.04%    73.04%  touch    libc-2.27.so      [.] _dl_addr
60fe0aed19SLeo Yan	#    7.71%     7.71%  touch    libc-2.27.so      [.] getenv
61fe0aed19SLeo Yan	#    2.59%     2.59%  touch    ld-2.27.so        [.] strcmp
6246355e3dSLeo Yan	perf report --stdio -i ${perfdata} 2>&1 | \
63818448e9STiezhu Yang		grep -E " +[0-9]+\.[0-9]+% +[0-9]+\.[0-9]+% +$1 " > /dev/null 2>&1
64fe0aed19SLeo Yan}
65fe0aed19SLeo Yan
66fe0aed19SLeo Yanperf_report_instruction_samples() {
67fe0aed19SLeo Yan	echo "Looking at perf.data file for instruction samples:"
68fe0aed19SLeo Yan
69fe0aed19SLeo Yan	# Below is an example of the instruction samples reporting:
70fe0aed19SLeo Yan	#   68.12%  touch    libc-2.27.so   [.] _dl_addr
71fe0aed19SLeo Yan	#    5.80%  touch    libc-2.27.so   [.] getenv
72fe0aed19SLeo Yan	#    4.35%  touch    ld-2.27.so     [.] _dl_fixup
73fe180a52SJames Clark	perf report --itrace=i20i --stdio -i ${perfdata} 2>&1 | \
74818448e9STiezhu Yang		grep -E " +[0-9]+\.[0-9]+% +$1" > /dev/null 2>&1
75fe0aed19SLeo Yan}
76fe0aed19SLeo Yan
7711d45d4fSLeo Yanarm_cs_report() {
7811d45d4fSLeo Yan	if [ $2 != 0 ]; then
7911d45d4fSLeo Yan		echo "$1: FAIL"
8011d45d4fSLeo Yan		glb_err=$2
8111d45d4fSLeo Yan	else
8211d45d4fSLeo Yan		echo "$1: PASS"
8311d45d4fSLeo Yan	fi
8411d45d4fSLeo Yan}
8511d45d4fSLeo Yan
86fe0aed19SLeo Yanis_device_sink() {
87fe0aed19SLeo Yan	# If the node of "enable_sink" is existed under the device path, this
88fe0aed19SLeo Yan	# means the device is a sink device.  Need to exclude 'tpiu' since it
89fe0aed19SLeo Yan	# cannot support perf PMU.
90818448e9STiezhu Yang	echo "$1" | grep -E -q -v "tpiu"
91fe0aed19SLeo Yan
920ed4b531SAnushree Mathur	if [ $? -eq 0 ] && [ -e "$1/enable_sink" ]; then
93fe0aed19SLeo Yan
94fe0aed19SLeo Yan		pmu_dev="/sys/bus/event_source/devices/cs_etm/sinks/$2"
95fe0aed19SLeo Yan
96fe0aed19SLeo Yan		# Warn if the device is not supported by PMU
97fe0aed19SLeo Yan		if ! [ -f $pmu_dev ]; then
98fe0aed19SLeo Yan			echo "PMU doesn't support $pmu_dev"
99fe0aed19SLeo Yan		fi
100fe0aed19SLeo Yan
101fe0aed19SLeo Yan		return 0
102fe0aed19SLeo Yan	fi
103fe0aed19SLeo Yan
104fe0aed19SLeo Yan	# Otherwise, it's not a sink device
105fe0aed19SLeo Yan	return 1
106fe0aed19SLeo Yan}
107fe0aed19SLeo Yan
108fe0aed19SLeo Yanarm_cs_iterate_devices() {
109fe0aed19SLeo Yan	for dev in $1/connections/out\:*; do
110fe0aed19SLeo Yan
111fe0aed19SLeo Yan		# Skip testing if it's not a directory
112fe0aed19SLeo Yan		! [ -d $dev ] && continue;
113fe0aed19SLeo Yan
114fe0aed19SLeo Yan		# Read out its symbol link file name
115fe0aed19SLeo Yan		path=`readlink -f $dev`
116fe0aed19SLeo Yan
117fe0aed19SLeo Yan		# Extract device name from path, e.g.
118fe0aed19SLeo Yan		#   path = '/sys/devices/platform/20010000.etf/tmc_etf0'
119fe0aed19SLeo Yan		#     `> device_name = 'tmc_etf0'
120fe0aed19SLeo Yan		device_name=$(basename $path)
121fe0aed19SLeo Yan
122db2ac2e4SLeo Yan		if is_device_sink $path $device_name; then
123fe0aed19SLeo Yan
124fe0aed19SLeo Yan			record_touch_file $device_name $2 &&
125fe0aed19SLeo Yan			perf_script_branch_samples touch &&
126fe0aed19SLeo Yan			perf_report_branch_samples touch &&
127fe0aed19SLeo Yan			perf_report_instruction_samples touch
128fe0aed19SLeo Yan
129fe0aed19SLeo Yan			err=$?
13011d45d4fSLeo Yan			arm_cs_report "CoreSight path testing (CPU$2 -> $device_name)" $err
131fe0aed19SLeo Yan		fi
132fe0aed19SLeo Yan
133fe0aed19SLeo Yan		arm_cs_iterate_devices $dev $2
134fe0aed19SLeo Yan	done
135fe0aed19SLeo Yan}
136fe0aed19SLeo Yan
137fe0aed19SLeo Yanarm_cs_etm_traverse_path_test() {
138fe0aed19SLeo Yan	# Iterate for every ETM device
139fe0aed19SLeo Yan	for dev in /sys/bus/coresight/devices/etm*; do
140fe0aed19SLeo Yan
141fe0aed19SLeo Yan		# Find the ETM device belonging to which CPU
142fe0aed19SLeo Yan		cpu=`cat $dev/cpu`
143fe0aed19SLeo Yan
144fe0aed19SLeo Yan		# Use depth-first search (DFS) to iterate outputs
145fe0aed19SLeo Yan		arm_cs_iterate_devices $dev $cpu
146fe0aed19SLeo Yan	done
147fe0aed19SLeo Yan}
148fe0aed19SLeo Yan
149fe0aed19SLeo Yanarm_cs_etm_system_wide_test() {
150fe0aed19SLeo Yan	echo "Recording trace with system wide mode"
15146355e3dSLeo Yan	perf record -o ${perfdata} -e cs_etm// -a -- ls > /dev/null 2>&1
152fe0aed19SLeo Yan
153d1efa4a0SJames Clark	# System-wide mode should include perf samples so test for that
154d1efa4a0SJames Clark	# instead of ls
155fe0aed19SLeo Yan	perf_script_branch_samples perf &&
156fe0aed19SLeo Yan	perf_report_branch_samples perf &&
157fe0aed19SLeo Yan	perf_report_instruction_samples perf
158fe0aed19SLeo Yan
159fe0aed19SLeo Yan	err=$?
16011d45d4fSLeo Yan	arm_cs_report "CoreSight system wide testing" $err
161fe0aed19SLeo Yan}
162fe0aed19SLeo Yan
163fe0aed19SLeo Yanarm_cs_etm_snapshot_test() {
164fe0aed19SLeo Yan	echo "Recording trace with snapshot mode"
165fe0aed19SLeo Yan	perf record -o ${perfdata} -e cs_etm// -S \
16646355e3dSLeo Yan		-- dd if=/dev/zero of=/dev/null > /dev/null 2>&1 &
167fe0aed19SLeo Yan	PERFPID=$!
168fe0aed19SLeo Yan
169fe0aed19SLeo Yan	# Wait for perf program
170fe0aed19SLeo Yan	sleep 1
171fe0aed19SLeo Yan
172fe0aed19SLeo Yan	# Send signal to snapshot trace data
173fe0aed19SLeo Yan	kill -USR2 $PERFPID
174fe0aed19SLeo Yan
175fe0aed19SLeo Yan	# Stop perf program
176fe0aed19SLeo Yan	kill $PERFPID
177fe0aed19SLeo Yan	wait $PERFPID
178fe0aed19SLeo Yan
179fe0aed19SLeo Yan	perf_script_branch_samples dd &&
180fe0aed19SLeo Yan	perf_report_branch_samples dd &&
181fe0aed19SLeo Yan	perf_report_instruction_samples dd
182fe0aed19SLeo Yan
183fe0aed19SLeo Yan	err=$?
18411d45d4fSLeo Yan	arm_cs_report "CoreSight snapshot testing" $err
185fe0aed19SLeo Yan}
186fe0aed19SLeo Yan
187d1efa4a0SJames Clarkarm_cs_etm_basic_test() {
188d1efa4a0SJames Clark	echo "Recording trace with '$*'"
189d3ced099SJames Clark	perf record -o ${perfdata} "$@" -m,8M -- ls > /dev/null 2>&1
190d1efa4a0SJames Clark
191d1efa4a0SJames Clark	perf_script_branch_samples ls &&
192d1efa4a0SJames Clark	perf_report_branch_samples ls &&
193d1efa4a0SJames Clark	perf_report_instruction_samples ls
194d1efa4a0SJames Clark
195d1efa4a0SJames Clark	err=$?
196d1efa4a0SJames Clark	arm_cs_report "CoreSight basic testing with '$*'" $err
197d1efa4a0SJames Clark}
198d1efa4a0SJames Clark
199fe0aed19SLeo Yanarm_cs_etm_traverse_path_test
200fe0aed19SLeo Yanarm_cs_etm_system_wide_test
201fe0aed19SLeo Yanarm_cs_etm_snapshot_test
202d1efa4a0SJames Clark
203d1efa4a0SJames Clark# Test all combinations of per-thread, system-wide and normal mode with
204d1efa4a0SJames Clark# and without timestamps
205d1efa4a0SJames Clarkarm_cs_etm_basic_test -e cs_etm/timestamp=0/ --per-thread
206d1efa4a0SJames Clarkarm_cs_etm_basic_test -e cs_etm/timestamp=1/ --per-thread
207d1efa4a0SJames Clarkarm_cs_etm_basic_test -e cs_etm/timestamp=0/ -a
208d1efa4a0SJames Clarkarm_cs_etm_basic_test -e cs_etm/timestamp=1/ -a
209d1efa4a0SJames Clarkarm_cs_etm_basic_test -e cs_etm/timestamp=0/
210d1efa4a0SJames Clarkarm_cs_etm_basic_test -e cs_etm/timestamp=1/
211d1efa4a0SJames Clark
21211d45d4fSLeo Yanexit $glb_err
213