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