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