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" 25973db240SAdrian Hunterjitdump_workload="${temp_dir}/jitdump_workload" 26f77811a0SAmmy Yimaxbrstack="${temp_dir}/maxbrstack.py" 271097b38fSAdrian Hunter 2819af23dfSAdrian Huntercleanup() 2919af23dfSAdrian Hunter{ 3019af23dfSAdrian Hunter trap - EXIT TERM INT 31170ac70fSAdrian Hunter sane=$(echo "${temp_dir}" | cut -b 1-26) 32170ac70fSAdrian Hunter if [ "${sane}" = "/tmp/perf-test-intel-pt-sh" ] ; then 33170ac70fSAdrian Hunter echo "--- Cleaning up ---" 34170ac70fSAdrian Hunter rm -f "${temp_dir}/"* 35170ac70fSAdrian Hunter rmdir "${temp_dir}" 36170ac70fSAdrian Hunter fi 3719af23dfSAdrian Hunter} 3819af23dfSAdrian Hunter 3919af23dfSAdrian Huntertrap_cleanup() 4019af23dfSAdrian Hunter{ 4119af23dfSAdrian Hunter cleanup 4219af23dfSAdrian Hunter exit 1 4319af23dfSAdrian Hunter} 4419af23dfSAdrian Hunter 4519af23dfSAdrian Huntertrap trap_cleanup EXIT TERM INT 4619af23dfSAdrian Hunter 475021d82bSAdrian Hunter# perf record for testing without decoding 485021d82bSAdrian Hunterperf_record_no_decode() 495021d82bSAdrian Hunter{ 505021d82bSAdrian Hunter # Options to speed up recording: no post-processing, no build-id cache update, 515021d82bSAdrian Hunter # and no BPF events. 525021d82bSAdrian Hunter perf record -B -N --no-bpf-event "$@" 535021d82bSAdrian Hunter} 545021d82bSAdrian Hunter 55973db240SAdrian Hunter# perf record for testing should not need BPF events 56973db240SAdrian Hunterperf_record_no_bpf() 57973db240SAdrian Hunter{ 58973db240SAdrian Hunter # Options for no BPF events 59973db240SAdrian Hunter perf record --no-bpf-event "$@" 60973db240SAdrian Hunter} 61973db240SAdrian Hunter 62fea753f8SAdrian Hunterhave_workload=false 63fea753f8SAdrian Huntercat << _end_of_file_ | /usr/bin/cc -o "${workload}" -xc - -pthread && have_workload=true 64fea753f8SAdrian Hunter#include <time.h> 65fea753f8SAdrian Hunter#include <pthread.h> 66fea753f8SAdrian Hunter 67fea753f8SAdrian Huntervoid work(void) { 68fea753f8SAdrian Hunter struct timespec tm = { 69fea753f8SAdrian Hunter .tv_nsec = 1000000, 70fea753f8SAdrian Hunter }; 71fea753f8SAdrian Hunter int i; 72fea753f8SAdrian Hunter 73fea753f8SAdrian Hunter /* Run for about 30 seconds */ 74fea753f8SAdrian Hunter for (i = 0; i < 30000; i++) 75fea753f8SAdrian Hunter nanosleep(&tm, NULL); 76fea753f8SAdrian Hunter} 77fea753f8SAdrian Hunter 78fea753f8SAdrian Huntervoid *threadfunc(void *arg) { 79fea753f8SAdrian Hunter work(); 80fea753f8SAdrian Hunter return NULL; 81fea753f8SAdrian Hunter} 82fea753f8SAdrian Hunter 83fea753f8SAdrian Hunterint main(void) { 84fea753f8SAdrian Hunter pthread_t th; 85fea753f8SAdrian Hunter 86fea753f8SAdrian Hunter pthread_create(&th, NULL, threadfunc, NULL); 87fea753f8SAdrian Hunter work(); 88fea753f8SAdrian Hunter pthread_join(th, NULL); 89fea753f8SAdrian Hunter return 0; 90fea753f8SAdrian Hunter} 91fea753f8SAdrian Hunter_end_of_file_ 92fea753f8SAdrian Hunter 931097b38fSAdrian Huntercan_cpu_wide() 941097b38fSAdrian Hunter{ 952c1c9e35SAdrian Hunter echo "Checking for CPU-wide recording on CPU $1" 965021d82bSAdrian Hunter if ! perf_record_no_decode -o "${tmpfile}" -e dummy:u -C "$1" true >/dev/null 2>&1 ; then 972c1c9e35SAdrian Hunter echo "No so skipping" 982c1c9e35SAdrian Hunter return 2 992c1c9e35SAdrian Hunter fi 1002c1c9e35SAdrian Hunter echo OK 1011097b38fSAdrian Hunter return 0 1021097b38fSAdrian Hunter} 1031097b38fSAdrian Hunter 1041097b38fSAdrian Huntertest_system_wide_side_band() 1051097b38fSAdrian Hunter{ 1062c1c9e35SAdrian Hunter echo "--- Test system-wide sideband ---" 1072c1c9e35SAdrian Hunter 1081097b38fSAdrian Hunter # Need CPU 0 and CPU 1 1091097b38fSAdrian Hunter can_cpu_wide 0 || return $? 1101097b38fSAdrian Hunter can_cpu_wide 1 || return $? 1111097b38fSAdrian Hunter 1121097b38fSAdrian Hunter # Record on CPU 0 a task running on CPU 1 1135021d82bSAdrian Hunter perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u -C 0 -- taskset --cpu-list 1 uname 1141097b38fSAdrian Hunter 1151097b38fSAdrian Hunter # Should get MMAP events from CPU 1 because they can be needed to decode 1165d7aac2bSAdrian Hunter mmap_cnt=$(perf script -i "${perfdatafile}" --no-itrace --show-mmap-events -C 1 2>/dev/null | grep -c MMAP) 1171097b38fSAdrian Hunter 1185d7aac2bSAdrian Hunter if [ "${mmap_cnt}" -gt 0 ] ; then 1192c1c9e35SAdrian Hunter echo OK 1201097b38fSAdrian Hunter return 0 1211097b38fSAdrian Hunter fi 1221097b38fSAdrian Hunter 1231097b38fSAdrian Hunter echo "Failed to record MMAP events on CPU 1 when tracing CPU 0" 1241097b38fSAdrian Hunter return 1 1251097b38fSAdrian Hunter} 1261097b38fSAdrian Hunter 127fea753f8SAdrian Huntercan_kernel() 128fea753f8SAdrian Hunter{ 1299637bf8fSAdrian Hunter if [ -z "${can_kernel_trace}" ] ; then 1309637bf8fSAdrian Hunter can_kernel_trace=0 1319637bf8fSAdrian Hunter perf_record_no_decode -o "${tmpfile}" -e dummy:k true >/dev/null 2>&1 && can_kernel_trace=1 1329637bf8fSAdrian Hunter fi 1339637bf8fSAdrian Hunter if [ ${can_kernel_trace} -eq 0 ] ; then 1349637bf8fSAdrian Hunter echo "SKIP: no kernel tracing" 1359637bf8fSAdrian Hunter return 2 1369637bf8fSAdrian Hunter fi 137fea753f8SAdrian Hunter return 0 138fea753f8SAdrian Hunter} 139fea753f8SAdrian Hunter 140fea753f8SAdrian Huntertest_per_thread() 141fea753f8SAdrian Hunter{ 142fea753f8SAdrian Hunter k="$1" 143fea753f8SAdrian Hunter desc="$2" 144fea753f8SAdrian Hunter 145fea753f8SAdrian Hunter echo "--- Test per-thread ${desc}recording ---" 146fea753f8SAdrian Hunter 147fea753f8SAdrian Hunter if ! $have_workload ; then 148fea753f8SAdrian Hunter echo "No workload, so skipping" 149fea753f8SAdrian Hunter return 2 150fea753f8SAdrian Hunter fi 151fea753f8SAdrian Hunter 152fea753f8SAdrian Hunter if [ "${k}" = "k" ] ; then 153fea753f8SAdrian Hunter can_kernel || return 2 154fea753f8SAdrian Hunter fi 155fea753f8SAdrian Hunter 156fea753f8SAdrian Hunter cat <<- "_end_of_file_" > "${awkscript}" 157fea753f8SAdrian Hunter BEGIN { 158fea753f8SAdrian Hunter s = "[ ]*" 159fea753f8SAdrian Hunter u = s"[0-9]+"s 160fea753f8SAdrian Hunter d = s"[0-9-]+"s 161fea753f8SAdrian Hunter x = s"[0-9a-fA-FxX]+"s 162fea753f8SAdrian Hunter mmapping = "idx"u": mmapping fd"u 163fea753f8SAdrian Hunter set_output = "idx"u": set output fd"u"->"u 164fea753f8SAdrian Hunter perf_event_open = "sys_perf_event_open: pid"d"cpu"d"group_fd"d"flags"x"="u 165fea753f8SAdrian Hunter } 166fea753f8SAdrian Hunter 167fea753f8SAdrian Hunter /perf record opening and mmapping events/ { 168fea753f8SAdrian Hunter if (!done) 169fea753f8SAdrian Hunter active = 1 170fea753f8SAdrian Hunter } 171fea753f8SAdrian Hunter 172fea753f8SAdrian Hunter /perf record done opening and mmapping events/ { 173fea753f8SAdrian Hunter active = 0 174fea753f8SAdrian Hunter done = 1 175fea753f8SAdrian Hunter } 176fea753f8SAdrian Hunter 177fea753f8SAdrian Hunter $0 ~ perf_event_open && active { 178fea753f8SAdrian Hunter match($0, perf_event_open) 179fea753f8SAdrian Hunter $0 = substr($0, RSTART, RLENGTH) 180fea753f8SAdrian Hunter pid = $3 181fea753f8SAdrian Hunter cpu = $5 182fea753f8SAdrian Hunter fd = $11 183fea753f8SAdrian Hunter print "pid " pid " cpu " cpu " fd " fd " : " $0 184fea753f8SAdrian Hunter fd_array[fd] = fd 185fea753f8SAdrian Hunter pid_array[fd] = pid 186fea753f8SAdrian Hunter cpu_array[fd] = cpu 187fea753f8SAdrian Hunter } 188fea753f8SAdrian Hunter 189fea753f8SAdrian Hunter $0 ~ mmapping && active { 190fea753f8SAdrian Hunter match($0, mmapping) 191fea753f8SAdrian Hunter $0 = substr($0, RSTART, RLENGTH) 192fea753f8SAdrian Hunter fd = $5 193fea753f8SAdrian Hunter print "fd " fd " : " $0 194fea753f8SAdrian Hunter if (fd in fd_array) { 195fea753f8SAdrian Hunter mmap_array[fd] = 1 196fea753f8SAdrian Hunter } else { 197fea753f8SAdrian Hunter print "Unknown fd " fd 198fea753f8SAdrian Hunter exit 1 199fea753f8SAdrian Hunter } 200fea753f8SAdrian Hunter } 201fea753f8SAdrian Hunter 202fea753f8SAdrian Hunter $0 ~ set_output && active { 203fea753f8SAdrian Hunter match($0, set_output) 204fea753f8SAdrian Hunter $0 = substr($0, RSTART, RLENGTH) 205fea753f8SAdrian Hunter fd = $6 206fea753f8SAdrian Hunter fd_to = $8 207fea753f8SAdrian Hunter print "fd " fd " fd_to " fd_to " : " $0 208fea753f8SAdrian Hunter if (fd in fd_array) { 209fea753f8SAdrian Hunter if (fd_to in fd_array) { 210fea753f8SAdrian Hunter set_output_array[fd] = fd_to 211fea753f8SAdrian Hunter } else { 212fea753f8SAdrian Hunter print "Unknown fd " fd_to 213fea753f8SAdrian Hunter exit 1 214fea753f8SAdrian Hunter } 215fea753f8SAdrian Hunter } else { 216fea753f8SAdrian Hunter print "Unknown fd " fd 217fea753f8SAdrian Hunter exit 1 218fea753f8SAdrian Hunter } 219fea753f8SAdrian Hunter } 220fea753f8SAdrian Hunter 221fea753f8SAdrian Hunter END { 222fea753f8SAdrian Hunter print "Checking " length(fd_array) " fds" 223fea753f8SAdrian Hunter for (fd in fd_array) { 224fea753f8SAdrian Hunter if (fd in mmap_array) { 225fea753f8SAdrian Hunter pid = pid_array[fd] 226fea753f8SAdrian Hunter if (pid != -1) { 227fea753f8SAdrian Hunter if (pid in pids) { 228fea753f8SAdrian Hunter print "More than 1 mmap for PID " pid 229fea753f8SAdrian Hunter exit 1 230fea753f8SAdrian Hunter } 231fea753f8SAdrian Hunter pids[pid] = 1 232fea753f8SAdrian Hunter } 233fea753f8SAdrian Hunter cpu = cpu_array[fd] 234fea753f8SAdrian Hunter if (cpu != -1) { 235fea753f8SAdrian Hunter if (cpu in cpus) { 236fea753f8SAdrian Hunter print "More than 1 mmap for CPU " cpu 237fea753f8SAdrian Hunter exit 1 238fea753f8SAdrian Hunter } 239fea753f8SAdrian Hunter cpus[cpu] = 1 240fea753f8SAdrian Hunter } 241fea753f8SAdrian Hunter } else if (!(fd in set_output_array)) { 242fea753f8SAdrian Hunter print "No mmap for fd " fd 243fea753f8SAdrian Hunter exit 1 244fea753f8SAdrian Hunter } 245fea753f8SAdrian Hunter } 246fea753f8SAdrian Hunter n = length(pids) 247fea753f8SAdrian Hunter if (n != thread_cnt) { 248fea753f8SAdrian Hunter print "Expected " thread_cnt " per-thread mmaps - found " n 249fea753f8SAdrian Hunter exit 1 250fea753f8SAdrian Hunter } 251fea753f8SAdrian Hunter } 252fea753f8SAdrian Hunter _end_of_file_ 253fea753f8SAdrian Hunter 254fea753f8SAdrian Hunter $workload & 255fea753f8SAdrian Hunter w1=$! 256fea753f8SAdrian Hunter $workload & 257fea753f8SAdrian Hunter w2=$! 258fea753f8SAdrian Hunter echo "Workload PIDs are $w1 and $w2" 259fea753f8SAdrian Hunter wait_for_threads ${w1} 2 260fea753f8SAdrian Hunter wait_for_threads ${w2} 2 261fea753f8SAdrian Hunter 2625021d82bSAdrian Hunter perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u"${k}" -vvv --per-thread -p "${w1},${w2}" 2>"${errfile}" >"${outfile}" & 263fea753f8SAdrian Hunter ppid=$! 264fea753f8SAdrian Hunter echo "perf PID is $ppid" 2655ebcdf07SAdrian Hunter wait_for_perf_to_start ${ppid} "${errfile}" || return 1 266fea753f8SAdrian Hunter 267fea753f8SAdrian Hunter kill ${w1} 268fea753f8SAdrian Hunter wait_for_process_to_exit ${w1} || return 1 269fea753f8SAdrian Hunter is_running ${ppid} || return 1 270fea753f8SAdrian Hunter 271fea753f8SAdrian Hunter kill ${w2} 272fea753f8SAdrian Hunter wait_for_process_to_exit ${w2} || return 1 273fea753f8SAdrian Hunter wait_for_process_to_exit ${ppid} || return 1 274fea753f8SAdrian Hunter 275fea753f8SAdrian Hunter awk -v thread_cnt=4 -f "${awkscript}" "${errfile}" || return 1 276fea753f8SAdrian Hunter 277fea753f8SAdrian Hunter echo OK 278fea753f8SAdrian Hunter return 0 279fea753f8SAdrian Hunter} 280fea753f8SAdrian Hunter 281973db240SAdrian Huntertest_jitdump() 282973db240SAdrian Hunter{ 283973db240SAdrian Hunter echo "--- Test tracing self-modifying code that uses jitdump ---" 284973db240SAdrian Hunter 285973db240SAdrian Hunter script_path=$(realpath "$0") 286973db240SAdrian Hunter script_dir=$(dirname "$script_path") 287973db240SAdrian Hunter jitdump_incl_dir="${script_dir}/../../util" 288973db240SAdrian Hunter jitdump_h="${jitdump_incl_dir}/jitdump.h" 289973db240SAdrian Hunter 290973db240SAdrian Hunter if [ ! -e "${jitdump_h}" ] ; then 291973db240SAdrian Hunter echo "SKIP: Include file jitdump.h not found" 292973db240SAdrian Hunter return 2 293973db240SAdrian Hunter fi 294973db240SAdrian Hunter 295973db240SAdrian Hunter if [ -z "${have_jitdump_workload}" ] ; then 296973db240SAdrian Hunter have_jitdump_workload=false 297973db240SAdrian Hunter # Create a workload that uses self-modifying code and generates its own jitdump file 298973db240SAdrian Hunter cat <<- "_end_of_file_" | /usr/bin/cc -o "${jitdump_workload}" -I "${jitdump_incl_dir}" -xc - -pthread && have_jitdump_workload=true 299973db240SAdrian Hunter #define _GNU_SOURCE 300973db240SAdrian Hunter #include <sys/mman.h> 301973db240SAdrian Hunter #include <sys/types.h> 302973db240SAdrian Hunter #include <stddef.h> 303973db240SAdrian Hunter #include <stdio.h> 304973db240SAdrian Hunter #include <stdint.h> 305973db240SAdrian Hunter #include <unistd.h> 306973db240SAdrian Hunter #include <string.h> 307973db240SAdrian Hunter 308973db240SAdrian Hunter #include "jitdump.h" 309973db240SAdrian Hunter 310973db240SAdrian Hunter #define CHK_BYTE 0x5a 311973db240SAdrian Hunter 312973db240SAdrian Hunter static inline uint64_t rdtsc(void) 313973db240SAdrian Hunter { 314973db240SAdrian Hunter unsigned int low, high; 315973db240SAdrian Hunter 316973db240SAdrian Hunter asm volatile("rdtsc" : "=a" (low), "=d" (high)); 317973db240SAdrian Hunter 318973db240SAdrian Hunter return low | ((uint64_t)high) << 32; 319973db240SAdrian Hunter } 320973db240SAdrian Hunter 321973db240SAdrian Hunter static FILE *open_jitdump(void) 322973db240SAdrian Hunter { 323973db240SAdrian Hunter struct jitheader header = { 324973db240SAdrian Hunter .magic = JITHEADER_MAGIC, 325973db240SAdrian Hunter .version = JITHEADER_VERSION, 326973db240SAdrian Hunter .total_size = sizeof(header), 327973db240SAdrian Hunter .pid = getpid(), 328973db240SAdrian Hunter .timestamp = rdtsc(), 329973db240SAdrian Hunter .flags = JITDUMP_FLAGS_ARCH_TIMESTAMP, 330973db240SAdrian Hunter }; 331973db240SAdrian Hunter char filename[256]; 332973db240SAdrian Hunter FILE *f; 333973db240SAdrian Hunter void *m; 334973db240SAdrian Hunter 335973db240SAdrian Hunter snprintf(filename, sizeof(filename), "jit-%d.dump", getpid()); 336973db240SAdrian Hunter f = fopen(filename, "w+"); 337973db240SAdrian Hunter if (!f) 338973db240SAdrian Hunter goto err; 339973db240SAdrian Hunter /* Create an MMAP event for the jitdump file. That is how perf tool finds it. */ 340973db240SAdrian Hunter m = mmap(0, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(f), 0); 341973db240SAdrian Hunter if (m == MAP_FAILED) 342973db240SAdrian Hunter goto err_close; 343973db240SAdrian Hunter munmap(m, 4096); 344973db240SAdrian Hunter if (fwrite(&header,sizeof(header),1,f) != 1) 345973db240SAdrian Hunter goto err_close; 346973db240SAdrian Hunter return f; 347973db240SAdrian Hunter 348973db240SAdrian Hunter err_close: 349973db240SAdrian Hunter fclose(f); 350973db240SAdrian Hunter err: 351973db240SAdrian Hunter return NULL; 352973db240SAdrian Hunter } 353973db240SAdrian Hunter 354973db240SAdrian Hunter static int write_jitdump(FILE *f, void *addr, const uint8_t *dat, size_t sz, uint64_t *idx) 355973db240SAdrian Hunter { 356973db240SAdrian Hunter struct jr_code_load rec = { 357973db240SAdrian Hunter .p.id = JIT_CODE_LOAD, 358973db240SAdrian Hunter .p.total_size = sizeof(rec) + sz, 359973db240SAdrian Hunter .p.timestamp = rdtsc(), 360973db240SAdrian Hunter .pid = getpid(), 361973db240SAdrian Hunter .tid = gettid(), 362973db240SAdrian Hunter .vma = (unsigned long)addr, 363973db240SAdrian Hunter .code_addr = (unsigned long)addr, 364973db240SAdrian Hunter .code_size = sz, 365973db240SAdrian Hunter .code_index = ++*idx, 366973db240SAdrian Hunter }; 367973db240SAdrian Hunter 368973db240SAdrian Hunter if (fwrite(&rec,sizeof(rec),1,f) != 1 || 369973db240SAdrian Hunter fwrite(dat, sz, 1, f) != 1) 370973db240SAdrian Hunter return -1; 371973db240SAdrian Hunter return 0; 372973db240SAdrian Hunter } 373973db240SAdrian Hunter 374973db240SAdrian Hunter static void close_jitdump(FILE *f) 375973db240SAdrian Hunter { 376973db240SAdrian Hunter fclose(f); 377973db240SAdrian Hunter } 378973db240SAdrian Hunter 379973db240SAdrian Hunter int main() 380973db240SAdrian Hunter { 381973db240SAdrian Hunter /* Get a memory page to store executable code */ 382973db240SAdrian Hunter void *addr = mmap(0, 4096, PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 383973db240SAdrian Hunter /* Code to execute: mov CHK_BYTE, %eax ; ret */ 384973db240SAdrian Hunter uint8_t dat[] = {0xb8, CHK_BYTE, 0x00, 0x00, 0x00, 0xc3}; 385973db240SAdrian Hunter FILE *f = open_jitdump(); 386973db240SAdrian Hunter uint64_t idx = 0; 387973db240SAdrian Hunter int ret = 1; 388973db240SAdrian Hunter 389973db240SAdrian Hunter if (!f) 390973db240SAdrian Hunter return 1; 391973db240SAdrian Hunter /* Copy executable code to executable memory page */ 392973db240SAdrian Hunter memcpy(addr, dat, sizeof(dat)); 393973db240SAdrian Hunter /* Record it in the jitdump file */ 394973db240SAdrian Hunter if (write_jitdump(f, addr, dat, sizeof(dat), &idx)) 395973db240SAdrian Hunter goto out_close; 396973db240SAdrian Hunter /* Call it */ 397973db240SAdrian Hunter ret = ((int (*)(void))addr)() - CHK_BYTE; 398973db240SAdrian Hunter out_close: 399973db240SAdrian Hunter close_jitdump(f); 400973db240SAdrian Hunter return ret; 401973db240SAdrian Hunter } 402973db240SAdrian Hunter _end_of_file_ 403973db240SAdrian Hunter fi 404973db240SAdrian Hunter 405973db240SAdrian Hunter if ! $have_jitdump_workload ; then 406973db240SAdrian Hunter echo "SKIP: No jitdump workload" 407973db240SAdrian Hunter return 2 408973db240SAdrian Hunter fi 409973db240SAdrian Hunter 410973db240SAdrian Hunter # Change to temp_dir so jitdump collateral files go there 411973db240SAdrian Hunter cd "${temp_dir}" 412973db240SAdrian Hunter perf_record_no_bpf -o "${tmpfile}" -e intel_pt//u "${jitdump_workload}" 413973db240SAdrian Hunter perf inject -i "${tmpfile}" -o "${perfdatafile}" --jit 414973db240SAdrian Hunter decode_br_cnt=$(perf script -i "${perfdatafile}" --itrace=b | wc -l) 415973db240SAdrian Hunter # Note that overflow and lost errors are suppressed for the error count 416973db240SAdrian Hunter decode_err_cnt=$(perf script -i "${perfdatafile}" --itrace=e-o-l | grep -ci error) 417973db240SAdrian Hunter cd - 418973db240SAdrian Hunter # Should be thousands of branches 419973db240SAdrian Hunter if [ "${decode_br_cnt}" -lt 1000 ] ; then 420973db240SAdrian Hunter echo "Decode failed, only ${decode_br_cnt} branches" 421973db240SAdrian Hunter return 1 422973db240SAdrian Hunter fi 423973db240SAdrian Hunter # Should be no errors 424973db240SAdrian Hunter if [ "${decode_err_cnt}" -ne 0 ] ; then 425973db240SAdrian Hunter echo "Decode failed, ${decode_err_cnt} errors" 426f77811a0SAmmy Yi perf script -i "${perfdatafile}" --itrace=e-o-l --show-mmap-events | cat 427973db240SAdrian Hunter return 1 428973db240SAdrian Hunter fi 429973db240SAdrian Hunter 430973db240SAdrian Hunter echo OK 431973db240SAdrian Hunter return 0 432973db240SAdrian Hunter} 433973db240SAdrian Hunter 434f77811a0SAmmy Yitest_packet_filter() 435f77811a0SAmmy Yi{ 436f77811a0SAmmy Yi echo "--- Test with MTC and TSC disabled ---" 437f77811a0SAmmy Yi # Disable MTC and TSC 438f77811a0SAmmy Yi perf_record_no_decode -o "${perfdatafile}" -e intel_pt/mtc=0,tsc=0/u uname 439f77811a0SAmmy Yi # Should not get MTC packet 440f77811a0SAmmy Yi mtc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "MTC 0x") 441f77811a0SAmmy Yi if [ "${mtc_cnt}" -ne 0 ] ; then 442f77811a0SAmmy Yi echo "Failed to filter with mtc=0" 443f77811a0SAmmy Yi return 1 444f77811a0SAmmy Yi fi 445f77811a0SAmmy Yi # Should not get TSC package 446f77811a0SAmmy Yi tsc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TSC 0x") 447f77811a0SAmmy Yi if [ "${tsc_cnt}" -ne 0 ] ; then 448f77811a0SAmmy Yi echo "Failed to filter with tsc=0" 449f77811a0SAmmy Yi return 1 450f77811a0SAmmy Yi fi 451f77811a0SAmmy Yi echo OK 452f77811a0SAmmy Yi return 0 453f77811a0SAmmy Yi} 454f77811a0SAmmy Yi 455f77811a0SAmmy Yitest_disable_branch() 456f77811a0SAmmy Yi{ 457f77811a0SAmmy Yi echo "--- Test with branches disabled ---" 458f77811a0SAmmy Yi # Disable branch 459f77811a0SAmmy Yi perf_record_no_decode -o "${perfdatafile}" -e intel_pt/branch=0/u uname 460f77811a0SAmmy Yi # Should not get branch related packets 461f77811a0SAmmy Yi tnt_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TNT 0x") 462f77811a0SAmmy Yi tip_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TIP 0x") 463f77811a0SAmmy Yi fup_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "FUP 0x") 464f77811a0SAmmy Yi if [ "${tnt_cnt}" -ne 0 ] || [ "${tip_cnt}" -ne 0 ] || [ "${fup_cnt}" -ne 0 ] ; then 465f77811a0SAmmy Yi echo "Failed to disable branches" 466f77811a0SAmmy Yi return 1 467f77811a0SAmmy Yi fi 468f77811a0SAmmy Yi echo OK 469f77811a0SAmmy Yi return 0 470f77811a0SAmmy Yi} 471f77811a0SAmmy Yi 472f77811a0SAmmy Yitest_time_cyc() 473f77811a0SAmmy Yi{ 474f77811a0SAmmy Yi echo "--- Test with/without CYC ---" 475f77811a0SAmmy Yi # Check if CYC is supported 476f77811a0SAmmy Yi cyc=$(cat /sys/bus/event_source/devices/intel_pt/caps/psb_cyc) 477f77811a0SAmmy Yi if [ "${cyc}" != "1" ] ; then 478f77811a0SAmmy Yi echo "SKIP: CYC is not supported" 479f77811a0SAmmy Yi return 2 480f77811a0SAmmy Yi fi 481f77811a0SAmmy Yi # Enable CYC 482f77811a0SAmmy Yi perf_record_no_decode -o "${perfdatafile}" -e intel_pt/cyc/u uname 483f77811a0SAmmy Yi # should get CYC packets 484f77811a0SAmmy Yi cyc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "CYC 0x") 485f77811a0SAmmy Yi if [ "${cyc_cnt}" = "0" ] ; then 486f77811a0SAmmy Yi echo "Failed to get CYC packet" 487f77811a0SAmmy Yi return 1 488f77811a0SAmmy Yi fi 489f77811a0SAmmy Yi # Without CYC 490f77811a0SAmmy Yi perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u uname 491f77811a0SAmmy Yi # Should not get CYC packets 492f77811a0SAmmy Yi cyc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "CYC 0x") 493f77811a0SAmmy Yi if [ "${cyc_cnt}" -gt 0 ] ; then 494f77811a0SAmmy Yi echo "Still get CYC packet without cyc" 495f77811a0SAmmy Yi return 1 496f77811a0SAmmy Yi fi 497f77811a0SAmmy Yi echo OK 498f77811a0SAmmy Yi return 0 499f77811a0SAmmy Yi} 500f77811a0SAmmy Yi 501f77811a0SAmmy Yitest_sample() 502f77811a0SAmmy Yi{ 503f77811a0SAmmy Yi echo "--- Test recording with sample mode ---" 504f77811a0SAmmy Yi # Check if recording with sample mode is working 505f77811a0SAmmy Yi if ! perf_record_no_decode -o "${perfdatafile}" --aux-sample=8192 -e '{intel_pt//u,branch-misses:u}' uname ; then 506f77811a0SAmmy Yi echo "perf record failed with --aux-sample" 507f77811a0SAmmy Yi return 1 508f77811a0SAmmy Yi fi 509*a4680850SAdrian Hunter # Check with event with PMU name 510*a4680850SAdrian Hunter if perf_record_no_decode -o "${perfdatafile}" -e br_misp_retired.all_branches:u uname ; then 511*a4680850SAdrian Hunter if ! perf_record_no_decode -o "${perfdatafile}" -e '{intel_pt//,br_misp_retired.all_branches/aux-sample-size=8192/}:u' uname ; then 512*a4680850SAdrian Hunter echo "perf record failed with --aux-sample-size" 513*a4680850SAdrian Hunter return 1 514*a4680850SAdrian Hunter fi 515*a4680850SAdrian Hunter fi 516f77811a0SAmmy Yi echo OK 517f77811a0SAmmy Yi return 0 518f77811a0SAmmy Yi} 519f77811a0SAmmy Yi 520f77811a0SAmmy Yitest_kernel_trace() 521f77811a0SAmmy Yi{ 522f77811a0SAmmy Yi echo "--- Test with kernel trace ---" 523f77811a0SAmmy Yi # Check if recording with kernel trace is working 524f77811a0SAmmy Yi can_kernel || return 2 525f77811a0SAmmy Yi if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt//k -m1,128 uname ; then 526f77811a0SAmmy Yi echo "perf record failed with intel_pt//k" 527f77811a0SAmmy Yi return 1 528f77811a0SAmmy Yi fi 529f77811a0SAmmy Yi echo OK 530f77811a0SAmmy Yi return 0 531f77811a0SAmmy Yi} 532f77811a0SAmmy Yi 533f77811a0SAmmy Yitest_virtual_lbr() 534f77811a0SAmmy Yi{ 535f77811a0SAmmy Yi echo "--- Test virtual LBR ---" 536246122a8SNamhyung Kim # Check if python script is supported 537246122a8SNamhyung Kim libpython=$(perf version --build-options | grep python | grep -cv OFF) 538246122a8SNamhyung Kim if [ "${libpython}" != "1" ] ; then 539246122a8SNamhyung Kim echo "SKIP: python scripting is not supported" 540246122a8SNamhyung Kim return 2 541246122a8SNamhyung Kim fi 542f77811a0SAmmy Yi 543f77811a0SAmmy Yi # Python script to determine the maximum size of branch stacks 544f77811a0SAmmy Yi cat << "_end_of_file_" > "${maxbrstack}" 545f77811a0SAmmy Yifrom __future__ import print_function 546f77811a0SAmmy Yi 547f77811a0SAmmy Yibmax = 0 548f77811a0SAmmy Yi 549f77811a0SAmmy Yidef process_event(param_dict): 550f77811a0SAmmy Yi if "brstack" in param_dict: 551f77811a0SAmmy Yi brstack = param_dict["brstack"] 552f77811a0SAmmy Yi n = len(brstack) 553f77811a0SAmmy Yi global bmax 554f77811a0SAmmy Yi if n > bmax: 555f77811a0SAmmy Yi bmax = n 556f77811a0SAmmy Yi 557f77811a0SAmmy Yidef trace_end(): 558f77811a0SAmmy Yi print("max brstack", bmax) 559f77811a0SAmmy Yi_end_of_file_ 560f77811a0SAmmy Yi 561f77811a0SAmmy Yi # Check if virtual lbr is working 562f77811a0SAmmy Yi perf_record_no_bpf -o "${perfdatafile}" --aux-sample -e '{intel_pt//,cycles}:u' uname 563f77811a0SAmmy Yi times_val=$(perf script -i "${perfdatafile}" --itrace=L -s "${maxbrstack}" 2>/dev/null | grep "max brstack " | cut -d " " -f 3) 564f77811a0SAmmy Yi case "${times_val}" in 565f77811a0SAmmy Yi [0-9]*) ;; 566f77811a0SAmmy Yi *) times_val=0;; 567f77811a0SAmmy Yi esac 568f77811a0SAmmy Yi if [ "${times_val}" -lt 2 ] ; then 569f77811a0SAmmy Yi echo "Failed with virtual lbr" 570f77811a0SAmmy Yi return 1 571f77811a0SAmmy Yi fi 572f77811a0SAmmy Yi echo OK 573f77811a0SAmmy Yi return 0 574f77811a0SAmmy Yi} 575f77811a0SAmmy Yi 576f77811a0SAmmy Yitest_power_event() 577f77811a0SAmmy Yi{ 578f77811a0SAmmy Yi echo "--- Test power events ---" 579f77811a0SAmmy Yi # Check if power events are supported 580f77811a0SAmmy Yi power_event=$(cat /sys/bus/event_source/devices/intel_pt/caps/power_event_trace) 581f77811a0SAmmy Yi if [ "${power_event}" != "1" ] ; then 582f77811a0SAmmy Yi echo "SKIP: power_event_trace is not supported" 583f77811a0SAmmy Yi return 2 584f77811a0SAmmy Yi fi 585f77811a0SAmmy Yi if ! perf_record_no_decode -o "${perfdatafile}" -a -e intel_pt/pwr_evt/u uname ; then 586f77811a0SAmmy Yi echo "perf record failed with pwr_evt" 587f77811a0SAmmy Yi return 1 588f77811a0SAmmy Yi fi 589f77811a0SAmmy Yi echo OK 590f77811a0SAmmy Yi return 0 591f77811a0SAmmy Yi} 592f77811a0SAmmy Yi 593f77811a0SAmmy Yitest_no_tnt() 594f77811a0SAmmy Yi{ 595f77811a0SAmmy Yi echo "--- Test with TNT packets disabled ---" 596f77811a0SAmmy Yi # Check if TNT disable is supported 597f77811a0SAmmy Yi notnt=$(cat /sys/bus/event_source/devices/intel_pt/caps/tnt_disable) 598f77811a0SAmmy Yi if [ "${notnt}" != "1" ] ; then 599f77811a0SAmmy Yi echo "SKIP: tnt_disable is not supported" 600f77811a0SAmmy Yi return 2 601f77811a0SAmmy Yi fi 602f77811a0SAmmy Yi perf_record_no_decode -o "${perfdatafile}" -e intel_pt/notnt/u uname 603f77811a0SAmmy Yi # Should be no TNT packets 604f77811a0SAmmy Yi tnt_cnt=$(perf script -i "${perfdatafile}" -D | grep -c TNT) 605f77811a0SAmmy Yi if [ "${tnt_cnt}" -ne 0 ] ; then 606f77811a0SAmmy Yi echo "TNT packets still there after notnt" 607f77811a0SAmmy Yi return 1 608f77811a0SAmmy Yi fi 609f77811a0SAmmy Yi echo OK 610f77811a0SAmmy Yi return 0 611f77811a0SAmmy Yi} 612f77811a0SAmmy Yi 613f77811a0SAmmy Yitest_event_trace() 614f77811a0SAmmy Yi{ 615f77811a0SAmmy Yi echo "--- Test with event_trace ---" 616f77811a0SAmmy Yi # Check if event_trace is supported 617f77811a0SAmmy Yi event_trace=$(cat /sys/bus/event_source/devices/intel_pt/caps/event_trace) 618f77811a0SAmmy Yi if [ "${event_trace}" != 1 ] ; then 619f77811a0SAmmy Yi echo "SKIP: event_trace is not supported" 620f77811a0SAmmy Yi return 2 621f77811a0SAmmy Yi fi 622f77811a0SAmmy Yi if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt/event/u uname ; then 623f77811a0SAmmy Yi echo "perf record failed with event trace" 624f77811a0SAmmy Yi return 1 625f77811a0SAmmy Yi fi 626f77811a0SAmmy Yi echo OK 627f77811a0SAmmy Yi return 0 628f77811a0SAmmy Yi} 629f77811a0SAmmy Yi 630e072b097SNamhyung Kimtest_pipe() 631e072b097SNamhyung Kim{ 632e072b097SNamhyung Kim echo "--- Test with pipe mode ---" 633e072b097SNamhyung Kim # Check if it works with pipe 634e072b097SNamhyung Kim if ! perf_record_no_bpf -o- -e intel_pt//u uname | perf report -q -i- --itrace=i10000 ; then 635e072b097SNamhyung Kim echo "perf record + report failed with pipe mode" 636e072b097SNamhyung Kim return 1 637e072b097SNamhyung Kim fi 638e072b097SNamhyung Kim if ! perf_record_no_bpf -o- -e intel_pt//u uname | perf inject -b > /dev/null ; then 639e072b097SNamhyung Kim echo "perf record + inject failed with pipe mode" 640e072b097SNamhyung Kim return 1 641e072b097SNamhyung Kim fi 642e072b097SNamhyung Kim echo OK 643e072b097SNamhyung Kim return 0 644e072b097SNamhyung Kim} 645e072b097SNamhyung Kim 6461097b38fSAdrian Huntercount_result() 6471097b38fSAdrian Hunter{ 6485d7aac2bSAdrian Hunter if [ "$1" -eq 2 ] ; then 649202d0394SAdrian Hunter skip_cnt=$((skip_cnt + 1)) 6501097b38fSAdrian Hunter return 6511097b38fSAdrian Hunter fi 6525d7aac2bSAdrian Hunter if [ "$1" -eq 0 ] ; then 653202d0394SAdrian Hunter ok_cnt=$((ok_cnt + 1)) 6541097b38fSAdrian Hunter return 6551097b38fSAdrian Hunter fi 656202d0394SAdrian Hunter err_cnt=$((err_cnt + 1)) 6571097b38fSAdrian Hunter} 6581097b38fSAdrian Hunter 659fd9b45e3SAdrian Hunterret=0 660e4080492SAdrian Huntertest_system_wide_side_band || ret=$? ; count_result $ret ; ret=0 661e4080492SAdrian Huntertest_per_thread "" "" || ret=$? ; count_result $ret ; ret=0 662e4080492SAdrian Huntertest_per_thread "k" "(incl. kernel) " || ret=$? ; count_result $ret ; ret=0 663973db240SAdrian Huntertest_jitdump || ret=$? ; count_result $ret ; ret=0 664f77811a0SAmmy Yitest_packet_filter || ret=$? ; count_result $ret ; ret=0 665f77811a0SAmmy Yitest_disable_branch || ret=$? ; count_result $ret ; ret=0 666f77811a0SAmmy Yitest_time_cyc || ret=$? ; count_result $ret ; ret=0 667f77811a0SAmmy Yitest_sample || ret=$? ; count_result $ret ; ret=0 668f77811a0SAmmy Yitest_kernel_trace || ret=$? ; count_result $ret ; ret=0 669f77811a0SAmmy Yitest_virtual_lbr || ret=$? ; count_result $ret ; ret=0 670f77811a0SAmmy Yitest_power_event || ret=$? ; count_result $ret ; ret=0 671f77811a0SAmmy Yitest_no_tnt || ret=$? ; count_result $ret ; ret=0 672f77811a0SAmmy Yitest_event_trace || ret=$? ; count_result $ret ; ret=0 673e072b097SNamhyung Kimtest_pipe || ret=$? ; count_result $ret ; ret=0 6741097b38fSAdrian Hunter 67519af23dfSAdrian Huntercleanup 6761097b38fSAdrian Hunter 6772c1c9e35SAdrian Hunterecho "--- Done ---" 6782c1c9e35SAdrian Hunter 6791097b38fSAdrian Hunterif [ ${err_cnt} -gt 0 ] ; then 6801097b38fSAdrian Hunter exit 1 6811097b38fSAdrian Hunterfi 6821097b38fSAdrian Hunter 6831097b38fSAdrian Hunterif [ ${ok_cnt} -gt 0 ] ; then 6841097b38fSAdrian Hunter exit 0 6851097b38fSAdrian Hunterfi 6861097b38fSAdrian Hunter 6871097b38fSAdrian Hunterexit 2 688