162306a36Sopenharmony_ci#!/bin/sh 262306a36Sopenharmony_ci# Miscellaneous Intel PT testing 362306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciset -e 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci# Skip if no Intel PT 862306a36Sopenharmony_ciperf list | grep -q 'intel_pt//' || exit 2 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cishelldir=$(dirname "$0") 1162306a36Sopenharmony_ci. "${shelldir}"/lib/waiting.sh 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciskip_cnt=0 1462306a36Sopenharmony_ciok_cnt=0 1562306a36Sopenharmony_cierr_cnt=0 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_citemp_dir=$(mktemp -d /tmp/perf-test-intel-pt-sh.XXXXXXXXXX) 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_citmpfile="${temp_dir}/tmp-perf.data" 2062306a36Sopenharmony_ciperfdatafile="${temp_dir}/test-perf.data" 2162306a36Sopenharmony_cioutfile="${temp_dir}/test-out.txt" 2262306a36Sopenharmony_cierrfile="${temp_dir}/test-err.txt" 2362306a36Sopenharmony_ciworkload="${temp_dir}/workload" 2462306a36Sopenharmony_ciawkscript="${temp_dir}/awkscript" 2562306a36Sopenharmony_cijitdump_workload="${temp_dir}/jitdump_workload" 2662306a36Sopenharmony_cimaxbrstack="${temp_dir}/maxbrstack.py" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cicleanup() 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci trap - EXIT TERM INT 3162306a36Sopenharmony_ci sane=$(echo "${temp_dir}" | cut -b 1-26) 3262306a36Sopenharmony_ci if [ "${sane}" = "/tmp/perf-test-intel-pt-sh" ] ; then 3362306a36Sopenharmony_ci echo "--- Cleaning up ---" 3462306a36Sopenharmony_ci rm -f "${temp_dir}/"* 3562306a36Sopenharmony_ci rmdir "${temp_dir}" 3662306a36Sopenharmony_ci fi 3762306a36Sopenharmony_ci} 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_citrap_cleanup() 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci cleanup 4262306a36Sopenharmony_ci exit 1 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_citrap trap_cleanup EXIT TERM INT 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci# perf record for testing without decoding 4862306a36Sopenharmony_ciperf_record_no_decode() 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci # Options to speed up recording: no post-processing, no build-id cache update, 5162306a36Sopenharmony_ci # and no BPF events. 5262306a36Sopenharmony_ci perf record -B -N --no-bpf-event "$@" 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci# perf record for testing should not need BPF events 5662306a36Sopenharmony_ciperf_record_no_bpf() 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci # Options for no BPF events 5962306a36Sopenharmony_ci perf record --no-bpf-event "$@" 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cihave_workload=false 6362306a36Sopenharmony_cicat << _end_of_file_ | /usr/bin/cc -o "${workload}" -xc - -pthread && have_workload=true 6462306a36Sopenharmony_ci#include <time.h> 6562306a36Sopenharmony_ci#include <pthread.h> 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_civoid work(void) { 6862306a36Sopenharmony_ci struct timespec tm = { 6962306a36Sopenharmony_ci .tv_nsec = 1000000, 7062306a36Sopenharmony_ci }; 7162306a36Sopenharmony_ci int i; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci /* Run for about 30 seconds */ 7462306a36Sopenharmony_ci for (i = 0; i < 30000; i++) 7562306a36Sopenharmony_ci nanosleep(&tm, NULL); 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_civoid *threadfunc(void *arg) { 7962306a36Sopenharmony_ci work(); 8062306a36Sopenharmony_ci return NULL; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciint main(void) { 8462306a36Sopenharmony_ci pthread_t th; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci pthread_create(&th, NULL, threadfunc, NULL); 8762306a36Sopenharmony_ci work(); 8862306a36Sopenharmony_ci pthread_join(th, NULL); 8962306a36Sopenharmony_ci return 0; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci_end_of_file_ 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cican_cpu_wide() 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci echo "Checking for CPU-wide recording on CPU $1" 9662306a36Sopenharmony_ci if ! perf_record_no_decode -o "${tmpfile}" -e dummy:u -C "$1" true >/dev/null 2>&1 ; then 9762306a36Sopenharmony_ci echo "No so skipping" 9862306a36Sopenharmony_ci return 2 9962306a36Sopenharmony_ci fi 10062306a36Sopenharmony_ci echo OK 10162306a36Sopenharmony_ci return 0 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_citest_system_wide_side_band() 10562306a36Sopenharmony_ci{ 10662306a36Sopenharmony_ci echo "--- Test system-wide sideband ---" 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci # Need CPU 0 and CPU 1 10962306a36Sopenharmony_ci can_cpu_wide 0 || return $? 11062306a36Sopenharmony_ci can_cpu_wide 1 || return $? 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci # Record on CPU 0 a task running on CPU 1 11362306a36Sopenharmony_ci perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u -C 0 -- taskset --cpu-list 1 uname 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci # Should get MMAP events from CPU 1 because they can be needed to decode 11662306a36Sopenharmony_ci mmap_cnt=$(perf script -i "${perfdatafile}" --no-itrace --show-mmap-events -C 1 2>/dev/null | grep -c MMAP) 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci if [ "${mmap_cnt}" -gt 0 ] ; then 11962306a36Sopenharmony_ci echo OK 12062306a36Sopenharmony_ci return 0 12162306a36Sopenharmony_ci fi 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci echo "Failed to record MMAP events on CPU 1 when tracing CPU 0" 12462306a36Sopenharmony_ci return 1 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cican_kernel() 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci if [ -z "${can_kernel_trace}" ] ; then 13062306a36Sopenharmony_ci can_kernel_trace=0 13162306a36Sopenharmony_ci perf_record_no_decode -o "${tmpfile}" -e dummy:k true >/dev/null 2>&1 && can_kernel_trace=1 13262306a36Sopenharmony_ci fi 13362306a36Sopenharmony_ci if [ ${can_kernel_trace} -eq 0 ] ; then 13462306a36Sopenharmony_ci echo "SKIP: no kernel tracing" 13562306a36Sopenharmony_ci return 2 13662306a36Sopenharmony_ci fi 13762306a36Sopenharmony_ci return 0 13862306a36Sopenharmony_ci} 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_citest_per_thread() 14162306a36Sopenharmony_ci{ 14262306a36Sopenharmony_ci k="$1" 14362306a36Sopenharmony_ci desc="$2" 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci echo "--- Test per-thread ${desc}recording ---" 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if ! $have_workload ; then 14862306a36Sopenharmony_ci echo "No workload, so skipping" 14962306a36Sopenharmony_ci return 2 15062306a36Sopenharmony_ci fi 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci if [ "${k}" = "k" ] ; then 15362306a36Sopenharmony_ci can_kernel || return 2 15462306a36Sopenharmony_ci fi 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci cat <<- "_end_of_file_" > "${awkscript}" 15762306a36Sopenharmony_ci BEGIN { 15862306a36Sopenharmony_ci s = "[ ]*" 15962306a36Sopenharmony_ci u = s"[0-9]+"s 16062306a36Sopenharmony_ci d = s"[0-9-]+"s 16162306a36Sopenharmony_ci x = s"[0-9a-fA-FxX]+"s 16262306a36Sopenharmony_ci mmapping = "idx"u": mmapping fd"u 16362306a36Sopenharmony_ci set_output = "idx"u": set output fd"u"->"u 16462306a36Sopenharmony_ci perf_event_open = "sys_perf_event_open: pid"d"cpu"d"group_fd"d"flags"x"="u 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci /perf record opening and mmapping events/ { 16862306a36Sopenharmony_ci if (!done) 16962306a36Sopenharmony_ci active = 1 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /perf record done opening and mmapping events/ { 17362306a36Sopenharmony_ci active = 0 17462306a36Sopenharmony_ci done = 1 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci $0 ~ perf_event_open && active { 17862306a36Sopenharmony_ci match($0, perf_event_open) 17962306a36Sopenharmony_ci $0 = substr($0, RSTART, RLENGTH) 18062306a36Sopenharmony_ci pid = $3 18162306a36Sopenharmony_ci cpu = $5 18262306a36Sopenharmony_ci fd = $11 18362306a36Sopenharmony_ci print "pid " pid " cpu " cpu " fd " fd " : " $0 18462306a36Sopenharmony_ci fd_array[fd] = fd 18562306a36Sopenharmony_ci pid_array[fd] = pid 18662306a36Sopenharmony_ci cpu_array[fd] = cpu 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci $0 ~ mmapping && active { 19062306a36Sopenharmony_ci match($0, mmapping) 19162306a36Sopenharmony_ci $0 = substr($0, RSTART, RLENGTH) 19262306a36Sopenharmony_ci fd = $5 19362306a36Sopenharmony_ci print "fd " fd " : " $0 19462306a36Sopenharmony_ci if (fd in fd_array) { 19562306a36Sopenharmony_ci mmap_array[fd] = 1 19662306a36Sopenharmony_ci } else { 19762306a36Sopenharmony_ci print "Unknown fd " fd 19862306a36Sopenharmony_ci exit 1 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci $0 ~ set_output && active { 20362306a36Sopenharmony_ci match($0, set_output) 20462306a36Sopenharmony_ci $0 = substr($0, RSTART, RLENGTH) 20562306a36Sopenharmony_ci fd = $6 20662306a36Sopenharmony_ci fd_to = $8 20762306a36Sopenharmony_ci print "fd " fd " fd_to " fd_to " : " $0 20862306a36Sopenharmony_ci if (fd in fd_array) { 20962306a36Sopenharmony_ci if (fd_to in fd_array) { 21062306a36Sopenharmony_ci set_output_array[fd] = fd_to 21162306a36Sopenharmony_ci } else { 21262306a36Sopenharmony_ci print "Unknown fd " fd_to 21362306a36Sopenharmony_ci exit 1 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci } else { 21662306a36Sopenharmony_ci print "Unknown fd " fd 21762306a36Sopenharmony_ci exit 1 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci END { 22262306a36Sopenharmony_ci print "Checking " length(fd_array) " fds" 22362306a36Sopenharmony_ci for (fd in fd_array) { 22462306a36Sopenharmony_ci if (fd in mmap_array) { 22562306a36Sopenharmony_ci pid = pid_array[fd] 22662306a36Sopenharmony_ci if (pid != -1) { 22762306a36Sopenharmony_ci if (pid in pids) { 22862306a36Sopenharmony_ci print "More than 1 mmap for PID " pid 22962306a36Sopenharmony_ci exit 1 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci pids[pid] = 1 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci cpu = cpu_array[fd] 23462306a36Sopenharmony_ci if (cpu != -1) { 23562306a36Sopenharmony_ci if (cpu in cpus) { 23662306a36Sopenharmony_ci print "More than 1 mmap for CPU " cpu 23762306a36Sopenharmony_ci exit 1 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci cpus[cpu] = 1 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci } else if (!(fd in set_output_array)) { 24262306a36Sopenharmony_ci print "No mmap for fd " fd 24362306a36Sopenharmony_ci exit 1 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci n = length(pids) 24762306a36Sopenharmony_ci if (n != thread_cnt) { 24862306a36Sopenharmony_ci print "Expected " thread_cnt " per-thread mmaps - found " n 24962306a36Sopenharmony_ci exit 1 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci _end_of_file_ 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci $workload & 25562306a36Sopenharmony_ci w1=$! 25662306a36Sopenharmony_ci $workload & 25762306a36Sopenharmony_ci w2=$! 25862306a36Sopenharmony_ci echo "Workload PIDs are $w1 and $w2" 25962306a36Sopenharmony_ci wait_for_threads ${w1} 2 26062306a36Sopenharmony_ci wait_for_threads ${w2} 2 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u"${k}" -vvv --per-thread -p "${w1},${w2}" 2>"${errfile}" >"${outfile}" & 26362306a36Sopenharmony_ci ppid=$! 26462306a36Sopenharmony_ci echo "perf PID is $ppid" 26562306a36Sopenharmony_ci wait_for_perf_to_start ${ppid} "${errfile}" || return 1 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci kill ${w1} 26862306a36Sopenharmony_ci wait_for_process_to_exit ${w1} || return 1 26962306a36Sopenharmony_ci is_running ${ppid} || return 1 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci kill ${w2} 27262306a36Sopenharmony_ci wait_for_process_to_exit ${w2} || return 1 27362306a36Sopenharmony_ci wait_for_process_to_exit ${ppid} || return 1 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci awk -v thread_cnt=4 -f "${awkscript}" "${errfile}" || return 1 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci echo OK 27862306a36Sopenharmony_ci return 0 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_citest_jitdump() 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci echo "--- Test tracing self-modifying code that uses jitdump ---" 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci script_path=$(realpath "$0") 28662306a36Sopenharmony_ci script_dir=$(dirname "$script_path") 28762306a36Sopenharmony_ci jitdump_incl_dir="${script_dir}/../../util" 28862306a36Sopenharmony_ci jitdump_h="${jitdump_incl_dir}/jitdump.h" 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if [ ! -e "${jitdump_h}" ] ; then 29162306a36Sopenharmony_ci echo "SKIP: Include file jitdump.h not found" 29262306a36Sopenharmony_ci return 2 29362306a36Sopenharmony_ci fi 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if [ -z "${have_jitdump_workload}" ] ; then 29662306a36Sopenharmony_ci have_jitdump_workload=false 29762306a36Sopenharmony_ci # Create a workload that uses self-modifying code and generates its own jitdump file 29862306a36Sopenharmony_ci cat <<- "_end_of_file_" | /usr/bin/cc -o "${jitdump_workload}" -I "${jitdump_incl_dir}" -xc - -pthread && have_jitdump_workload=true 29962306a36Sopenharmony_ci #define _GNU_SOURCE 30062306a36Sopenharmony_ci #include <sys/mman.h> 30162306a36Sopenharmony_ci #include <sys/types.h> 30262306a36Sopenharmony_ci #include <stddef.h> 30362306a36Sopenharmony_ci #include <stdio.h> 30462306a36Sopenharmony_ci #include <stdint.h> 30562306a36Sopenharmony_ci #include <unistd.h> 30662306a36Sopenharmony_ci #include <string.h> 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci #include "jitdump.h" 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci #define CHK_BYTE 0x5a 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci static inline uint64_t rdtsc(void) 31362306a36Sopenharmony_ci { 31462306a36Sopenharmony_ci unsigned int low, high; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci asm volatile("rdtsc" : "=a" (low), "=d" (high)); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci return low | ((uint64_t)high) << 32; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci static FILE *open_jitdump(void) 32262306a36Sopenharmony_ci { 32362306a36Sopenharmony_ci struct jitheader header = { 32462306a36Sopenharmony_ci .magic = JITHEADER_MAGIC, 32562306a36Sopenharmony_ci .version = JITHEADER_VERSION, 32662306a36Sopenharmony_ci .total_size = sizeof(header), 32762306a36Sopenharmony_ci .pid = getpid(), 32862306a36Sopenharmony_ci .timestamp = rdtsc(), 32962306a36Sopenharmony_ci .flags = JITDUMP_FLAGS_ARCH_TIMESTAMP, 33062306a36Sopenharmony_ci }; 33162306a36Sopenharmony_ci char filename[256]; 33262306a36Sopenharmony_ci FILE *f; 33362306a36Sopenharmony_ci void *m; 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci snprintf(filename, sizeof(filename), "jit-%d.dump", getpid()); 33662306a36Sopenharmony_ci f = fopen(filename, "w+"); 33762306a36Sopenharmony_ci if (!f) 33862306a36Sopenharmony_ci goto err; 33962306a36Sopenharmony_ci /* Create an MMAP event for the jitdump file. That is how perf tool finds it. */ 34062306a36Sopenharmony_ci m = mmap(0, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(f), 0); 34162306a36Sopenharmony_ci if (m == MAP_FAILED) 34262306a36Sopenharmony_ci goto err_close; 34362306a36Sopenharmony_ci munmap(m, 4096); 34462306a36Sopenharmony_ci if (fwrite(&header,sizeof(header),1,f) != 1) 34562306a36Sopenharmony_ci goto err_close; 34662306a36Sopenharmony_ci return f; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci err_close: 34962306a36Sopenharmony_ci fclose(f); 35062306a36Sopenharmony_ci err: 35162306a36Sopenharmony_ci return NULL; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci static int write_jitdump(FILE *f, void *addr, const uint8_t *dat, size_t sz, uint64_t *idx) 35562306a36Sopenharmony_ci { 35662306a36Sopenharmony_ci struct jr_code_load rec = { 35762306a36Sopenharmony_ci .p.id = JIT_CODE_LOAD, 35862306a36Sopenharmony_ci .p.total_size = sizeof(rec) + sz, 35962306a36Sopenharmony_ci .p.timestamp = rdtsc(), 36062306a36Sopenharmony_ci .pid = getpid(), 36162306a36Sopenharmony_ci .tid = gettid(), 36262306a36Sopenharmony_ci .vma = (unsigned long)addr, 36362306a36Sopenharmony_ci .code_addr = (unsigned long)addr, 36462306a36Sopenharmony_ci .code_size = sz, 36562306a36Sopenharmony_ci .code_index = ++*idx, 36662306a36Sopenharmony_ci }; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci if (fwrite(&rec,sizeof(rec),1,f) != 1 || 36962306a36Sopenharmony_ci fwrite(dat, sz, 1, f) != 1) 37062306a36Sopenharmony_ci return -1; 37162306a36Sopenharmony_ci return 0; 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci static void close_jitdump(FILE *f) 37562306a36Sopenharmony_ci { 37662306a36Sopenharmony_ci fclose(f); 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci int main() 38062306a36Sopenharmony_ci { 38162306a36Sopenharmony_ci /* Get a memory page to store executable code */ 38262306a36Sopenharmony_ci void *addr = mmap(0, 4096, PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 38362306a36Sopenharmony_ci /* Code to execute: mov CHK_BYTE, %eax ; ret */ 38462306a36Sopenharmony_ci uint8_t dat[] = {0xb8, CHK_BYTE, 0x00, 0x00, 0x00, 0xc3}; 38562306a36Sopenharmony_ci FILE *f = open_jitdump(); 38662306a36Sopenharmony_ci uint64_t idx = 0; 38762306a36Sopenharmony_ci int ret = 1; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci if (!f) 39062306a36Sopenharmony_ci return 1; 39162306a36Sopenharmony_ci /* Copy executable code to executable memory page */ 39262306a36Sopenharmony_ci memcpy(addr, dat, sizeof(dat)); 39362306a36Sopenharmony_ci /* Record it in the jitdump file */ 39462306a36Sopenharmony_ci if (write_jitdump(f, addr, dat, sizeof(dat), &idx)) 39562306a36Sopenharmony_ci goto out_close; 39662306a36Sopenharmony_ci /* Call it */ 39762306a36Sopenharmony_ci ret = ((int (*)(void))addr)() - CHK_BYTE; 39862306a36Sopenharmony_ci out_close: 39962306a36Sopenharmony_ci close_jitdump(f); 40062306a36Sopenharmony_ci return ret; 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci _end_of_file_ 40362306a36Sopenharmony_ci fi 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if ! $have_jitdump_workload ; then 40662306a36Sopenharmony_ci echo "SKIP: No jitdump workload" 40762306a36Sopenharmony_ci return 2 40862306a36Sopenharmony_ci fi 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci # Change to temp_dir so jitdump collateral files go there 41162306a36Sopenharmony_ci cd "${temp_dir}" 41262306a36Sopenharmony_ci perf_record_no_bpf -o "${tmpfile}" -e intel_pt//u "${jitdump_workload}" 41362306a36Sopenharmony_ci perf inject -i "${tmpfile}" -o "${perfdatafile}" --jit 41462306a36Sopenharmony_ci decode_br_cnt=$(perf script -i "${perfdatafile}" --itrace=b | wc -l) 41562306a36Sopenharmony_ci # Note that overflow and lost errors are suppressed for the error count 41662306a36Sopenharmony_ci decode_err_cnt=$(perf script -i "${perfdatafile}" --itrace=e-o-l | grep -ci error) 41762306a36Sopenharmony_ci cd - 41862306a36Sopenharmony_ci # Should be thousands of branches 41962306a36Sopenharmony_ci if [ "${decode_br_cnt}" -lt 1000 ] ; then 42062306a36Sopenharmony_ci echo "Decode failed, only ${decode_br_cnt} branches" 42162306a36Sopenharmony_ci return 1 42262306a36Sopenharmony_ci fi 42362306a36Sopenharmony_ci # Should be no errors 42462306a36Sopenharmony_ci if [ "${decode_err_cnt}" -ne 0 ] ; then 42562306a36Sopenharmony_ci echo "Decode failed, ${decode_err_cnt} errors" 42662306a36Sopenharmony_ci perf script -i "${perfdatafile}" --itrace=e-o-l --show-mmap-events | cat 42762306a36Sopenharmony_ci return 1 42862306a36Sopenharmony_ci fi 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci echo OK 43162306a36Sopenharmony_ci return 0 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_citest_packet_filter() 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci echo "--- Test with MTC and TSC disabled ---" 43762306a36Sopenharmony_ci # Disable MTC and TSC 43862306a36Sopenharmony_ci perf_record_no_decode -o "${perfdatafile}" -e intel_pt/mtc=0,tsc=0/u uname 43962306a36Sopenharmony_ci # Should not get MTC packet 44062306a36Sopenharmony_ci mtc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "MTC 0x") 44162306a36Sopenharmony_ci if [ "${mtc_cnt}" -ne 0 ] ; then 44262306a36Sopenharmony_ci echo "Failed to filter with mtc=0" 44362306a36Sopenharmony_ci return 1 44462306a36Sopenharmony_ci fi 44562306a36Sopenharmony_ci # Should not get TSC package 44662306a36Sopenharmony_ci tsc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TSC 0x") 44762306a36Sopenharmony_ci if [ "${tsc_cnt}" -ne 0 ] ; then 44862306a36Sopenharmony_ci echo "Failed to filter with tsc=0" 44962306a36Sopenharmony_ci return 1 45062306a36Sopenharmony_ci fi 45162306a36Sopenharmony_ci echo OK 45262306a36Sopenharmony_ci return 0 45362306a36Sopenharmony_ci} 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_citest_disable_branch() 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci echo "--- Test with branches disabled ---" 45862306a36Sopenharmony_ci # Disable branch 45962306a36Sopenharmony_ci perf_record_no_decode -o "${perfdatafile}" -e intel_pt/branch=0/u uname 46062306a36Sopenharmony_ci # Should not get branch related packets 46162306a36Sopenharmony_ci tnt_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TNT 0x") 46262306a36Sopenharmony_ci tip_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TIP 0x") 46362306a36Sopenharmony_ci fup_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "FUP 0x") 46462306a36Sopenharmony_ci if [ "${tnt_cnt}" -ne 0 ] || [ "${tip_cnt}" -ne 0 ] || [ "${fup_cnt}" -ne 0 ] ; then 46562306a36Sopenharmony_ci echo "Failed to disable branches" 46662306a36Sopenharmony_ci return 1 46762306a36Sopenharmony_ci fi 46862306a36Sopenharmony_ci echo OK 46962306a36Sopenharmony_ci return 0 47062306a36Sopenharmony_ci} 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_citest_time_cyc() 47362306a36Sopenharmony_ci{ 47462306a36Sopenharmony_ci echo "--- Test with/without CYC ---" 47562306a36Sopenharmony_ci # Check if CYC is supported 47662306a36Sopenharmony_ci cyc=$(cat /sys/bus/event_source/devices/intel_pt/caps/psb_cyc) 47762306a36Sopenharmony_ci if [ "${cyc}" != "1" ] ; then 47862306a36Sopenharmony_ci echo "SKIP: CYC is not supported" 47962306a36Sopenharmony_ci return 2 48062306a36Sopenharmony_ci fi 48162306a36Sopenharmony_ci # Enable CYC 48262306a36Sopenharmony_ci perf_record_no_decode -o "${perfdatafile}" -e intel_pt/cyc/u uname 48362306a36Sopenharmony_ci # should get CYC packets 48462306a36Sopenharmony_ci cyc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "CYC 0x") 48562306a36Sopenharmony_ci if [ "${cyc_cnt}" = "0" ] ; then 48662306a36Sopenharmony_ci echo "Failed to get CYC packet" 48762306a36Sopenharmony_ci return 1 48862306a36Sopenharmony_ci fi 48962306a36Sopenharmony_ci # Without CYC 49062306a36Sopenharmony_ci perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u uname 49162306a36Sopenharmony_ci # Should not get CYC packets 49262306a36Sopenharmony_ci cyc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "CYC 0x") 49362306a36Sopenharmony_ci if [ "${cyc_cnt}" -gt 0 ] ; then 49462306a36Sopenharmony_ci echo "Still get CYC packet without cyc" 49562306a36Sopenharmony_ci return 1 49662306a36Sopenharmony_ci fi 49762306a36Sopenharmony_ci echo OK 49862306a36Sopenharmony_ci return 0 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_citest_sample() 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci echo "--- Test recording with sample mode ---" 50462306a36Sopenharmony_ci # Check if recording with sample mode is working 50562306a36Sopenharmony_ci if ! perf_record_no_decode -o "${perfdatafile}" --aux-sample=8192 -e '{intel_pt//u,branch-misses:u}' uname ; then 50662306a36Sopenharmony_ci echo "perf record failed with --aux-sample" 50762306a36Sopenharmony_ci return 1 50862306a36Sopenharmony_ci fi 50962306a36Sopenharmony_ci # Check with event with PMU name 51062306a36Sopenharmony_ci if perf_record_no_decode -o "${perfdatafile}" -e br_misp_retired.all_branches:u uname ; then 51162306a36Sopenharmony_ci if ! perf_record_no_decode -o "${perfdatafile}" -e '{intel_pt//,br_misp_retired.all_branches/aux-sample-size=8192/}:u' uname ; then 51262306a36Sopenharmony_ci echo "perf record failed with --aux-sample-size" 51362306a36Sopenharmony_ci return 1 51462306a36Sopenharmony_ci fi 51562306a36Sopenharmony_ci fi 51662306a36Sopenharmony_ci echo OK 51762306a36Sopenharmony_ci return 0 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_citest_kernel_trace() 52162306a36Sopenharmony_ci{ 52262306a36Sopenharmony_ci echo "--- Test with kernel trace ---" 52362306a36Sopenharmony_ci # Check if recording with kernel trace is working 52462306a36Sopenharmony_ci can_kernel || return 2 52562306a36Sopenharmony_ci if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt//k -m1,128 uname ; then 52662306a36Sopenharmony_ci echo "perf record failed with intel_pt//k" 52762306a36Sopenharmony_ci return 1 52862306a36Sopenharmony_ci fi 52962306a36Sopenharmony_ci echo OK 53062306a36Sopenharmony_ci return 0 53162306a36Sopenharmony_ci} 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_citest_virtual_lbr() 53462306a36Sopenharmony_ci{ 53562306a36Sopenharmony_ci echo "--- Test virtual LBR ---" 53662306a36Sopenharmony_ci # Check if python script is supported 53762306a36Sopenharmony_ci libpython=$(perf version --build-options | grep python | grep -cv OFF) 53862306a36Sopenharmony_ci if [ "${libpython}" != "1" ] ; then 53962306a36Sopenharmony_ci echo "SKIP: python scripting is not supported" 54062306a36Sopenharmony_ci return 2 54162306a36Sopenharmony_ci fi 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci # Python script to determine the maximum size of branch stacks 54462306a36Sopenharmony_ci cat << "_end_of_file_" > "${maxbrstack}" 54562306a36Sopenharmony_cifrom __future__ import print_function 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_cibmax = 0 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cidef process_event(param_dict): 55062306a36Sopenharmony_ci if "brstack" in param_dict: 55162306a36Sopenharmony_ci brstack = param_dict["brstack"] 55262306a36Sopenharmony_ci n = len(brstack) 55362306a36Sopenharmony_ci global bmax 55462306a36Sopenharmony_ci if n > bmax: 55562306a36Sopenharmony_ci bmax = n 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_cidef trace_end(): 55862306a36Sopenharmony_ci print("max brstack", bmax) 55962306a36Sopenharmony_ci_end_of_file_ 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci # Check if virtual lbr is working 56262306a36Sopenharmony_ci perf_record_no_bpf -o "${perfdatafile}" --aux-sample -e '{intel_pt//,cycles}:u' uname 56362306a36Sopenharmony_ci times_val=$(perf script -i "${perfdatafile}" --itrace=L -s "${maxbrstack}" 2>/dev/null | grep "max brstack " | cut -d " " -f 3) 56462306a36Sopenharmony_ci case "${times_val}" in 56562306a36Sopenharmony_ci [0-9]*) ;; 56662306a36Sopenharmony_ci *) times_val=0;; 56762306a36Sopenharmony_ci esac 56862306a36Sopenharmony_ci if [ "${times_val}" -lt 2 ] ; then 56962306a36Sopenharmony_ci echo "Failed with virtual lbr" 57062306a36Sopenharmony_ci return 1 57162306a36Sopenharmony_ci fi 57262306a36Sopenharmony_ci echo OK 57362306a36Sopenharmony_ci return 0 57462306a36Sopenharmony_ci} 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_citest_power_event() 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci echo "--- Test power events ---" 57962306a36Sopenharmony_ci # Check if power events are supported 58062306a36Sopenharmony_ci power_event=$(cat /sys/bus/event_source/devices/intel_pt/caps/power_event_trace) 58162306a36Sopenharmony_ci if [ "${power_event}" != "1" ] ; then 58262306a36Sopenharmony_ci echo "SKIP: power_event_trace is not supported" 58362306a36Sopenharmony_ci return 2 58462306a36Sopenharmony_ci fi 58562306a36Sopenharmony_ci if ! perf_record_no_decode -o "${perfdatafile}" -a -e intel_pt/pwr_evt/u uname ; then 58662306a36Sopenharmony_ci echo "perf record failed with pwr_evt" 58762306a36Sopenharmony_ci return 1 58862306a36Sopenharmony_ci fi 58962306a36Sopenharmony_ci echo OK 59062306a36Sopenharmony_ci return 0 59162306a36Sopenharmony_ci} 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_citest_no_tnt() 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci echo "--- Test with TNT packets disabled ---" 59662306a36Sopenharmony_ci # Check if TNT disable is supported 59762306a36Sopenharmony_ci notnt=$(cat /sys/bus/event_source/devices/intel_pt/caps/tnt_disable) 59862306a36Sopenharmony_ci if [ "${notnt}" != "1" ] ; then 59962306a36Sopenharmony_ci echo "SKIP: tnt_disable is not supported" 60062306a36Sopenharmony_ci return 2 60162306a36Sopenharmony_ci fi 60262306a36Sopenharmony_ci perf_record_no_decode -o "${perfdatafile}" -e intel_pt/notnt/u uname 60362306a36Sopenharmony_ci # Should be no TNT packets 60462306a36Sopenharmony_ci tnt_cnt=$(perf script -i "${perfdatafile}" -D | grep -c TNT) 60562306a36Sopenharmony_ci if [ "${tnt_cnt}" -ne 0 ] ; then 60662306a36Sopenharmony_ci echo "TNT packets still there after notnt" 60762306a36Sopenharmony_ci return 1 60862306a36Sopenharmony_ci fi 60962306a36Sopenharmony_ci echo OK 61062306a36Sopenharmony_ci return 0 61162306a36Sopenharmony_ci} 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_citest_event_trace() 61462306a36Sopenharmony_ci{ 61562306a36Sopenharmony_ci echo "--- Test with event_trace ---" 61662306a36Sopenharmony_ci # Check if event_trace is supported 61762306a36Sopenharmony_ci event_trace=$(cat /sys/bus/event_source/devices/intel_pt/caps/event_trace) 61862306a36Sopenharmony_ci if [ "${event_trace}" != 1 ] ; then 61962306a36Sopenharmony_ci echo "SKIP: event_trace is not supported" 62062306a36Sopenharmony_ci return 2 62162306a36Sopenharmony_ci fi 62262306a36Sopenharmony_ci if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt/event/u uname ; then 62362306a36Sopenharmony_ci echo "perf record failed with event trace" 62462306a36Sopenharmony_ci return 1 62562306a36Sopenharmony_ci fi 62662306a36Sopenharmony_ci echo OK 62762306a36Sopenharmony_ci return 0 62862306a36Sopenharmony_ci} 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_citest_pipe() 63162306a36Sopenharmony_ci{ 63262306a36Sopenharmony_ci echo "--- Test with pipe mode ---" 63362306a36Sopenharmony_ci # Check if it works with pipe 63462306a36Sopenharmony_ci if ! perf_record_no_bpf -o- -e intel_pt//u uname | perf report -q -i- --itrace=i10000 ; then 63562306a36Sopenharmony_ci echo "perf record + report failed with pipe mode" 63662306a36Sopenharmony_ci return 1 63762306a36Sopenharmony_ci fi 63862306a36Sopenharmony_ci if ! perf_record_no_bpf -o- -e intel_pt//u uname | perf inject -b > /dev/null ; then 63962306a36Sopenharmony_ci echo "perf record + inject failed with pipe mode" 64062306a36Sopenharmony_ci return 1 64162306a36Sopenharmony_ci fi 64262306a36Sopenharmony_ci echo OK 64362306a36Sopenharmony_ci return 0 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cicount_result() 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci if [ "$1" -eq 2 ] ; then 64962306a36Sopenharmony_ci skip_cnt=$((skip_cnt + 1)) 65062306a36Sopenharmony_ci return 65162306a36Sopenharmony_ci fi 65262306a36Sopenharmony_ci if [ "$1" -eq 0 ] ; then 65362306a36Sopenharmony_ci ok_cnt=$((ok_cnt + 1)) 65462306a36Sopenharmony_ci return 65562306a36Sopenharmony_ci fi 65662306a36Sopenharmony_ci err_cnt=$((err_cnt + 1)) 65762306a36Sopenharmony_ci} 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ciret=0 66062306a36Sopenharmony_citest_system_wide_side_band || ret=$? ; count_result $ret ; ret=0 66162306a36Sopenharmony_citest_per_thread "" "" || ret=$? ; count_result $ret ; ret=0 66262306a36Sopenharmony_citest_per_thread "k" "(incl. kernel) " || ret=$? ; count_result $ret ; ret=0 66362306a36Sopenharmony_citest_jitdump || ret=$? ; count_result $ret ; ret=0 66462306a36Sopenharmony_citest_packet_filter || ret=$? ; count_result $ret ; ret=0 66562306a36Sopenharmony_citest_disable_branch || ret=$? ; count_result $ret ; ret=0 66662306a36Sopenharmony_citest_time_cyc || ret=$? ; count_result $ret ; ret=0 66762306a36Sopenharmony_citest_sample || ret=$? ; count_result $ret ; ret=0 66862306a36Sopenharmony_citest_kernel_trace || ret=$? ; count_result $ret ; ret=0 66962306a36Sopenharmony_citest_virtual_lbr || ret=$? ; count_result $ret ; ret=0 67062306a36Sopenharmony_citest_power_event || ret=$? ; count_result $ret ; ret=0 67162306a36Sopenharmony_citest_no_tnt || ret=$? ; count_result $ret ; ret=0 67262306a36Sopenharmony_citest_event_trace || ret=$? ; count_result $ret ; ret=0 67362306a36Sopenharmony_citest_pipe || ret=$? ; count_result $ret ; ret=0 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cicleanup 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ciecho "--- Done ---" 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ciif [ ${err_cnt} -gt 0 ] ; then 68062306a36Sopenharmony_ci exit 1 68162306a36Sopenharmony_cifi 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ciif [ ${ok_cnt} -gt 0 ] ; then 68462306a36Sopenharmony_ci exit 0 68562306a36Sopenharmony_cifi 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ciexit 2 688