11097b38fSAdrian Hunter#!/bin/sh 21097b38fSAdrian Hunter# Miscellaneous Intel PT testing 31097b38fSAdrian Hunter# SPDX-License-Identifier: GPL-2.0 41097b38fSAdrian Hunter 51097b38fSAdrian Hunterset -e 61097b38fSAdrian Hunter 71097b38fSAdrian Hunter# Skip if no Intel PT 81097b38fSAdrian Hunterperf list | grep -q 'intel_pt//' || exit 2 91097b38fSAdrian Hunter 105ebcdf07SAdrian Huntershelldir=$(dirname "$0") 115ebcdf07SAdrian Hunter. "${shelldir}"/lib/waiting.sh 125ebcdf07SAdrian Hunter 131097b38fSAdrian Hunterskip_cnt=0 141097b38fSAdrian Hunterok_cnt=0 151097b38fSAdrian Huntererr_cnt=0 161097b38fSAdrian Hunter 17170ac70fSAdrian Huntertemp_dir=$(mktemp -d /tmp/perf-test-intel-pt-sh.XXXXXXXXXX) 18170ac70fSAdrian Hunter 19170ac70fSAdrian Huntertmpfile="${temp_dir}/tmp-perf.data" 20170ac70fSAdrian Hunterperfdatafile="${temp_dir}/test-perf.data" 21fea753f8SAdrian Hunteroutfile="${temp_dir}/test-out.txt" 22fea753f8SAdrian Huntererrfile="${temp_dir}/test-err.txt" 23fea753f8SAdrian Hunterworkload="${temp_dir}/workload" 24fea753f8SAdrian Hunterawkscript="${temp_dir}/awkscript" 251097b38fSAdrian Hunter 2619af23dfSAdrian Huntercleanup() 2719af23dfSAdrian Hunter{ 2819af23dfSAdrian Hunter trap - EXIT TERM INT 29170ac70fSAdrian Hunter sane=$(echo "${temp_dir}" | cut -b 1-26) 30170ac70fSAdrian Hunter if [ "${sane}" = "/tmp/perf-test-intel-pt-sh" ] ; then 31170ac70fSAdrian Hunter echo "--- Cleaning up ---" 32170ac70fSAdrian Hunter rm -f "${temp_dir}/"* 33170ac70fSAdrian Hunter rmdir "${temp_dir}" 34170ac70fSAdrian Hunter fi 3519af23dfSAdrian Hunter} 3619af23dfSAdrian Hunter 3719af23dfSAdrian Huntertrap_cleanup() 3819af23dfSAdrian Hunter{ 3919af23dfSAdrian Hunter cleanup 4019af23dfSAdrian Hunter exit 1 4119af23dfSAdrian Hunter} 4219af23dfSAdrian Hunter 4319af23dfSAdrian Huntertrap trap_cleanup EXIT TERM INT 4419af23dfSAdrian Hunter 455021d82bSAdrian Hunter# perf record for testing without decoding 465021d82bSAdrian Hunterperf_record_no_decode() 475021d82bSAdrian Hunter{ 485021d82bSAdrian Hunter # Options to speed up recording: no post-processing, no build-id cache update, 495021d82bSAdrian Hunter # and no BPF events. 505021d82bSAdrian Hunter perf record -B -N --no-bpf-event "$@" 515021d82bSAdrian Hunter} 525021d82bSAdrian Hunter 53fea753f8SAdrian Hunterhave_workload=false 54fea753f8SAdrian Huntercat << _end_of_file_ | /usr/bin/cc -o "${workload}" -xc - -pthread && have_workload=true 55fea753f8SAdrian Hunter#include <time.h> 56fea753f8SAdrian Hunter#include <pthread.h> 57fea753f8SAdrian Hunter 58fea753f8SAdrian Huntervoid work(void) { 59fea753f8SAdrian Hunter struct timespec tm = { 60fea753f8SAdrian Hunter .tv_nsec = 1000000, 61fea753f8SAdrian Hunter }; 62fea753f8SAdrian Hunter int i; 63fea753f8SAdrian Hunter 64fea753f8SAdrian Hunter /* Run for about 30 seconds */ 65fea753f8SAdrian Hunter for (i = 0; i < 30000; i++) 66fea753f8SAdrian Hunter nanosleep(&tm, NULL); 67fea753f8SAdrian Hunter} 68fea753f8SAdrian Hunter 69fea753f8SAdrian Huntervoid *threadfunc(void *arg) { 70fea753f8SAdrian Hunter work(); 71fea753f8SAdrian Hunter return NULL; 72fea753f8SAdrian Hunter} 73fea753f8SAdrian Hunter 74fea753f8SAdrian Hunterint main(void) { 75fea753f8SAdrian Hunter pthread_t th; 76fea753f8SAdrian Hunter 77fea753f8SAdrian Hunter pthread_create(&th, NULL, threadfunc, NULL); 78fea753f8SAdrian Hunter work(); 79fea753f8SAdrian Hunter pthread_join(th, NULL); 80fea753f8SAdrian Hunter return 0; 81fea753f8SAdrian Hunter} 82fea753f8SAdrian Hunter_end_of_file_ 83fea753f8SAdrian Hunter 841097b38fSAdrian Huntercan_cpu_wide() 851097b38fSAdrian Hunter{ 862c1c9e35SAdrian Hunter echo "Checking for CPU-wide recording on CPU $1" 875021d82bSAdrian Hunter if ! perf_record_no_decode -o "${tmpfile}" -e dummy:u -C "$1" true >/dev/null 2>&1 ; then 882c1c9e35SAdrian Hunter echo "No so skipping" 892c1c9e35SAdrian Hunter return 2 902c1c9e35SAdrian Hunter fi 912c1c9e35SAdrian Hunter echo OK 921097b38fSAdrian Hunter return 0 931097b38fSAdrian Hunter} 941097b38fSAdrian Hunter 951097b38fSAdrian Huntertest_system_wide_side_band() 961097b38fSAdrian Hunter{ 972c1c9e35SAdrian Hunter echo "--- Test system-wide sideband ---" 982c1c9e35SAdrian Hunter 991097b38fSAdrian Hunter # Need CPU 0 and CPU 1 1001097b38fSAdrian Hunter can_cpu_wide 0 || return $? 1011097b38fSAdrian Hunter can_cpu_wide 1 || return $? 1021097b38fSAdrian Hunter 1031097b38fSAdrian Hunter # Record on CPU 0 a task running on CPU 1 1045021d82bSAdrian Hunter perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u -C 0 -- taskset --cpu-list 1 uname 1051097b38fSAdrian Hunter 1061097b38fSAdrian Hunter # Should get MMAP events from CPU 1 because they can be needed to decode 1075d7aac2bSAdrian Hunter mmap_cnt=$(perf script -i "${perfdatafile}" --no-itrace --show-mmap-events -C 1 2>/dev/null | grep -c MMAP) 1081097b38fSAdrian Hunter 1095d7aac2bSAdrian Hunter if [ "${mmap_cnt}" -gt 0 ] ; then 1102c1c9e35SAdrian Hunter echo OK 1111097b38fSAdrian Hunter return 0 1121097b38fSAdrian Hunter fi 1131097b38fSAdrian Hunter 1141097b38fSAdrian Hunter echo "Failed to record MMAP events on CPU 1 when tracing CPU 0" 1151097b38fSAdrian Hunter return 1 1161097b38fSAdrian Hunter} 1171097b38fSAdrian Hunter 118fea753f8SAdrian Huntercan_kernel() 119fea753f8SAdrian Hunter{ 120*9637bf8fSAdrian Hunter if [ -z "${can_kernel_trace}" ] ; then 121*9637bf8fSAdrian Hunter can_kernel_trace=0 122*9637bf8fSAdrian Hunter perf_record_no_decode -o "${tmpfile}" -e dummy:k true >/dev/null 2>&1 && can_kernel_trace=1 123*9637bf8fSAdrian Hunter fi 124*9637bf8fSAdrian Hunter if [ ${can_kernel_trace} -eq 0 ] ; then 125*9637bf8fSAdrian Hunter echo "SKIP: no kernel tracing" 126*9637bf8fSAdrian Hunter return 2 127*9637bf8fSAdrian Hunter fi 128fea753f8SAdrian Hunter return 0 129fea753f8SAdrian Hunter} 130fea753f8SAdrian Hunter 131fea753f8SAdrian Huntertest_per_thread() 132fea753f8SAdrian Hunter{ 133fea753f8SAdrian Hunter k="$1" 134fea753f8SAdrian Hunter desc="$2" 135fea753f8SAdrian Hunter 136fea753f8SAdrian Hunter echo "--- Test per-thread ${desc}recording ---" 137fea753f8SAdrian Hunter 138fea753f8SAdrian Hunter if ! $have_workload ; then 139fea753f8SAdrian Hunter echo "No workload, so skipping" 140fea753f8SAdrian Hunter return 2 141fea753f8SAdrian Hunter fi 142fea753f8SAdrian Hunter 143fea753f8SAdrian Hunter if [ "${k}" = "k" ] ; then 144fea753f8SAdrian Hunter can_kernel || return 2 145fea753f8SAdrian Hunter fi 146fea753f8SAdrian Hunter 147fea753f8SAdrian Hunter cat <<- "_end_of_file_" > "${awkscript}" 148fea753f8SAdrian Hunter BEGIN { 149fea753f8SAdrian Hunter s = "[ ]*" 150fea753f8SAdrian Hunter u = s"[0-9]+"s 151fea753f8SAdrian Hunter d = s"[0-9-]+"s 152fea753f8SAdrian Hunter x = s"[0-9a-fA-FxX]+"s 153fea753f8SAdrian Hunter mmapping = "idx"u": mmapping fd"u 154fea753f8SAdrian Hunter set_output = "idx"u": set output fd"u"->"u 155fea753f8SAdrian Hunter perf_event_open = "sys_perf_event_open: pid"d"cpu"d"group_fd"d"flags"x"="u 156fea753f8SAdrian Hunter } 157fea753f8SAdrian Hunter 158fea753f8SAdrian Hunter /perf record opening and mmapping events/ { 159fea753f8SAdrian Hunter if (!done) 160fea753f8SAdrian Hunter active = 1 161fea753f8SAdrian Hunter } 162fea753f8SAdrian Hunter 163fea753f8SAdrian Hunter /perf record done opening and mmapping events/ { 164fea753f8SAdrian Hunter active = 0 165fea753f8SAdrian Hunter done = 1 166fea753f8SAdrian Hunter } 167fea753f8SAdrian Hunter 168fea753f8SAdrian Hunter $0 ~ perf_event_open && active { 169fea753f8SAdrian Hunter match($0, perf_event_open) 170fea753f8SAdrian Hunter $0 = substr($0, RSTART, RLENGTH) 171fea753f8SAdrian Hunter pid = $3 172fea753f8SAdrian Hunter cpu = $5 173fea753f8SAdrian Hunter fd = $11 174fea753f8SAdrian Hunter print "pid " pid " cpu " cpu " fd " fd " : " $0 175fea753f8SAdrian Hunter fd_array[fd] = fd 176fea753f8SAdrian Hunter pid_array[fd] = pid 177fea753f8SAdrian Hunter cpu_array[fd] = cpu 178fea753f8SAdrian Hunter } 179fea753f8SAdrian Hunter 180fea753f8SAdrian Hunter $0 ~ mmapping && active { 181fea753f8SAdrian Hunter match($0, mmapping) 182fea753f8SAdrian Hunter $0 = substr($0, RSTART, RLENGTH) 183fea753f8SAdrian Hunter fd = $5 184fea753f8SAdrian Hunter print "fd " fd " : " $0 185fea753f8SAdrian Hunter if (fd in fd_array) { 186fea753f8SAdrian Hunter mmap_array[fd] = 1 187fea753f8SAdrian Hunter } else { 188fea753f8SAdrian Hunter print "Unknown fd " fd 189fea753f8SAdrian Hunter exit 1 190fea753f8SAdrian Hunter } 191fea753f8SAdrian Hunter } 192fea753f8SAdrian Hunter 193fea753f8SAdrian Hunter $0 ~ set_output && active { 194fea753f8SAdrian Hunter match($0, set_output) 195fea753f8SAdrian Hunter $0 = substr($0, RSTART, RLENGTH) 196fea753f8SAdrian Hunter fd = $6 197fea753f8SAdrian Hunter fd_to = $8 198fea753f8SAdrian Hunter print "fd " fd " fd_to " fd_to " : " $0 199fea753f8SAdrian Hunter if (fd in fd_array) { 200fea753f8SAdrian Hunter if (fd_to in fd_array) { 201fea753f8SAdrian Hunter set_output_array[fd] = fd_to 202fea753f8SAdrian Hunter } else { 203fea753f8SAdrian Hunter print "Unknown fd " fd_to 204fea753f8SAdrian Hunter exit 1 205fea753f8SAdrian Hunter } 206fea753f8SAdrian Hunter } else { 207fea753f8SAdrian Hunter print "Unknown fd " fd 208fea753f8SAdrian Hunter exit 1 209fea753f8SAdrian Hunter } 210fea753f8SAdrian Hunter } 211fea753f8SAdrian Hunter 212fea753f8SAdrian Hunter END { 213fea753f8SAdrian Hunter print "Checking " length(fd_array) " fds" 214fea753f8SAdrian Hunter for (fd in fd_array) { 215fea753f8SAdrian Hunter if (fd in mmap_array) { 216fea753f8SAdrian Hunter pid = pid_array[fd] 217fea753f8SAdrian Hunter if (pid != -1) { 218fea753f8SAdrian Hunter if (pid in pids) { 219fea753f8SAdrian Hunter print "More than 1 mmap for PID " pid 220fea753f8SAdrian Hunter exit 1 221fea753f8SAdrian Hunter } 222fea753f8SAdrian Hunter pids[pid] = 1 223fea753f8SAdrian Hunter } 224fea753f8SAdrian Hunter cpu = cpu_array[fd] 225fea753f8SAdrian Hunter if (cpu != -1) { 226fea753f8SAdrian Hunter if (cpu in cpus) { 227fea753f8SAdrian Hunter print "More than 1 mmap for CPU " cpu 228fea753f8SAdrian Hunter exit 1 229fea753f8SAdrian Hunter } 230fea753f8SAdrian Hunter cpus[cpu] = 1 231fea753f8SAdrian Hunter } 232fea753f8SAdrian Hunter } else if (!(fd in set_output_array)) { 233fea753f8SAdrian Hunter print "No mmap for fd " fd 234fea753f8SAdrian Hunter exit 1 235fea753f8SAdrian Hunter } 236fea753f8SAdrian Hunter } 237fea753f8SAdrian Hunter n = length(pids) 238fea753f8SAdrian Hunter if (n != thread_cnt) { 239fea753f8SAdrian Hunter print "Expected " thread_cnt " per-thread mmaps - found " n 240fea753f8SAdrian Hunter exit 1 241fea753f8SAdrian Hunter } 242fea753f8SAdrian Hunter } 243fea753f8SAdrian Hunter _end_of_file_ 244fea753f8SAdrian Hunter 245fea753f8SAdrian Hunter $workload & 246fea753f8SAdrian Hunter w1=$! 247fea753f8SAdrian Hunter $workload & 248fea753f8SAdrian Hunter w2=$! 249fea753f8SAdrian Hunter echo "Workload PIDs are $w1 and $w2" 250fea753f8SAdrian Hunter wait_for_threads ${w1} 2 251fea753f8SAdrian Hunter wait_for_threads ${w2} 2 252fea753f8SAdrian Hunter 2535021d82bSAdrian Hunter perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u"${k}" -vvv --per-thread -p "${w1},${w2}" 2>"${errfile}" >"${outfile}" & 254fea753f8SAdrian Hunter ppid=$! 255fea753f8SAdrian Hunter echo "perf PID is $ppid" 2565ebcdf07SAdrian Hunter wait_for_perf_to_start ${ppid} "${errfile}" || return 1 257fea753f8SAdrian Hunter 258fea753f8SAdrian Hunter kill ${w1} 259fea753f8SAdrian Hunter wait_for_process_to_exit ${w1} || return 1 260fea753f8SAdrian Hunter is_running ${ppid} || return 1 261fea753f8SAdrian Hunter 262fea753f8SAdrian Hunter kill ${w2} 263fea753f8SAdrian Hunter wait_for_process_to_exit ${w2} || return 1 264fea753f8SAdrian Hunter wait_for_process_to_exit ${ppid} || return 1 265fea753f8SAdrian Hunter 266fea753f8SAdrian Hunter awk -v thread_cnt=4 -f "${awkscript}" "${errfile}" || return 1 267fea753f8SAdrian Hunter 268fea753f8SAdrian Hunter echo OK 269fea753f8SAdrian Hunter return 0 270fea753f8SAdrian Hunter} 271fea753f8SAdrian Hunter 2721097b38fSAdrian Huntercount_result() 2731097b38fSAdrian Hunter{ 2745d7aac2bSAdrian Hunter if [ "$1" -eq 2 ] ; then 275202d0394SAdrian Hunter skip_cnt=$((skip_cnt + 1)) 2761097b38fSAdrian Hunter return 2771097b38fSAdrian Hunter fi 2785d7aac2bSAdrian Hunter if [ "$1" -eq 0 ] ; then 279202d0394SAdrian Hunter ok_cnt=$((ok_cnt + 1)) 2801097b38fSAdrian Hunter return 2811097b38fSAdrian Hunter fi 282202d0394SAdrian Hunter err_cnt=$((err_cnt + 1)) 2831097b38fSAdrian Hunter} 2841097b38fSAdrian Hunter 285fd9b45e3SAdrian Hunterret=0 286e4080492SAdrian Huntertest_system_wide_side_band || ret=$? ; count_result $ret ; ret=0 287e4080492SAdrian Huntertest_per_thread "" "" || ret=$? ; count_result $ret ; ret=0 288e4080492SAdrian Huntertest_per_thread "k" "(incl. kernel) " || ret=$? ; count_result $ret ; ret=0 2891097b38fSAdrian Hunter 29019af23dfSAdrian Huntercleanup 2911097b38fSAdrian Hunter 2922c1c9e35SAdrian Hunterecho "--- Done ---" 2932c1c9e35SAdrian Hunter 2941097b38fSAdrian Hunterif [ ${err_cnt} -gt 0 ] ; then 2951097b38fSAdrian Hunter exit 1 2961097b38fSAdrian Hunterfi 2971097b38fSAdrian Hunter 2981097b38fSAdrian Hunterif [ ${ok_cnt} -gt 0 ] ; then 2991097b38fSAdrian Hunter exit 0 3001097b38fSAdrian Hunterfi 3011097b38fSAdrian Hunter 3021097b38fSAdrian Hunterexit 2 303