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 "$@"
}
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
}
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
}
} elseif (!(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
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;
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 # Check with event with PMU name if perf_record_no_decode -o "${perfdatafile}" -e br_misp_retired.all_branches:u uname ; then if ! perf_record_no_decode -o "${perfdatafile}" -e '{intel_pt//,br_misp_retired.all_branches/aux-sample-size=8192/}:u' uname ; then echo"perf record failed with --aux-sample-size"
return 1 fi 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 ---" # Check if python script is supported
libpython=$(perf version --build-options | grep python | grep -cv OFF) if [ "${libpython}" != "1" ] ; then echo"SKIP: python scripting is not supported"
return 2 fi
# 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
# 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
}
test_pipe()
{ echo"--- Test with pipe mode ---" # Check if it works with pipe if ! perf_record_no_bpf -o- -e intel_pt//u uname | perf report -q -i- --itrace=i10000 ; then echo"perf record + report failed with pipe mode"
return 1 fi if ! perf_record_no_bpf -o- -e intel_pt//u uname | perf inject -b > /dev/null ; then echo"perf record + inject failed with pipe mode"
return 1 fi echo OK
return 0
}
test_pause_resume()
{ echo"--- Test with pause / resume ---" if ! perf_record_no_decode -o "${perfdatafile}" -e intel_pt/aux-action=start-paused/u uname ; then echo"SKIP: pause / resume is not supported"
return 2 fi if ! perf_record_no_bpf -o "${perfdatafile}" \
-e intel_pt/aux-action=start-paused/u \
-e instructions/period=50000,aux-action=resume,name=Resume/u \
-e instructions/period=100000,aux-action=pause,name=Pause/u uname ; then echo"perf record with pause / resume failed"
return 1 fi if ! perf script -i "${perfdatafile}" --itrace=b -Fperiod,event | \
awk 'BEGIN {paused=1;branches=0}
/Resume/ {paused=0}
/branches/ {if (paused) exit 1;branches=1}
/Pause/ {paused=1} END {if (!branches) exit 1}' ; then echo"perf record with pause / resume failed"
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))
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.