Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,45 @@
#!/bin/bash -e
# CoreSight concurrent threads (exclusive)
# SPDX-License-Identifier: GPL-2.0
# If CoreSight is not available, skip the test
perf list pmu | grep -q cs_etm || exit 2
tmpdir=$(mktemp -d /tmp/__perf_test.coresight_concurrent_threads.XXXXX)
cleanup() {
rm -rf "${tmpdir}"
trap - EXIT TERM INT
}
trap_cleanup() {
cleanup
exit 1
}
trap trap_cleanup EXIT TERM INT
cf="$tmpdir/ctl"
af="$tmpdir/ack"
mkfifo "$cf" "$af"
nthreads=10
# Timestamps off to reduce trace size, start disabled and use the control FIFO
# to only record the workload and not startup.
perf record -o "$tmpdir/data" -e cs_etm/timestamp=0/u -D -1 --control fifo:"$cf","$af" \
-- perf test --record-ctl fifo:"$cf","$af" -w named_threads $nthreads 1 > /dev/null 2>&1
perf script -i "$tmpdir/data" > "$tmpdir/script" 2>/dev/null
# Check all threads were traced and they have the correct thread name and symbol
for i in $(seq 1 $nthreads); do
if ! grep -q "thread${i} .* named_threads_thread${i}" "$tmpdir/script"; then
echo "Error: thread${i} missing" >&2
cleanup
exit 1
fi
done
cleanup
exit 0
@@ -0,0 +1,69 @@
#!/bin/bash -e
# CoreSight context switch thread attribution (exclusive)
# SPDX-License-Identifier: GPL-2.0
# If CoreSight is not available, skip the test
perf list pmu | grep -q cs_etm || exit 2
if [ "$(id -u)" != 0 ]; then
# Requires root for "-C 0" in record command
echo "[Skip] No root permission"
exit 2
fi
tmpdir=$(mktemp -d /tmp/__perf_test.coresight_context_switch.XXXXX)
cleanup() {
rm -rf "${tmpdir}"
trap - EXIT TERM INT
}
trap_cleanup() {
cleanup
exit 1
}
trap trap_cleanup EXIT TERM INT
check_samples() {
owner_samples=$(grep -c "proc1.*context_switch_loop_proc1" "$tmpdir/script" || true)
next_samples=$(grep -c "proc2.*context_switch_loop_proc2" "$tmpdir/script" || true)
if [ "$owner_samples" -eq 0 ] || [ "$next_samples" -eq 0 ]; then
echo "No samples found"
cleanup
exit 1
fi
if grep "proc2.*context_switch_loop_proc1" "$tmpdir/script"; then
echo "Thread1 symbol was attributed to proc2"
cleanup
exit 1
fi
if grep "proc1.*context_switch_loop_proc2" "$tmpdir/script"; then
echo "Thread2 symbol was attributed to proc1"
cleanup
exit 1
fi
}
cf="$tmpdir/ctl"
af="$tmpdir/ack"
mkfifo "$cf" "$af"
# Pin to one CPU so the two threads alternate running but record into the same
# trace buffer. Start disabled and use the control FIFO to only record the
# workload and not startup.
perf record -o "$tmpdir/data" -e cs_etm/timestamp=0/u -C 0 -D -1 --control fifo:"$cf","$af" -- \
taskset --cpu-list 0 perf test --record-ctl fifo:"$cf","$af" \
-w context_switch_loop > /dev/null 2>&1
# Test both instruction and branch sample generation modes.
perf script -i "$tmpdir/data" --itrace=i4 -F comm,pid,tid,ip,sym > "$tmpdir/script" 2>/dev/null
check_samples
perf script -i "$tmpdir/data" --itrace=b -F comm,pid,tid,ip,sym > "$tmpdir/script" 2>/dev/null
check_samples
cleanup
exit 0
@@ -0,0 +1,72 @@
#!/bin/bash -e
# CoreSight deterministic workload decode (exclusive)
# SPDX-License-Identifier: GPL-2.0
# If CoreSight is not available, skip the test
perf list pmu | grep -q cs_etm || exit 2
tmpdir=$(mktemp -d /tmp/__perf_test.coresight_deterministic.XXXXX)
cleanup() {
rm -rf "${tmpdir}"
trap - EXIT TERM INT
}
trap_cleanup() {
cleanup
exit 1
}
trap trap_cleanup EXIT TERM INT
cf="$tmpdir/ctl"
af="$tmpdir/ack"
mkfifo "$cf" "$af"
# Start disabled and use the control FIFO to only record the workload and not
# startup.
perf record -o "$tmpdir/data" -e cs_etm//u -D -1 --control fifo:"$cf","$af" -- \
perf test --record-ctl fifo:"$cf","$af" -w deterministic > /dev/null 2>&1
perf script -i "$tmpdir/data" --itrace=i1i -F ip,srcline | \
grep "deterministic.c" | uniq > "$tmpdir/script" 2>/dev/null
# Remove brace lines and call sites as they may not be hit or may have
# extra hits after returning, depending on the compiler.
sed -i \
-e '/deterministic.c:8$/d' \
-e '/deterministic.c:12$/d' \
-e '/deterministic.c:15$/d' \
-e '/deterministic.c:19$/d' \
-e '/deterministic.c:23$/d' \
-e '/deterministic.c:28$/d' \
-e '/deterministic.c:34$/d' \
-e '/deterministic.c:36$/d' \
-e '/deterministic.c:37$/d' \
"$tmpdir/script"
cat > "$tmpdir/expected" << EOF
deterministic.c:24
deterministic.c:25
deterministic.c:26
deterministic.c:9
deterministic.c:10
deterministic.c:11
deterministic.c:30
deterministic.c:31
deterministic.c:32
deterministic.c:16
deterministic.c:17
deterministic.c:18
EOF
if ! diff -q "$tmpdir/script" "$tmpdir/expected"; then
echo "FAIL: line numbers don't match expected: "
head -n 100 "$tmpdir/script"
cleanup
exit 1
fi
cleanup
exit 0
@@ -0,0 +1,65 @@
#!/bin/bash -e
# CoreSight raw dump stress (exclusive)
# SPDX-License-Identifier: GPL-2.0
if [ "$(id -u)" != 0 ]; then
# Requires root for larger buffer size
echo "[Skip] No root permission"
exit 2
fi
# If CoreSight is not available, skip the test
perf list pmu | grep -q cs_etm || exit 2
tmpdir=$(mktemp -d /tmp/__perf_test.coresight_raw_dump_stress.XXXXX)
cleanup() {
rm -r "${tmpdir}"
trap - EXIT TERM INT
}
trap_cleanup() {
cleanup
exit 1
}
trap trap_cleanup EXIT TERM INT
# Use exit snapshot to record 2M of trace to make about 80MB of raw dump data.
echo "Recording..."
perf record -e cs_etm/timestamp=0/u -m,2M -Se -o "$tmpdir/data" -- \
perf test -w brstack 20000 > /dev/null 2>&1
# Test raw dump runs to completion but don't decode because that's too slow for
# a test
echo "Dumping raw trace..."
perf report --dump-raw-trace -i "$tmpdir/data" 2>/dev/null > "$tmpdir/rawdump"
# Get the size and offset of the first AUXTRACE buffer and the index of the last
# packet in the raw dump.
read -r size offset last_idx <<< "$(awk '
found && /PERF_RECORD_/ { exit }
/PERF_RECORD_AUXTRACE / { found = 1; size = $7; offset = $9; next }
found && /Idx:/ { last_idx = $1; gsub(/Idx:|;/, "", last_idx) }
END { if (last_idx) print size, offset, last_idx }
' "$tmpdir/rawdump")"
# The last Idx minus start offset should equal the size of the buffer if
# everything was dumped. Allow 48 bytes difference to cover 3 frames: current
# frame length, a partial frame and a final empty one, all of which aren't
# dumped.
#
# TODO: for a single snapshot, offset should always be zero. However, we
# currently output AUX records in snapshot mode when we shouldn't, which
# increments the offset. Allow for that until it's fixed so we can test raw
# dumping.
decode_size=$((1 + last_idx - offset))
if [ "$decode_size" -gt "$((size - 48))" ] && [ "$decode_size" -le "$((size))" ]; then
echo "PASS: AUXTRACE buffer length matches dumped packet index"
cleanup
exit 0
fi
echo "FAIL: AUXTRACE buffer length mismatch: size=$size offset=$offset last_idx=$last_idx decode_size=$decode_size"
cleanup
exit 1
@@ -0,0 +1,257 @@
#!/bin/bash
# Check Arm CoreSight trace data recording and synthesized samples (exclusive)
# Uses the 'perf record' to record trace data with Arm CoreSight sinks;
# then verify if there have any branch samples and instruction samples
# are generated by CoreSight with 'perf script' and 'perf report'
# commands.
# SPDX-License-Identifier: GPL-2.0
# Leo Yan <leo.yan@linaro.org>, 2020
glb_err=0
skip_if_no_cs_etm_event() {
perf list pmu | grep -q 'cs_etm//' && return 0
# cs_etm event doesn't exist
return 2
}
skip_if_no_cs_etm_event || exit 2
if [ "$(id -u)" != 0 ]; then
# Requires root for -C and system wide tests
echo "[Skip] No root permission"
exit 2
fi
perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX)
file=$(mktemp /tmp/temporary_file.XXXXX)
cleanup_files()
{
rm -f ${perfdata}
rm -f ${file}
rm -f "${perfdata}.old"
trap - EXIT TERM INT
exit $glb_err
}
trap cleanup_files EXIT TERM INT
record_touch_file() {
echo "Recording trace (only user mode) with path: CPU$2 => $1"
rm -f $file
perf record -o ${perfdata} -e cs_etm/@$1/u --per-thread \
-- taskset -c $2 touch $file > /dev/null 2>&1
}
perf_script_branch_samples() {
echo "Looking at perf.data file for dumping branch samples:"
# Below is an example of the branch samples dumping:
# touch 6512 1 branches:u: ffffb220824c strcmp+0xc (/lib/aarch64-linux-gnu/ld-2.27.so)
# touch 6512 1 branches:u: ffffb22082e0 strcmp+0xa0 (/lib/aarch64-linux-gnu/ld-2.27.so)
# touch 6512 1 branches:u: ffffb2208320 strcmp+0xe0 (/lib/aarch64-linux-gnu/ld-2.27.so)
perf script -F,-time -i ${perfdata} 2>&1 | \
grep -E " +$1 +[0-9]+ .* +branches:(.*:)? +" > /dev/null 2>&1
}
perf_report_instruction_samples() {
echo "Looking at perf.data file for instruction samples:"
# Below is an example of the instruction samples reporting:
# 68.12% touch libc-2.27.so [.] _dl_addr
# 5.80% touch libc-2.27.so [.] getenv
# 4.35% touch ld-2.27.so [.] _dl_fixup
perf report --itrace=i20i --stdio -i ${perfdata} 2>&1 | \
grep -E " +[0-9]+\.[0-9]+% +$1" > /dev/null 2>&1
}
arm_cs_report() {
if [ $2 != 0 ]; then
echo "$1: FAIL"
glb_err=$2
else
echo "$1: PASS"
fi
}
is_device_sink() {
# If the node of "enable_sink" is existed under the device path, this
# means the device is a sink device. Need to exclude 'tpiu' since it
# cannot support perf PMU.
echo "$1" | grep -E -q -v "tpiu"
if [ $? -eq 0 ] && [ -e "$1/enable_sink" ]; then
pmu_dev="/sys/bus/event_source/devices/cs_etm/sinks/$2"
# Warn if the device is not supported by PMU
if ! [ -f $pmu_dev ]; then
echo "PMU doesn't support $pmu_dev"
fi
return 0
fi
# Otherwise, it's not a sink device
return 1
}
arm_cs_iterate_devices() {
for dev in $1/connections/out\:*; do
# Skip testing if it's not a directory
! [ -d $dev ] && continue;
# Read out its symbol link file name
path=`readlink -f $dev`
# Extract device name from path, e.g.
# path = '/sys/devices/platform/20010000.etf/tmc_etf0'
# `> device_name = 'tmc_etf0'
device_name=$(basename $path)
if is_device_sink $path $device_name; then
record_touch_file $device_name $2 &&
perf_script_branch_samples touch &&
perf_report_instruction_samples touch
err=$?
arm_cs_report "CoreSight path testing (CPU$2 -> $device_name)" $err
fi
arm_cs_iterate_devices $dev $2
done
}
arm_cs_etm_traverse_path_test() {
# Iterate for every ETM device
for dev in /sys/bus/event_source/devices/cs_etm/cpu*; do
# Canonicalize the path
dev=`readlink -f $dev`
# Find the ETM device belonging to which CPU
cpu=`cat $dev/cpu`
# Use depth-first search (DFS) to iterate outputs
arm_cs_iterate_devices $dev $cpu
done
}
arm_cs_etm_system_wide_test() {
echo "Recording trace with system wide mode"
perf record -o ${perfdata} -e cs_etm// -a -- ls > /dev/null 2>&1
# System-wide mode should include perf samples so test for that
# instead of ls
perf_script_branch_samples perf
err=$?
arm_cs_report "CoreSight system wide testing" $err
}
arm_cs_etm_snapshot_test() {
echo "Recording trace with snapshot mode"
perf record -o ${perfdata} -e cs_etm// -S -m,128K \
-- dd if=/dev/zero of=/dev/null > /dev/null 2>&1 &
PERFPID=$!
# Wait for perf program
sleep 1
# Send signal to snapshot trace data
kill -USR2 $PERFPID
# Stop perf program
kill $PERFPID
wait $PERFPID
perf_script_branch_samples dd &&
perf_report_instruction_samples dd
err=$?
arm_cs_report "CoreSight snapshot testing" $err
}
arm_cs_etm_basic_test() {
echo "Recording trace with '$*'"
perf record -o ${perfdata} "$@" -- true > /dev/null 2>&1
perf_script_branch_samples true
err=$?
arm_cs_report "CoreSight basic testing with '$*'" $err
}
arm_cs_etm_test_cpu_list() {
echo "Testing sparse CPU list: $1"
perf record -o ${perfdata} -e cs_etm//u -C $1 \
-- taskset --cpu-list $1 true > /dev/null 2>&1
perf_script_branch_samples true
err=$?
arm_cs_report "CoreSight sparse CPUs with '$*'" $err
}
arm_cs_etm_sparse_cpus_test() {
# Iterate for every ETM device
cpus=()
for dev in /sys/bus/event_source/devices/cs_etm/cpu*; do
# Canonicalize the path
dev=`readlink -f $dev`
# Find the ETM device belonging to which CPU
cpus+=("$(cat $dev/cpu)")
done
mapfile -t cpus < <(printf '%s\n' "${cpus[@]}" | sort -n)
total=${#cpus[@]}
# Need more than 1 to test
if [ $total -le 1 ]; then
return 0
fi
half=$((total / 2))
# First half
first_half=$(IFS=,; echo "${cpus[*]:0:$half}")
arm_cs_etm_test_cpu_list $first_half
# Second half
second_half=$(IFS=,; echo "${cpus[*]:$half}")
arm_cs_etm_test_cpu_list $second_half
# Odd list is the same as halves unless >= 4 CPUs
if [ $total -lt 4 ]; then
return 0
fi
# Odd indices
odd_cpus=()
for ((i=1; i<total; i+=2)); do
odd_cpus+=("${cpus[$i]}")
done
odd_list=$(IFS=,; echo "${odd_cpus[*]}")
arm_cs_etm_test_cpu_list $odd_list
}
arm_cs_etm_traverse_path_test
arm_cs_etm_system_wide_test
arm_cs_etm_snapshot_test
# Test all combinations of per-thread, system-wide and normal mode with
# and without timestamps
arm_cs_etm_basic_test -e cs_etm/timestamp=0/u --per-thread
arm_cs_etm_basic_test -e cs_etm/timestamp=1/u --per-thread
arm_cs_etm_basic_test -e cs_etm/timestamp=0/u -a
arm_cs_etm_basic_test -e cs_etm/timestamp=1/u -a
arm_cs_etm_basic_test -e cs_etm/timestamp=0/u
arm_cs_etm_basic_test -e cs_etm/timestamp=1/u
arm_cs_etm_sparse_cpus_test
exit $glb_err
@@ -0,0 +1,64 @@
#!/bin/bash
# Check Arm CoreSight disassembly script completes without errors (exclusive)
# SPDX-License-Identifier: GPL-2.0
# The disassembly script reconstructs ranges of instructions and gives these to objdump to
# decode. objdump doesn't like ranges that go backwards, but these are a good indication
# that decoding has gone wrong either in OpenCSD, Perf or in the range reconstruction in
# the script. Test all 3 parts are working correctly by running the script.
skip_if_no_cs_etm_event() {
perf list pmu | grep -q 'cs_etm//' && return 0
# cs_etm event doesn't exist
return 2
}
skip_if_no_cs_etm_event || exit 2
# Assume an error unless we reach the very end
set -e
glb_err=1
perfdata_dir=$(mktemp -d /tmp/__perf_test.perf.data.XXXXX)
perfdata=${perfdata_dir}/perf.data
file=$(mktemp /tmp/temporary_file.XXXXX)
# Relative path works whether it's installed or running from repo
script_path=$(dirname "$0")/../../../scripts/python/arm-cs-trace-disasm.py
cleanup_files()
{
set +e
rm -rf ${perfdata_dir}
rm -f ${file}
trap - EXIT TERM INT
exit $glb_err
}
trap cleanup_files EXIT TERM INT
# Ranges start and end on branches, so check for some likely branch instructions
branch_search='[[:space:]](bl|b(\.(eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le|al))?|br|blr|ret|cbz|cbnz|tbz|tbnz|svc|eret)([[:space:]]|$)'
## Test kernel ##
if [ "$(id -u)" == 0 ] && [ -e /proc/kcore ]; then
echo "Testing kernel disassembly"
perf record -o ${perfdata} -e cs_etm//k --kcore -Se -m,64K -- touch $file > /dev/null 2>&1
perf script -i ${perfdata} -s python:${script_path} -- \
-d --stop-sample=2 -k ${perfdata}/kcore_dir/kcore 2> /dev/null > ${file}
grep -q -E ${branch_search} ${file}
echo "Found kernel branches"
else
# Root and kcore are required for correct kernel decode due to runtime code patching
echo "No root or kcore, skipping kernel test"
fi
## Test user ##
echo "Testing userspace disassembly"
perf record -o ${perfdata} -e cs_etm//u -Se -m,64K -- touch $file > /dev/null 2>&1
perf script -i ${perfdata} -s python:${script_path} -- \
-d --stop-sample=2 2> /dev/null > ${file}
grep -q -E ${branch_search} ${file}
echo "Found userspace branches"
glb_err=0