Add tests: Test with MTC and TSC disabled Test with branches disabled Test with/without CYC Test recording with sample mode Test with kernel trace Test virtual LBR Test power events Test with TNT packets disabled Test with event_trace These tests mostly check that perf record works with the corresponding Intel PT config terms, sometimes also checking that certain packets do or do not appear in the resulting trace as appropriate. The "Test virtual LBR" is slightly trickier, using a Python script to check that branch stacks are actually synthesized. Signed-off-by: Ammy Yi <ammy.yi@intel.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Link: https://lore.kernel.org/r/20221014170905.64069-8-adrian.hunter@intel.com Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
657 lines
15 KiB
Bash
Executable file
657 lines
15 KiB
Bash
Executable file
#!/bin/sh
|
|
# Miscellaneous Intel PT testing
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
set -e
|
|
|
|
# Skip if no Intel PT
|
|
perf list | grep -q 'intel_pt//' || exit 2
|
|
|
|
shelldir=$(dirname "$0")
|
|
. "${shelldir}"/lib/waiting.sh
|
|
|
|
skip_cnt=0
|
|
ok_cnt=0
|
|
err_cnt=0
|
|
|
|
temp_dir=$(mktemp -d /tmp/perf-test-intel-pt-sh.XXXXXXXXXX)
|
|
|
|
tmpfile="${temp_dir}/tmp-perf.data"
|
|
perfdatafile="${temp_dir}/test-perf.data"
|
|
outfile="${temp_dir}/test-out.txt"
|
|
errfile="${temp_dir}/test-err.txt"
|
|
workload="${temp_dir}/workload"
|
|
awkscript="${temp_dir}/awkscript"
|
|
jitdump_workload="${temp_dir}/jitdump_workload"
|
|
maxbrstack="${temp_dir}/maxbrstack.py"
|
|
|
|
cleanup()
|
|
{
|
|
trap - EXIT TERM INT
|
|
sane=$(echo "${temp_dir}" | cut -b 1-26)
|
|
if [ "${sane}" = "/tmp/perf-test-intel-pt-sh" ] ; then
|
|
echo "--- Cleaning up ---"
|
|
rm -f "${temp_dir}/"*
|
|
rmdir "${temp_dir}"
|
|
fi
|
|
}
|
|
|
|
trap_cleanup()
|
|
{
|
|
cleanup
|
|
exit 1
|
|
}
|
|
|
|
trap trap_cleanup EXIT TERM INT
|
|
|
|
# perf record for testing without decoding
|
|
perf_record_no_decode()
|
|
{
|
|
# Options to speed up recording: no post-processing, no build-id cache update,
|
|
# and no BPF events.
|
|
perf record -B -N --no-bpf-event "$@"
|
|
}
|
|
|
|
# perf record for testing should not need BPF events
|
|
perf_record_no_bpf()
|
|
{
|
|
# Options for no BPF events
|
|
perf record --no-bpf-event "$@"
|
|
}
|
|
|
|
have_workload=false
|
|
cat << _end_of_file_ | /usr/bin/cc -o "${workload}" -xc - -pthread && have_workload=true
|
|
#include <time.h>
|
|
#include <pthread.h>
|
|
|
|
void work(void) {
|
|
struct timespec tm = {
|
|
.tv_nsec = 1000000,
|
|
};
|
|
int i;
|
|
|
|
/* Run for about 30 seconds */
|
|
for (i = 0; i < 30000; i++)
|
|
nanosleep(&tm, NULL);
|
|
}
|
|
|
|
void *threadfunc(void *arg) {
|
|
work();
|
|
return NULL;
|
|
}
|
|
|
|
int main(void) {
|
|
pthread_t th;
|
|
|
|
pthread_create(&th, NULL, threadfunc, NULL);
|
|
work();
|
|
pthread_join(th, NULL);
|
|
return 0;
|
|
}
|
|
_end_of_file_
|
|
|
|
can_cpu_wide()
|
|
{
|
|
echo "Checking for CPU-wide recording on CPU $1"
|
|
if ! perf_record_no_decode -o "${tmpfile}" -e dummy:u -C "$1" true >/dev/null 2>&1 ; then
|
|
echo "No so skipping"
|
|
return 2
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_system_wide_side_band()
|
|
{
|
|
echo "--- Test system-wide sideband ---"
|
|
|
|
# Need CPU 0 and CPU 1
|
|
can_cpu_wide 0 || return $?
|
|
can_cpu_wide 1 || return $?
|
|
|
|
# Record on CPU 0 a task running on CPU 1
|
|
perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u -C 0 -- taskset --cpu-list 1 uname
|
|
|
|
# Should get MMAP events from CPU 1 because they can be needed to decode
|
|
mmap_cnt=$(perf script -i "${perfdatafile}" --no-itrace --show-mmap-events -C 1 2>/dev/null | grep -c MMAP)
|
|
|
|
if [ "${mmap_cnt}" -gt 0 ] ; then
|
|
echo OK
|
|
return 0
|
|
fi
|
|
|
|
echo "Failed to record MMAP events on CPU 1 when tracing CPU 0"
|
|
return 1
|
|
}
|
|
|
|
can_kernel()
|
|
{
|
|
if [ -z "${can_kernel_trace}" ] ; then
|
|
can_kernel_trace=0
|
|
perf_record_no_decode -o "${tmpfile}" -e dummy:k true >/dev/null 2>&1 && can_kernel_trace=1
|
|
fi
|
|
if [ ${can_kernel_trace} -eq 0 ] ; then
|
|
echo "SKIP: no kernel tracing"
|
|
return 2
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
test_per_thread()
|
|
{
|
|
k="$1"
|
|
desc="$2"
|
|
|
|
echo "--- Test per-thread ${desc}recording ---"
|
|
|
|
if ! $have_workload ; then
|
|
echo "No workload, so skipping"
|
|
return 2
|
|
fi
|
|
|
|
if [ "${k}" = "k" ] ; then
|
|
can_kernel || return 2
|
|
fi
|
|
|
|
cat <<- "_end_of_file_" > "${awkscript}"
|
|
BEGIN {
|
|
s = "[ ]*"
|
|
u = s"[0-9]+"s
|
|
d = s"[0-9-]+"s
|
|
x = s"[0-9a-fA-FxX]+"s
|
|
mmapping = "idx"u": mmapping fd"u
|
|
set_output = "idx"u": set output fd"u"->"u
|
|
perf_event_open = "sys_perf_event_open: pid"d"cpu"d"group_fd"d"flags"x"="u
|
|
}
|
|
|
|
/perf record opening and mmapping events/ {
|
|
if (!done)
|
|
active = 1
|
|
}
|
|
|
|
/perf record done opening and mmapping events/ {
|
|
active = 0
|
|
done = 1
|
|
}
|
|
|
|
$0 ~ perf_event_open && active {
|
|
match($0, perf_event_open)
|
|
$0 = substr($0, RSTART, RLENGTH)
|
|
pid = $3
|
|
cpu = $5
|
|
fd = $11
|
|
print "pid " pid " cpu " cpu " fd " fd " : " $0
|
|
fd_array[fd] = fd
|
|
pid_array[fd] = pid
|
|
cpu_array[fd] = cpu
|
|
}
|
|
|
|
$0 ~ mmapping && active {
|
|
match($0, mmapping)
|
|
$0 = substr($0, RSTART, RLENGTH)
|
|
fd = $5
|
|
print "fd " fd " : " $0
|
|
if (fd in fd_array) {
|
|
mmap_array[fd] = 1
|
|
} else {
|
|
print "Unknown fd " fd
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
$0 ~ set_output && active {
|
|
match($0, set_output)
|
|
$0 = substr($0, RSTART, RLENGTH)
|
|
fd = $6
|
|
fd_to = $8
|
|
print "fd " fd " fd_to " fd_to " : " $0
|
|
if (fd in fd_array) {
|
|
if (fd_to in fd_array) {
|
|
set_output_array[fd] = fd_to
|
|
} else {
|
|
print "Unknown fd " fd_to
|
|
exit 1
|
|
}
|
|
} else {
|
|
print "Unknown fd " fd
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
END {
|
|
print "Checking " length(fd_array) " fds"
|
|
for (fd in fd_array) {
|
|
if (fd in mmap_array) {
|
|
pid = pid_array[fd]
|
|
if (pid != -1) {
|
|
if (pid in pids) {
|
|
print "More than 1 mmap for PID " pid
|
|
exit 1
|
|
}
|
|
pids[pid] = 1
|
|
}
|
|
cpu = cpu_array[fd]
|
|
if (cpu != -1) {
|
|
if (cpu in cpus) {
|
|
print "More than 1 mmap for CPU " cpu
|
|
exit 1
|
|
}
|
|
cpus[cpu] = 1
|
|
}
|
|
} else if (!(fd in set_output_array)) {
|
|
print "No mmap for fd " fd
|
|
exit 1
|
|
}
|
|
}
|
|
n = length(pids)
|
|
if (n != thread_cnt) {
|
|
print "Expected " thread_cnt " per-thread mmaps - found " n
|
|
exit 1
|
|
}
|
|
}
|
|
_end_of_file_
|
|
|
|
$workload &
|
|
w1=$!
|
|
$workload &
|
|
w2=$!
|
|
echo "Workload PIDs are $w1 and $w2"
|
|
wait_for_threads ${w1} 2
|
|
wait_for_threads ${w2} 2
|
|
|
|
perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u"${k}" -vvv --per-thread -p "${w1},${w2}" 2>"${errfile}" >"${outfile}" &
|
|
ppid=$!
|
|
echo "perf PID is $ppid"
|
|
wait_for_perf_to_start ${ppid} "${errfile}" || return 1
|
|
|
|
kill ${w1}
|
|
wait_for_process_to_exit ${w1} || return 1
|
|
is_running ${ppid} || return 1
|
|
|
|
kill ${w2}
|
|
wait_for_process_to_exit ${w2} || return 1
|
|
wait_for_process_to_exit ${ppid} || return 1
|
|
|
|
awk -v thread_cnt=4 -f "${awkscript}" "${errfile}" || return 1
|
|
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_jitdump()
|
|
{
|
|
echo "--- Test tracing self-modifying code that uses jitdump ---"
|
|
|
|
script_path=$(realpath "$0")
|
|
script_dir=$(dirname "$script_path")
|
|
jitdump_incl_dir="${script_dir}/../../util"
|
|
jitdump_h="${jitdump_incl_dir}/jitdump.h"
|
|
|
|
if [ ! -e "${jitdump_h}" ] ; then
|
|
echo "SKIP: Include file jitdump.h not found"
|
|
return 2
|
|
fi
|
|
|
|
if [ -z "${have_jitdump_workload}" ] ; then
|
|
have_jitdump_workload=false
|
|
# Create a workload that uses self-modifying code and generates its own jitdump file
|
|
cat <<- "_end_of_file_" | /usr/bin/cc -o "${jitdump_workload}" -I "${jitdump_incl_dir}" -xc - -pthread && have_jitdump_workload=true
|
|
#define _GNU_SOURCE
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
#include "jitdump.h"
|
|
|
|
#define CHK_BYTE 0x5a
|
|
|
|
static inline uint64_t rdtsc(void)
|
|
{
|
|
unsigned int low, high;
|
|
|
|
asm volatile("rdtsc" : "=a" (low), "=d" (high));
|
|
|
|
return low | ((uint64_t)high) << 32;
|
|
}
|
|
|
|
static FILE *open_jitdump(void)
|
|
{
|
|
struct jitheader header = {
|
|
.magic = JITHEADER_MAGIC,
|
|
.version = JITHEADER_VERSION,
|
|
.total_size = sizeof(header),
|
|
.pid = getpid(),
|
|
.timestamp = rdtsc(),
|
|
.flags = JITDUMP_FLAGS_ARCH_TIMESTAMP,
|
|
};
|
|
char filename[256];
|
|
FILE *f;
|
|
void *m;
|
|
|
|
snprintf(filename, sizeof(filename), "jit-%d.dump", getpid());
|
|
f = fopen(filename, "w+");
|
|
if (!f)
|
|
goto err;
|
|
/* Create an MMAP event for the jitdump file. That is how perf tool finds it. */
|
|
m = mmap(0, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(f), 0);
|
|
if (m == MAP_FAILED)
|
|
goto err_close;
|
|
munmap(m, 4096);
|
|
if (fwrite(&header,sizeof(header),1,f) != 1)
|
|
goto err_close;
|
|
return f;
|
|
|
|
err_close:
|
|
fclose(f);
|
|
err:
|
|
return NULL;
|
|
}
|
|
|
|
static int write_jitdump(FILE *f, void *addr, const uint8_t *dat, size_t sz, uint64_t *idx)
|
|
{
|
|
struct jr_code_load rec = {
|
|
.p.id = JIT_CODE_LOAD,
|
|
.p.total_size = sizeof(rec) + sz,
|
|
.p.timestamp = rdtsc(),
|
|
.pid = getpid(),
|
|
.tid = gettid(),
|
|
.vma = (unsigned long)addr,
|
|
.code_addr = (unsigned long)addr,
|
|
.code_size = sz,
|
|
.code_index = ++*idx,
|
|
};
|
|
|
|
if (fwrite(&rec,sizeof(rec),1,f) != 1 ||
|
|
fwrite(dat, sz, 1, f) != 1)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
static void close_jitdump(FILE *f)
|
|
{
|
|
fclose(f);
|
|
}
|
|
|
|
int main()
|
|
{
|
|
/* Get a memory page to store executable code */
|
|
void *addr = mmap(0, 4096, PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
|
/* Code to execute: mov CHK_BYTE, %eax ; ret */
|
|
uint8_t dat[] = {0xb8, CHK_BYTE, 0x00, 0x00, 0x00, 0xc3};
|
|
FILE *f = open_jitdump();
|
|
uint64_t idx = 0;
|
|
int ret = 1;
|
|
|
|
if (!f)
|
|
return 1;
|
|
/* Copy executable code to executable memory page */
|
|
memcpy(addr, dat, sizeof(dat));
|
|
/* Record it in the jitdump file */
|
|
if (write_jitdump(f, addr, dat, sizeof(dat), &idx))
|
|
goto out_close;
|
|
/* Call it */
|
|
ret = ((int (*)(void))addr)() - CHK_BYTE;
|
|
out_close:
|
|
close_jitdump(f);
|
|
return ret;
|
|
}
|
|
_end_of_file_
|
|
fi
|
|
|
|
if ! $have_jitdump_workload ; then
|
|
echo "SKIP: No jitdump workload"
|
|
return 2
|
|
fi
|
|
|
|
# Change to temp_dir so jitdump collateral files go there
|
|
cd "${temp_dir}"
|
|
perf_record_no_bpf -o "${tmpfile}" -e intel_pt//u "${jitdump_workload}"
|
|
perf inject -i "${tmpfile}" -o "${perfdatafile}" --jit
|
|
decode_br_cnt=$(perf script -i "${perfdatafile}" --itrace=b | wc -l)
|
|
# Note that overflow and lost errors are suppressed for the error count
|
|
decode_err_cnt=$(perf script -i "${perfdatafile}" --itrace=e-o-l | grep -ci error)
|
|
cd -
|
|
# Should be thousands of branches
|
|
if [ "${decode_br_cnt}" -lt 1000 ] ; then
|
|
echo "Decode failed, only ${decode_br_cnt} branches"
|
|
return 1
|
|
fi
|
|
# Should be no errors
|
|
if [ "${decode_err_cnt}" -ne 0 ] ; then
|
|
echo "Decode failed, ${decode_err_cnt} errors"
|
|
perf script -i "${perfdatafile}" --itrace=e-o-l --show-mmap-events | cat
|
|
return 1
|
|
fi
|
|
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_packet_filter()
|
|
{
|
|
echo "--- Test with MTC and TSC disabled ---"
|
|
# Disable MTC and TSC
|
|
perf_record_no_decode -o "${perfdatafile}" -e intel_pt/mtc=0,tsc=0/u uname
|
|
# Should not get MTC packet
|
|
mtc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "MTC 0x")
|
|
if [ "${mtc_cnt}" -ne 0 ] ; then
|
|
echo "Failed to filter with mtc=0"
|
|
return 1
|
|
fi
|
|
# Should not get TSC package
|
|
tsc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TSC 0x")
|
|
if [ "${tsc_cnt}" -ne 0 ] ; then
|
|
echo "Failed to filter with tsc=0"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_disable_branch()
|
|
{
|
|
echo "--- Test with branches disabled ---"
|
|
# Disable branch
|
|
perf_record_no_decode -o "${perfdatafile}" -e intel_pt/branch=0/u uname
|
|
# Should not get branch related packets
|
|
tnt_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TNT 0x")
|
|
tip_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "TIP 0x")
|
|
fup_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "FUP 0x")
|
|
if [ "${tnt_cnt}" -ne 0 ] || [ "${tip_cnt}" -ne 0 ] || [ "${fup_cnt}" -ne 0 ] ; then
|
|
echo "Failed to disable branches"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_time_cyc()
|
|
{
|
|
echo "--- Test with/without CYC ---"
|
|
# Check if CYC is supported
|
|
cyc=$(cat /sys/bus/event_source/devices/intel_pt/caps/psb_cyc)
|
|
if [ "${cyc}" != "1" ] ; then
|
|
echo "SKIP: CYC is not supported"
|
|
return 2
|
|
fi
|
|
# Enable CYC
|
|
perf_record_no_decode -o "${perfdatafile}" -e intel_pt/cyc/u uname
|
|
# should get CYC packets
|
|
cyc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "CYC 0x")
|
|
if [ "${cyc_cnt}" = "0" ] ; then
|
|
echo "Failed to get CYC packet"
|
|
return 1
|
|
fi
|
|
# Without CYC
|
|
perf_record_no_decode -o "${perfdatafile}" -e intel_pt//u uname
|
|
# Should not get CYC packets
|
|
cyc_cnt=$(perf script -i "${perfdatafile}" -D 2>/dev/null | grep -c "CYC 0x")
|
|
if [ "${cyc_cnt}" -gt 0 ] ; then
|
|
echo "Still get CYC packet without cyc"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_sample()
|
|
{
|
|
echo "--- Test recording with sample mode ---"
|
|
# Check if recording with sample mode is working
|
|
if ! perf_record_no_decode -o "${perfdatafile}" --aux-sample=8192 -e '{intel_pt//u,branch-misses:u}' uname ; then
|
|
echo "perf record failed with --aux-sample"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_kernel_trace()
|
|
{
|
|
echo "--- Test with kernel trace ---"
|
|
# Check if recording with kernel trace is working
|
|
can_kernel || return 2
|
|
if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt//k -m1,128 uname ; then
|
|
echo "perf record failed with intel_pt//k"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_virtual_lbr()
|
|
{
|
|
echo "--- Test virtual LBR ---"
|
|
|
|
# Python script to determine the maximum size of branch stacks
|
|
cat << "_end_of_file_" > "${maxbrstack}"
|
|
from __future__ import print_function
|
|
|
|
bmax = 0
|
|
|
|
def process_event(param_dict):
|
|
if "brstack" in param_dict:
|
|
brstack = param_dict["brstack"]
|
|
n = len(brstack)
|
|
global bmax
|
|
if n > bmax:
|
|
bmax = n
|
|
|
|
def trace_end():
|
|
print("max brstack", bmax)
|
|
_end_of_file_
|
|
|
|
# Check if virtual lbr is working
|
|
perf_record_no_bpf -o "${perfdatafile}" --aux-sample -e '{intel_pt//,cycles}:u' uname
|
|
times_val=$(perf script -i "${perfdatafile}" --itrace=L -s "${maxbrstack}" 2>/dev/null | grep "max brstack " | cut -d " " -f 3)
|
|
case "${times_val}" in
|
|
[0-9]*) ;;
|
|
*) times_val=0;;
|
|
esac
|
|
if [ "${times_val}" -lt 2 ] ; then
|
|
echo "Failed with virtual lbr"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_power_event()
|
|
{
|
|
echo "--- Test power events ---"
|
|
# Check if power events are supported
|
|
power_event=$(cat /sys/bus/event_source/devices/intel_pt/caps/power_event_trace)
|
|
if [ "${power_event}" != "1" ] ; then
|
|
echo "SKIP: power_event_trace is not supported"
|
|
return 2
|
|
fi
|
|
if ! perf_record_no_decode -o "${perfdatafile}" -a -e intel_pt/pwr_evt/u uname ; then
|
|
echo "perf record failed with pwr_evt"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_no_tnt()
|
|
{
|
|
echo "--- Test with TNT packets disabled ---"
|
|
# Check if TNT disable is supported
|
|
notnt=$(cat /sys/bus/event_source/devices/intel_pt/caps/tnt_disable)
|
|
if [ "${notnt}" != "1" ] ; then
|
|
echo "SKIP: tnt_disable is not supported"
|
|
return 2
|
|
fi
|
|
perf_record_no_decode -o "${perfdatafile}" -e intel_pt/notnt/u uname
|
|
# Should be no TNT packets
|
|
tnt_cnt=$(perf script -i "${perfdatafile}" -D | grep -c TNT)
|
|
if [ "${tnt_cnt}" -ne 0 ] ; then
|
|
echo "TNT packets still there after notnt"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
test_event_trace()
|
|
{
|
|
echo "--- Test with event_trace ---"
|
|
# Check if event_trace is supported
|
|
event_trace=$(cat /sys/bus/event_source/devices/intel_pt/caps/event_trace)
|
|
if [ "${event_trace}" != 1 ] ; then
|
|
echo "SKIP: event_trace is not supported"
|
|
return 2
|
|
fi
|
|
if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt/event/u uname ; then
|
|
echo "perf record failed with event trace"
|
|
return 1
|
|
fi
|
|
echo OK
|
|
return 0
|
|
}
|
|
|
|
count_result()
|
|
{
|
|
if [ "$1" -eq 2 ] ; then
|
|
skip_cnt=$((skip_cnt + 1))
|
|
return
|
|
fi
|
|
if [ "$1" -eq 0 ] ; then
|
|
ok_cnt=$((ok_cnt + 1))
|
|
return
|
|
fi
|
|
err_cnt=$((err_cnt + 1))
|
|
}
|
|
|
|
ret=0
|
|
test_system_wide_side_band || ret=$? ; count_result $ret ; ret=0
|
|
test_per_thread "" "" || ret=$? ; count_result $ret ; ret=0
|
|
test_per_thread "k" "(incl. kernel) " || ret=$? ; count_result $ret ; ret=0
|
|
test_jitdump || ret=$? ; count_result $ret ; ret=0
|
|
test_packet_filter || ret=$? ; count_result $ret ; ret=0
|
|
test_disable_branch || ret=$? ; count_result $ret ; ret=0
|
|
test_time_cyc || ret=$? ; count_result $ret ; ret=0
|
|
test_sample || ret=$? ; count_result $ret ; ret=0
|
|
test_kernel_trace || ret=$? ; count_result $ret ; ret=0
|
|
test_virtual_lbr || ret=$? ; count_result $ret ; ret=0
|
|
test_power_event || ret=$? ; count_result $ret ; ret=0
|
|
test_no_tnt || ret=$? ; count_result $ret ; ret=0
|
|
test_event_trace || ret=$? ; count_result $ret ; ret=0
|
|
|
|
cleanup
|
|
|
|
echo "--- Done ---"
|
|
|
|
if [ ${err_cnt} -gt 0 ] ; then
|
|
exit 1
|
|
fi
|
|
|
|
if [ ${ok_cnt} -gt 0 ] ; then
|
|
exit 0
|
|
fi
|
|
|
|
exit 2
|