* [PATCH v1] perf test: Fixes for check branch stack sampling
@ 2026-04-08 6:03 Ian Rogers
2026-04-08 6:12 ` sashiko-bot
0 siblings, 1 reply; 8+ messages in thread
From: Ian Rogers @ 2026-04-08 6:03 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, German Gomez, linux-perf-users,
linux-kernel
When filtering branch stack samples on user events they sample in user
land but may have come from the kernel. Avoid the target address being
a kernel address but allow the source to be the kernel.
When filtering branch stack samples on kernel events they sample in
kernel land but may have come from user land. Avoid the target being a
user address but allow the source to be in user land.
Increase the duration of the system call sampling test to make the
likelihood of sampling a system call higher (increased from 1000 to
8000 loops - a number found through experimentation on an Intel
Tigerlake laptop), also make the period of the event a prime number.
Put unneeded perf record output into a temporary file so that the test
output isn't cluttered. More clearly state which test is running and
the pass, fail or skipped result of the test.
These changes make the test on an Intel tigerlake laptop reliably pass
rather than reliably fail.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/shell/test_brstack.sh | 122 ++++++++++++++++---------
1 file changed, 78 insertions(+), 44 deletions(-)
diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
index 85233d435be6..d317ed0e063e 100755
--- a/tools/perf/tests/shell/test_brstack.sh
+++ b/tools/perf/tests/shell/test_brstack.sh
@@ -40,7 +40,7 @@ is_arm64() {
check_branches() {
if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$1"; then
- echo "Branches missing $1"
+ echo "ERROR: Branches missing $1"
err=1
fi
}
@@ -48,6 +48,8 @@ check_branches() {
test_user_branches() {
echo "Testing user branch stack sampling"
+ start_err=$err
+ err=0
perf record -o "$TMPDIR/perf.data" --branch-filter any,save_type,u -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
perf script -i "$TMPDIR/perf.data" --fields brstacksym > "$TMPDIR/perf.script"
@@ -73,59 +75,81 @@ test_user_branches() {
perf script -i "$TMPDIR/perf.data" --fields brstack | \
tr ' ' '\n' > "$TMPDIR/perf.script"
- # There should be no kernel addresses with the u option, in either
- # source or target addresses.
- if grep -E -m1 "0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
- echo "ERROR: Kernel address found in user mode"
+ # There should be no kernel addresses in the target with the u option.
+ if grep -q -E -m1 "^0x[0-9a-f]{16}/[89a-f][0-9a-f]{15}/" $TMPDIR/perf.script; then
+ echo "Testing user branch stack sampling [Failed kernel address found in user mode]"
err=1
fi
# some branch types are still not being tested:
# IND COND_CALL COND_RET SYSRET SERROR NO_TX
+ if [ $err -eq 0 ]; then
+ echo "Testing user branch stack sampling [Passed]"
+ err=$start_err
+ else
+ echo "Testing user branch stack sampling [Failed]"
+ fi
}
test_trap_eret_branches() {
echo "Testing trap & eret branches"
+
if ! is_arm64; then
- echo "skip: not arm64"
+ echo "Testing trap & eret branches [Skipped not arm64]"
+ return
+ fi
+ start_err=$err
+ err=0
+ perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
+ perf test -w traploop 1000
+ perf script -i $TMPDIR/perf.data --fields brstacksym | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
+ check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
+ check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
+ if [ $err -eq 0 ]; then
+ echo "Testing trap & eret branches [Passed]"
+ err=$start_err
else
- perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
- perf test -w traploop 1000
- perf script -i $TMPDIR/perf.data --fields brstacksym | \
- tr ' ' '\n' > $TMPDIR/perf.script
-
- # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
- check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
- check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
+ echo "Testing trap & eret branches [Failed]"
fi
}
test_kernel_branches() {
echo "Testing that k option only includes kernel source addresses"
- if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
- echo "skip: not enough privileges"
+ if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
+ echo "Testing that k option [Skipped not enough privileges]"
+ return
+ fi
+ start_err=$err
+ err=0
+ perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
+ perf bench syscall basic --loop 1000 > "$TMPDIR/record.txt" 2>&1
+ perf script -i $TMPDIR/perf.data --fields brstack | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ # Example of branch entries:
+ # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
+ # Source addresses come first and target address can be either
+ # userspace or kernel even with k option, as long as the source
+ # is in kernel.
+
+ # Look for source addresses with top bit set
+ if ! grep -q -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
+ echo "Testing that k option [Failed kernel branches missing]"
+ err=1
+ fi
+ # Look for no target addresses without top bit set
+ if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{0,15}/" $TMPDIR/perf.script; then
+ echo "Testing that k option [Failed user branches found with kernel filter"
+ err=1
+ fi
+ if [ $err -eq 0 ]; then
+ echo "Testing that k option [Passed]"
+ err=$start_err
else
- perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
- perf bench syscall basic --loop 1000
- perf script -i $TMPDIR/perf.data --fields brstack | \
- tr ' ' '\n' > $TMPDIR/perf.script
-
- # Example of branch entries:
- # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
- # Source addresses come first and target address can be either
- # userspace or kernel even with k option, as long as the source
- # is in kernel.
-
- #Look for source addresses with top bit set
- if ! grep -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
- echo "ERROR: Kernel branches missing"
- err=1
- fi
- # Look for no source addresses without top bit set
- if grep -E -m1 "^0x[0-7][0-9a-f]{0,15}" $TMPDIR/perf.script; then
- echo "ERROR: User branches found with kernel filter"
- err=1
- fi
+ echo "Testing that k option [Failed]"
fi
}
@@ -136,14 +160,15 @@ test_filter() {
test_filter_expect=$2
echo "Testing branch stack filtering permutation ($test_filter_filter,$test_filter_expect)"
- perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
+ perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- \
+ ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
perf script -i "$TMPDIR/perf.data" --fields brstack > "$TMPDIR/perf.script"
# fail if we find any branch type that doesn't match any of the expected ones
# also consider UNKNOWN branch types (-)
if [ ! -s "$TMPDIR/perf.script" ]
then
- echo "Empty script output"
+ echo "Testing branch stack filtering [Failed empty script output]"
err=1
return
fi
@@ -154,27 +179,36 @@ test_filter() {
> "$TMPDIR/perf.script-filtered" || true
if [ -s "$TMPDIR/perf.script-filtered" ]
then
- echo "Unexpected branch filter in script output"
+ echo "Testing branch stack filtering [Failed unexpected branch filter]"
cat "$TMPDIR/perf.script"
err=1
return
fi
+ echo "Testing branch stack filtering [Passed]"
}
test_syscall() {
echo "Testing syscalls"
+ start_err=$err
+ err=0
# skip if perf doesn't have enough privileges
- if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
- echo "skip: not enough privileges"
+ if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
+ echo "Testing syscalls [Skipped: not enough privileges]"
else
perf record -o $TMPDIR/perf.data --branch-filter \
- any_call,save_type,u,k -c 10000 -- \
- perf bench syscall basic --loop 1000
+ any_call,save_type,u,k -c 10007 -- \
+ perf bench syscall basic --loop 8000 > "$TMPDIR/record.txt" 2>&1
perf script -i $TMPDIR/perf.data --fields brstacksym | \
tr ' ' '\n' > $TMPDIR/perf.script
check_branches "getppid[^ ]*/SYSCALL/"
fi
+ if [ $err -eq 0 ]; then
+ echo "Testing syscalls [Passed]"
+ err=$start_err
+ else
+ echo "Testing syscalls [Failed]"
+ fi
}
set -e
--
2.53.0.1213.gd9a14994de-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v1] perf test: Fixes for check branch stack sampling
2026-04-08 6:03 [PATCH v1] perf test: Fixes for check branch stack sampling Ian Rogers
@ 2026-04-08 6:12 ` sashiko-bot
2026-04-08 6:20 ` [PATCH v2] " Ian Rogers
0 siblings, 1 reply; 8+ messages in thread
From: sashiko-bot @ 2026-04-08 6:12 UTC (permalink / raw)
To: Ian Rogers; +Cc: linux-perf-users
Sashiko AI review found 3 potential issue(s):
- [Medium] Incorrect regex in `test_user_branches()` renders the test a false negative for leaked kernel addresses.
- [Low] Contradictory test output in `test_syscall()` when skipped.
- [Low] Missing closing bracket in the failure log output of `test_kernel_branches()`.
--
commit 5cc9b2c1d3de6813cdf5dae014b695e4edf82d5d
Author: Ian Rogers <irogers@google.com>
perf test: Fixes for check branch stack sampling
This commit updates the branch stack sampling tests to filter cross-boundary
branches properly and increases the sampling duration to make syscall
sampling more reliable. It also redirects unnecessary test output to
temporary files to unclutter the logs and improves the pass/fail reporting.
> diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
> index 85233d435be63..d317ed0e063ef 100755
> --- a/tools/perf/tests/shell/test_brstack.sh
> +++ b/tools/perf/tests/shell/test_brstack.sh
[ ... ]
> @@ -73,59 +75,81 @@ test_user_branches() {
> perf script -i "$TMPDIR/perf.data" --fields brstack | \
> tr ' ' '\n' > "$TMPDIR/perf.script"
>
> - # There should be no kernel addresses with the u option, in either
> - # source or target addresses.
> - if grep -E -m1 "0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
> - echo "ERROR: Kernel address found in user mode"
> + # There should be no kernel addresses in the target with the u option.
> + if grep -q -E -m1 "^0x[0-9a-f]{16}/[89a-f][0-9a-f]{15}/" $TMPDIR/perf.script; then
The perf script output normally prefixes addresses with 0x, but this regex
appears to expect the target address immediately after the slash to lack a
0x prefix.
It also requires the source address to be exactly 16 hex digits, but user
space addresses often lack zero-padding and look like 0x400000.
Does this regex fail to match these output formats, preventing it from
detecting leaked kernel addresses in the test?
> + echo "Testing user branch stack sampling [Failed kernel address found in user mode]"
> err=1
> fi
[ ... ]
> test_kernel_branches() {
> echo "Testing that k option only includes kernel source addresses"
>
[ ... ]
> + # Look for no target addresses without top bit set
> + if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{0,15}/" $TMPDIR/perf.script; then
> + echo "Testing that k option [Failed user branches found with kernel filter"
This isn't a bug, but there is a missing closing ] bracket at the end of the
failure string.
> + err=1
> + fi
[ ... ]
> test_syscall() {
> echo "Testing syscalls"
> + start_err=$err
> + err=0
> # skip if perf doesn't have enough privileges
> - if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
> - echo "skip: not enough privileges"
> + if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
> + echo "Testing syscalls [Skipped: not enough privileges]"
> else
> perf record -o $TMPDIR/perf.data --branch-filter \
> - any_call,save_type,u,k -c 10000 -- \
> - perf bench syscall basic --loop 1000
> + any_call,save_type,u,k -c 10007 -- \
> + perf bench syscall basic --loop 8000 > "$TMPDIR/record.txt" 2>&1
> perf script -i $TMPDIR/perf.data --fields brstacksym | \
> tr ' ' '\n' > $TMPDIR/perf.script
>
> check_branches "getppid[^ ]*/SYSCALL/"
> fi
> + if [ $err -eq 0 ]; then
> + echo "Testing syscalls [Passed]"
Unlike test_kernel_branches(), there is no early return after the skip
message.
If perf record lacks privileges, will the test execution fall through to here
and incorrectly print that the test passed immediately after printing that
it was skipped?
> + err=$start_err
> + else
> + echo "Testing syscalls [Failed]"
> + fi
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260408060303.51231-1-irogers@google.com?part=1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2] perf test: Fixes for check branch stack sampling
2026-04-08 6:12 ` sashiko-bot
@ 2026-04-08 6:20 ` Ian Rogers
2026-04-08 6:34 ` sashiko-bot
2026-04-08 6:58 ` [PATCH v3] " Ian Rogers
0 siblings, 2 replies; 8+ messages in thread
From: Ian Rogers @ 2026-04-08 6:20 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, German Gomez, linux-perf-users,
linux-kernel
When filtering branch stack samples on user events they sample in user
land but may have come from the kernel. Avoid the target address being
a kernel address but allow the source to be the kernel.
When filtering branch stack samples on kernel events they sample in
kernel land but may have come from user land. Avoid the target being a
user address but allow the source to be in user land.
Increase the duration of the system call sampling test to make the
likelihood of sampling a system call higher (increased from 1000 to
8000 loops - a number found through experimentation on an Intel
Tigerlake laptop), also make the period of the event a prime number.
Put unneeded perf record output into a temporary file so that the test
output isn't cluttered. More clearly state which test is running and
the pass, fail or skipped result of the test.
These changes make the test on an Intel tigerlake laptop reliably pass
rather than reliably fail.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/shell/test_brstack.sh | 133 ++++++++++++++++---------
1 file changed, 84 insertions(+), 49 deletions(-)
diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
index 85233d435be6..51cd1dcd1855 100755
--- a/tools/perf/tests/shell/test_brstack.sh
+++ b/tools/perf/tests/shell/test_brstack.sh
@@ -40,7 +40,7 @@ is_arm64() {
check_branches() {
if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$1"; then
- echo "Branches missing $1"
+ echo "ERROR: Branches missing $1"
err=1
fi
}
@@ -48,6 +48,8 @@ check_branches() {
test_user_branches() {
echo "Testing user branch stack sampling"
+ start_err=$err
+ err=0
perf record -o "$TMPDIR/perf.data" --branch-filter any,save_type,u -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
perf script -i "$TMPDIR/perf.data" --fields brstacksym > "$TMPDIR/perf.script"
@@ -73,59 +75,81 @@ test_user_branches() {
perf script -i "$TMPDIR/perf.data" --fields brstack | \
tr ' ' '\n' > "$TMPDIR/perf.script"
- # There should be no kernel addresses with the u option, in either
- # source or target addresses.
- if grep -E -m1 "0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
- echo "ERROR: Kernel address found in user mode"
+ # There should be no kernel addresses in the target with the u option.
+ if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[89a-f][0-9a-f]{15}/" $TMPDIR/perf.script; then
+ echo "Testing user branch stack sampling [Failed kernel address found in user mode]"
err=1
fi
# some branch types are still not being tested:
# IND COND_CALL COND_RET SYSRET SERROR NO_TX
+ if [ $err -eq 0 ]; then
+ echo "Testing user branch stack sampling [Passed]"
+ err=$start_err
+ else
+ echo "Testing user branch stack sampling [Failed]"
+ fi
}
test_trap_eret_branches() {
echo "Testing trap & eret branches"
+
if ! is_arm64; then
- echo "skip: not arm64"
+ echo "Testing trap & eret branches [Skipped not arm64]"
+ return
+ fi
+ start_err=$err
+ err=0
+ perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
+ perf test -w traploop 1000
+ perf script -i $TMPDIR/perf.data --fields brstacksym | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
+ check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
+ check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
+ if [ $err -eq 0 ]; then
+ echo "Testing trap & eret branches [Passed]"
+ err=$start_err
else
- perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
- perf test -w traploop 1000
- perf script -i $TMPDIR/perf.data --fields brstacksym | \
- tr ' ' '\n' > $TMPDIR/perf.script
-
- # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
- check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
- check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
+ echo "Testing trap & eret branches [Failed]"
fi
}
test_kernel_branches() {
echo "Testing that k option only includes kernel source addresses"
- if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
- echo "skip: not enough privileges"
+ if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
+ echo "Testing that k option [Skipped not enough privileges]"
+ return
+ fi
+ start_err=$err
+ err=0
+ perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
+ perf bench syscall basic --loop 1000 > "$TMPDIR/record.txt" 2>&1
+ perf script -i $TMPDIR/perf.data --fields brstack | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ # Example of branch entries:
+ # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
+ # Source addresses come first and target address can be either
+ # userspace or kernel even with k option, as long as the source
+ # is in kernel.
+
+ # Look for source addresses with top bit set
+ if ! grep -q -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
+ echo "Testing that k option [Failed kernel branches missing]"
+ err=1
+ fi
+ # Look for no target addresses without top bit set
+ if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{0,15}/" $TMPDIR/perf.script; then
+ echo "Testing that k option [Failed user branches found with kernel filter]"
+ err=1
+ fi
+ if [ $err -eq 0 ]; then
+ echo "Testing that k option [Passed]"
+ err=$start_err
else
- perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
- perf bench syscall basic --loop 1000
- perf script -i $TMPDIR/perf.data --fields brstack | \
- tr ' ' '\n' > $TMPDIR/perf.script
-
- # Example of branch entries:
- # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
- # Source addresses come first and target address can be either
- # userspace or kernel even with k option, as long as the source
- # is in kernel.
-
- #Look for source addresses with top bit set
- if ! grep -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
- echo "ERROR: Kernel branches missing"
- err=1
- fi
- # Look for no source addresses without top bit set
- if grep -E -m1 "^0x[0-7][0-9a-f]{0,15}" $TMPDIR/perf.script; then
- echo "ERROR: User branches found with kernel filter"
- err=1
- fi
+ echo "Testing that k option [Failed]"
fi
}
@@ -136,14 +160,15 @@ test_filter() {
test_filter_expect=$2
echo "Testing branch stack filtering permutation ($test_filter_filter,$test_filter_expect)"
- perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
+ perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- \
+ ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
perf script -i "$TMPDIR/perf.data" --fields brstack > "$TMPDIR/perf.script"
# fail if we find any branch type that doesn't match any of the expected ones
# also consider UNKNOWN branch types (-)
if [ ! -s "$TMPDIR/perf.script" ]
then
- echo "Empty script output"
+ echo "Testing branch stack filtering [Failed empty script output]"
err=1
return
fi
@@ -154,26 +179,36 @@ test_filter() {
> "$TMPDIR/perf.script-filtered" || true
if [ -s "$TMPDIR/perf.script-filtered" ]
then
- echo "Unexpected branch filter in script output"
+ echo "Testing branch stack filtering [Failed unexpected branch filter]"
cat "$TMPDIR/perf.script"
err=1
return
fi
+ echo "Testing branch stack filtering [Passed]"
}
test_syscall() {
echo "Testing syscalls"
# skip if perf doesn't have enough privileges
- if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
- echo "skip: not enough privileges"
+ if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
+ echo "Testing syscalls [Skipped: not enough privileges]"
+ return
+ fi
+ start_err=$err
+ err=0
+ perf record -o $TMPDIR/perf.data --branch-filter \
+ any_call,save_type,u,k -c 10007 -- \
+ perf bench syscall basic --loop 8000 > "$TMPDIR/record.txt" 2>&1
+ perf script -i $TMPDIR/perf.data --fields brstacksym | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ check_branches "getppid[^ ]*/SYSCALL/"
+
+ if [ $err -eq 0 ]; then
+ echo "Testing syscalls [Passed]"
+ err=$start_err
else
- perf record -o $TMPDIR/perf.data --branch-filter \
- any_call,save_type,u,k -c 10000 -- \
- perf bench syscall basic --loop 1000
- perf script -i $TMPDIR/perf.data --fields brstacksym | \
- tr ' ' '\n' > $TMPDIR/perf.script
-
- check_branches "getppid[^ ]*/SYSCALL/"
+ echo "Testing syscalls [Failed]"
fi
}
set -e
--
2.53.0.1213.gd9a14994de-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2] perf test: Fixes for check branch stack sampling
2026-04-08 6:20 ` [PATCH v2] " Ian Rogers
@ 2026-04-08 6:34 ` sashiko-bot
2026-04-08 6:58 ` [PATCH v3] " Ian Rogers
1 sibling, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-04-08 6:34 UTC (permalink / raw)
To: Ian Rogers; +Cc: linux-perf-users
Sashiko AI review found 2 potential issue(s):
- [Medium] Outdated comments and output messages in `test_kernel_branches` explicitly contradict the new test logic and the commit message.
- [Medium] Missing `perf record` output redirection in `test_trap_eret_branches`.
--
commit 123631eaa14de0c5e9e90fa3e9a1064ed9d669af
Author: Ian Rogers <irogers@google.com>
perf test: Fixes for check branch stack sampling
This commit updates branch stack sampling tests to handle user/kernel
boundary crossings. It also increases the duration of the system call
sampling test for reliability, and redirects unneeded perf record output
to a temporary file.
> diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
> --- a/tools/perf/tests/shell/test_brstack.sh
> +++ b/tools/perf/tests/shell/test_brstack.sh
[ ... ]
> test_trap_eret_branches() {
> echo "Testing trap & eret branches"
> +
> if ! is_arm64; then
> - echo "skip: not arm64"
> + echo "Testing trap & eret branches [Skipped not arm64]"
> + return
> + fi
> + start_err=$err
> + err=0
> + perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
> + perf test -w traploop 1000
The commit message states that unneeded perf record output is put into a
temporary file to avoid cluttering the test output. Was the redirection
intentionally omitted for this specific test?
> + perf script -i $TMPDIR/perf.data --fields brstacksym | \
> + tr ' ' '\n' > $TMPDIR/perf.script
[ ... ]
> test_kernel_branches() {
> echo "Testing that k option only includes kernel source addresses"
Does this output message still reflect the test's intent? The commit message
states that the test now allows the source to be in user land, but this
message says it "only includes kernel source addresses".
>
> - if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
> - echo "skip: not enough privileges"
> + if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
> + echo "Testing that k option [Skipped not enough privileges]"
> + return
> + fi
> + start_err=$err
> + err=0
> + perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
> + perf bench syscall basic --loop 1000 > "$TMPDIR/record.txt" 2>&1
> + perf script -i $TMPDIR/perf.data --fields brstack | \
> + tr ' ' '\n' > $TMPDIR/perf.script
> +
> + # Example of branch entries:
> + # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
> + # Source addresses come first and target address can be either
> + # userspace or kernel even with k option, as long as the source
> + # is in kernel.
This isn't a bug, but this comment appears to contradict the new test logic.
The new test logic below correctly checks that the target address is in the
kernel rather than the source address. Should this comment be updated?
> +
> + # Look for source addresses with top bit set
> + if ! grep -q -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
> + echo "Testing that k option [Failed kernel branches missing]"
> + err=1
> + fi
> + # Look for no target addresses without top bit set
> + if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{0,15}/" $TMPDIR/perf.script; then
> + echo "Testing that k option [Failed user branches found with kernel filter]"
> + err=1
> + fi
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260408062048.61252-1-irogers@google.com?part=1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3] perf test: Fixes for check branch stack sampling
2026-04-08 6:20 ` [PATCH v2] " Ian Rogers
2026-04-08 6:34 ` sashiko-bot
@ 2026-04-08 6:58 ` Ian Rogers
2026-04-08 7:16 ` sashiko-bot
2026-04-08 12:37 ` James Clark
1 sibling, 2 replies; 8+ messages in thread
From: Ian Rogers @ 2026-04-08 6:58 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Ian Rogers,
Adrian Hunter, James Clark, German Gomez, linux-perf-users,
linux-kernel
When filtering branch stack samples on user events they sample in user
land but may have come from the kernel. Avoid the target address being
a kernel address but allow the source to be the kernel.
When filtering branch stack samples on kernel events they sample in
kernel land but may have come from user land. Avoid the target being a
user address but allow the source to be in user land.
Increase the duration of the system call sampling test to make the
likelihood of sampling a system call higher (increased from 1000 to
8000 loops - a number found through experimentation on an Intel
Tigerlake laptop), also make the period of the event a prime number.
Put unneeded perf record output into a temporary file so that the test
output isn't cluttered. More clearly state which test is running and
the pass, fail or skipped result of the test.
These changes make the test on an Intel tigerlake laptop reliably pass
rather than reliably fail.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/tests/shell/test_brstack.sh | 134 ++++++++++++++++---------
1 file changed, 84 insertions(+), 50 deletions(-)
diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
index 85233d435be6..025ed9d3d110 100755
--- a/tools/perf/tests/shell/test_brstack.sh
+++ b/tools/perf/tests/shell/test_brstack.sh
@@ -40,7 +40,7 @@ is_arm64() {
check_branches() {
if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$1"; then
- echo "Branches missing $1"
+ echo "ERROR: Branches missing $1"
err=1
fi
}
@@ -48,6 +48,8 @@ check_branches() {
test_user_branches() {
echo "Testing user branch stack sampling"
+ start_err=$err
+ err=0
perf record -o "$TMPDIR/perf.data" --branch-filter any,save_type,u -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
perf script -i "$TMPDIR/perf.data" --fields brstacksym > "$TMPDIR/perf.script"
@@ -73,59 +75,80 @@ test_user_branches() {
perf script -i "$TMPDIR/perf.data" --fields brstack | \
tr ' ' '\n' > "$TMPDIR/perf.script"
- # There should be no kernel addresses with the u option, in either
- # source or target addresses.
- if grep -E -m1 "0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
- echo "ERROR: Kernel address found in user mode"
+ # There should be no kernel addresses in the target with the u option.
+ if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[89a-f][0-9a-f]{15}/" $TMPDIR/perf.script; then
+ echo "Testing user branch stack sampling [Failed kernel address found in user mode]"
err=1
fi
# some branch types are still not being tested:
# IND COND_CALL COND_RET SYSRET SERROR NO_TX
+ if [ $err -eq 0 ]; then
+ echo "Testing user branch stack sampling [Passed]"
+ err=$start_err
+ else
+ echo "Testing user branch stack sampling [Failed]"
+ fi
}
test_trap_eret_branches() {
echo "Testing trap & eret branches"
+
if ! is_arm64; then
- echo "skip: not arm64"
+ echo "Testing trap & eret branches [Skipped not arm64]"
+ return
+ fi
+ start_err=$err
+ err=0
+ perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
+ perf test -w traploop 1000 > "$TMPDIR/record.txt" 2>&1
+ perf script -i $TMPDIR/perf.data --fields brstacksym | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
+ check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
+ check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
+ if [ $err -eq 0 ]; then
+ echo "Testing trap & eret branches [Passed]"
+ err=$start_err
else
- perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
- perf test -w traploop 1000
- perf script -i $TMPDIR/perf.data --fields brstacksym | \
- tr ' ' '\n' > $TMPDIR/perf.script
-
- # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
- check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
- check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
+ echo "Testing trap & eret branches [Failed]"
fi
}
test_kernel_branches() {
- echo "Testing that k option only includes kernel source addresses"
+ echo "Testing kernel branch sampling"
- if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
- echo "skip: not enough privileges"
+ if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
+ echo "Testing that k option [Skipped not enough privileges]"
+ return
+ fi
+ start_err=$err
+ err=0
+ perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
+ perf bench syscall basic --loop 1000 > "$TMPDIR/record.txt" 2>&1
+ perf script -i $TMPDIR/perf.data --fields brstack | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ # Example of branch entries:
+ # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
+ # Source addresses come first in user or kernel code. Next is the target
+ # address that must be in the kernel.
+
+ # Look for source addresses with top bit set
+ if ! grep -q -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
+ echo "Testing kernel branch sampling [Failed kernel branches missing]"
+ err=1
+ fi
+ # Look for no target addresses without top bit set
+ if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{0,15}/" $TMPDIR/perf.script; then
+ echo "Testing kernel branch sampling [Failed user branches found]"
+ err=1
+ fi
+ if [ $err -eq 0 ]; then
+ echo "Testing kernel branch sampling [Passed]"
+ err=$start_err
else
- perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
- perf bench syscall basic --loop 1000
- perf script -i $TMPDIR/perf.data --fields brstack | \
- tr ' ' '\n' > $TMPDIR/perf.script
-
- # Example of branch entries:
- # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
- # Source addresses come first and target address can be either
- # userspace or kernel even with k option, as long as the source
- # is in kernel.
-
- #Look for source addresses with top bit set
- if ! grep -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
- echo "ERROR: Kernel branches missing"
- err=1
- fi
- # Look for no source addresses without top bit set
- if grep -E -m1 "^0x[0-7][0-9a-f]{0,15}" $TMPDIR/perf.script; then
- echo "ERROR: User branches found with kernel filter"
- err=1
- fi
+ echo "Testing kernel branch sampling [Failed]"
fi
}
@@ -136,14 +159,15 @@ test_filter() {
test_filter_expect=$2
echo "Testing branch stack filtering permutation ($test_filter_filter,$test_filter_expect)"
- perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
+ perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- \
+ ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
perf script -i "$TMPDIR/perf.data" --fields brstack > "$TMPDIR/perf.script"
# fail if we find any branch type that doesn't match any of the expected ones
# also consider UNKNOWN branch types (-)
if [ ! -s "$TMPDIR/perf.script" ]
then
- echo "Empty script output"
+ echo "Testing branch stack filtering [Failed empty script output]"
err=1
return
fi
@@ -154,26 +178,36 @@ test_filter() {
> "$TMPDIR/perf.script-filtered" || true
if [ -s "$TMPDIR/perf.script-filtered" ]
then
- echo "Unexpected branch filter in script output"
+ echo "Testing branch stack filtering [Failed unexpected branch filter]"
cat "$TMPDIR/perf.script"
err=1
return
fi
+ echo "Testing branch stack filtering [Passed]"
}
test_syscall() {
echo "Testing syscalls"
# skip if perf doesn't have enough privileges
- if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
- echo "skip: not enough privileges"
+ if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
+ echo "Testing syscalls [Skipped: not enough privileges]"
+ return
+ fi
+ start_err=$err
+ err=0
+ perf record -o $TMPDIR/perf.data --branch-filter \
+ any_call,save_type,u,k -c 10007 -- \
+ perf bench syscall basic --loop 8000 > "$TMPDIR/record.txt" 2>&1
+ perf script -i $TMPDIR/perf.data --fields brstacksym | \
+ tr ' ' '\n' > $TMPDIR/perf.script
+
+ check_branches "getppid[^ ]*/SYSCALL/"
+
+ if [ $err -eq 0 ]; then
+ echo "Testing syscalls [Passed]"
+ err=$start_err
else
- perf record -o $TMPDIR/perf.data --branch-filter \
- any_call,save_type,u,k -c 10000 -- \
- perf bench syscall basic --loop 1000
- perf script -i $TMPDIR/perf.data --fields brstacksym | \
- tr ' ' '\n' > $TMPDIR/perf.script
-
- check_branches "getppid[^ ]*/SYSCALL/"
+ echo "Testing syscalls [Failed]"
fi
}
set -e
--
2.53.0.1213.gd9a14994de-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3] perf test: Fixes for check branch stack sampling
2026-04-08 6:58 ` [PATCH v3] " Ian Rogers
@ 2026-04-08 7:16 ` sashiko-bot
2026-04-08 7:40 ` Ian Rogers
2026-04-08 12:37 ` James Clark
1 sibling, 1 reply; 8+ messages in thread
From: sashiko-bot @ 2026-04-08 7:16 UTC (permalink / raw)
To: Ian Rogers; +Cc: linux-perf-users
Sashiko AI review found 1 potential issue(s):
- [Medium] Incomplete regex in `test_kernel_branches` misses user branch target addresses that don't start with 0-7, causing false negatives.
--
commit 81a20991ebd7cf4f6e494b9b81ee11052acea653
Author: Ian Rogers <irogers@google.com>
perf test: Fixes for check branch stack sampling
This commit fixes and expands the branch stack sampling tests in perf.
It updates user and kernel branch filters to properly check source and target
addresses, increases system call sampling duration for reliability, and cleans
up test output.
> diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
> index 85233d435be63..025ed9d3d1105 100755
> --- a/tools/perf/tests/shell/test_brstack.sh
> +++ b/tools/perf/tests/shell/test_brstack.sh
[ ... ]
> @@ -73,59 +75,80 @@ test_user_branches() {
[ ... ]
> test_kernel_branches() {
[ ... ]
> + # Look for no target addresses without top bit set
> + if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{0,15}/" $TMPDIR/perf.script; then
Does this regex reliably match all user space target addresses?
Because perf script prints brstack addresses without zero-padding, a valid
32-bit user address like 0x8048000 begins with 8 but is much shorter than
16 characters.
Since the regex strictly requires the first character after the prefix to be
between 0 and 7, it seems like it might silently miss shorter user addresses
that start with 8 through f, potentially causing the test to pass when it
should fail.
> + echo "Testing kernel branch sampling [Failed user branches found]"
> + err=1
> + fi
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260408065841.165393-1-irogers@google.com?part=1
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3] perf test: Fixes for check branch stack sampling
2026-04-08 7:16 ` sashiko-bot
@ 2026-04-08 7:40 ` Ian Rogers
0 siblings, 0 replies; 8+ messages in thread
From: Ian Rogers @ 2026-04-08 7:40 UTC (permalink / raw)
To: linux-perf-users
On Wed, Apr 8, 2026 at 12:16 AM <sashiko-bot@kernel.org> wrote:
>
> Sashiko AI review found 1 potential issue(s):
> - [Medium] Incomplete regex in `test_kernel_branches` misses user branch target addresses that don't start with 0-7, causing false negatives.
> --
>
> commit 81a20991ebd7cf4f6e494b9b81ee11052acea653
> Author: Ian Rogers <irogers@google.com>
>
> perf test: Fixes for check branch stack sampling
>
> This commit fixes and expands the branch stack sampling tests in perf.
> It updates user and kernel branch filters to properly check source and target
> addresses, increases system call sampling duration for reliability, and cleans
> up test output.
>
> > diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
> > index 85233d435be63..025ed9d3d1105 100755
> > --- a/tools/perf/tests/shell/test_brstack.sh
> > +++ b/tools/perf/tests/shell/test_brstack.sh
> [ ... ]
> > @@ -73,59 +75,80 @@ test_user_branches() {
> [ ... ]
> > test_kernel_branches() {
> [ ... ]
> > + # Look for no target addresses without top bit set
> > + if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{0,15}/" $TMPDIR/perf.script; then
>
> Does this regex reliably match all user space target addresses?
>
> Because perf script prints brstack addresses without zero-padding, a valid
> 32-bit user address like 0x8048000 begins with 8 but is much shorter than
> 16 characters.
>
> Since the regex strictly requires the first character after the prefix to be
> between 0 and 7, it seems like it might silently miss shorter user addresses
> that start with 8 through f, potentially causing the test to pass when it
> should fail.
Expanding the test to support 32-bit and 64-bit addresses in the
regular expressions is out-of-scope for this series.
Thanks,
Ian
> > + echo "Testing kernel branch sampling [Failed user branches found]"
> > + err=1
> > + fi
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260408065841.165393-1-irogers@google.com?part=1
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3] perf test: Fixes for check branch stack sampling
2026-04-08 6:58 ` [PATCH v3] " Ian Rogers
2026-04-08 7:16 ` sashiko-bot
@ 2026-04-08 12:37 ` James Clark
1 sibling, 0 replies; 8+ messages in thread
From: James Clark @ 2026-04-08 12:37 UTC (permalink / raw)
To: Ian Rogers
Cc: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Alexander Shishkin, Jiri Olsa, Adrian Hunter,
German Gomez, linux-perf-users, linux-kernel
On 08/04/2026 7:58 am, Ian Rogers wrote:
> When filtering branch stack samples on user events they sample in user
> land but may have come from the kernel. Avoid the target address being
> a kernel address but allow the source to be the kernel.
Doesn't that leak kernel pointers then? I thought they were supposed to
be semi secret to not break KASLR? With /u on Arm64 all kernel branch
addresses are filtered out or zeroed. I think it might be worth adding
an architecture condition with a different test for Intel if the
behavior is different. Otherwise we could start leaking pointers on Arm
and the test would not detect it.
>
> When filtering branch stack samples on kernel events they sample in
> kernel land but may have come from user land. Avoid the target being a
> user address but allow the source to be in user land.
>
> Increase the duration of the system call sampling test to make the
> likelihood of sampling a system call higher (increased from 1000 to
> 8000 loops - a number found through experimentation on an Intel
> Tigerlake laptop), also make the period of the event a prime number.
>
> Put unneeded perf record output into a temporary file so that the test
> output isn't cluttered. More clearly state which test is running and
> the pass, fail or skipped result of the test.
>
> These changes make the test on an Intel tigerlake laptop reliably pass
> rather than reliably fail.
>
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
> tools/perf/tests/shell/test_brstack.sh | 134 ++++++++++++++++---------
> 1 file changed, 84 insertions(+), 50 deletions(-)
>
> diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shell/test_brstack.sh
> index 85233d435be6..025ed9d3d110 100755
> --- a/tools/perf/tests/shell/test_brstack.sh
> +++ b/tools/perf/tests/shell/test_brstack.sh
> @@ -40,7 +40,7 @@ is_arm64() {
>
> check_branches() {
> if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$1"; then
> - echo "Branches missing $1"
> + echo "ERROR: Branches missing $1"
> err=1
> fi
> }
> @@ -48,6 +48,8 @@ check_branches() {
> test_user_branches() {
> echo "Testing user branch stack sampling"
>
> + start_err=$err
> + err=0
> perf record -o "$TMPDIR/perf.data" --branch-filter any,save_type,u -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
> perf script -i "$TMPDIR/perf.data" --fields brstacksym > "$TMPDIR/perf.script"
>
> @@ -73,59 +75,80 @@ test_user_branches() {
> perf script -i "$TMPDIR/perf.data" --fields brstack | \
> tr ' ' '\n' > "$TMPDIR/perf.script"
>
> - # There should be no kernel addresses with the u option, in either
> - # source or target addresses.
> - if grep -E -m1 "0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
> - echo "ERROR: Kernel address found in user mode"
> + # There should be no kernel addresses in the target with the u option.
> + if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[89a-f][0-9a-f]{15}/" $TMPDIR/perf.script; then
> + echo "Testing user branch stack sampling [Failed kernel address found in user mode]"
> err=1
> fi
> # some branch types are still not being tested:
> # IND COND_CALL COND_RET SYSRET SERROR NO_TX
> + if [ $err -eq 0 ]; then
> + echo "Testing user branch stack sampling [Passed]"
> + err=$start_err
> + else
> + echo "Testing user branch stack sampling [Failed]"
> + fi
> }
>
> test_trap_eret_branches() {
> echo "Testing trap & eret branches"
> +
> if ! is_arm64; then
> - echo "skip: not arm64"
> + echo "Testing trap & eret branches [Skipped not arm64]"
> + return
> + fi
> + start_err=$err
> + err=0
> + perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
> + perf test -w traploop 1000 > "$TMPDIR/record.txt" 2>&1
> + perf script -i $TMPDIR/perf.data --fields brstacksym | \
> + tr ' ' '\n' > $TMPDIR/perf.script
> +
> + # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
> + check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
> + check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
> + if [ $err -eq 0 ]; then
> + echo "Testing trap & eret branches [Passed]"
> + err=$start_err
> else
> - perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \
> - perf test -w traploop 1000
> - perf script -i $TMPDIR/perf.data --fields brstacksym | \
> - tr ' ' '\n' > $TMPDIR/perf.script
> -
> - # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
> - check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/"
> - check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/"
> + echo "Testing trap & eret branches [Failed]"
> fi
> }
>
> test_kernel_branches() {
> - echo "Testing that k option only includes kernel source addresses"
> + echo "Testing kernel branch sampling"
>
> - if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
> - echo "skip: not enough privileges"
> + if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
> + echo "Testing that k option [Skipped not enough privileges]"
> + return
> + fi
> + start_err=$err
> + err=0
> + perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
> + perf bench syscall basic --loop 1000 > "$TMPDIR/record.txt" 2>&1
> + perf script -i $TMPDIR/perf.data --fields brstack | \
> + tr ' ' '\n' > $TMPDIR/perf.script
> +
> + # Example of branch entries:
> + # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
> + # Source addresses come first in user or kernel code. Next is the target
> + # address that must be in the kernel.
> +
> + # Look for source addresses with top bit set
> + if ! grep -q -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
> + echo "Testing kernel branch sampling [Failed kernel branches missing]"
> + err=1
> + fi
> + # Look for no target addresses without top bit set
> + if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{0,15}/" $TMPDIR/perf.script; then
Target can be "0x0" for jumps from the kernel back to userspace with
only kernel branches turned on. Before we were only looking at source
addresses but now it looks at targets the test fails on 0x0 targets on Arm.
I suppose we could special case 0x0? It starts to get a bit horrible to
do in bash with regexes though.
The rest of the changes look good.
> + echo "Testing kernel branch sampling [Failed user branches found]"
> + err=1
> + fi
> + if [ $err -eq 0 ]; then
> + echo "Testing kernel branch sampling [Passed]"
> + err=$start_err
> else
> - perf record -o $TMPDIR/perf.data --branch-filter any,k -- \
> - perf bench syscall basic --loop 1000
> - perf script -i $TMPDIR/perf.data --fields brstack | \
> - tr ' ' '\n' > $TMPDIR/perf.script
> -
> - # Example of branch entries:
> - # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
> - # Source addresses come first and target address can be either
> - # userspace or kernel even with k option, as long as the source
> - # is in kernel.
> -
> - #Look for source addresses with top bit set
> - if ! grep -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then
> - echo "ERROR: Kernel branches missing"
> - err=1
> - fi
> - # Look for no source addresses without top bit set
> - if grep -E -m1 "^0x[0-7][0-9a-f]{0,15}" $TMPDIR/perf.script; then
> - echo "ERROR: User branches found with kernel filter"
> - err=1
> - fi
> + echo "Testing kernel branch sampling [Failed]"
> fi
> }
>
> @@ -136,14 +159,15 @@ test_filter() {
> test_filter_expect=$2
>
> echo "Testing branch stack filtering permutation ($test_filter_filter,$test_filter_expect)"
> - perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
> + perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- \
> + ${TESTPROG} > "$TMPDIR/record.txt" 2>&1
> perf script -i "$TMPDIR/perf.data" --fields brstack > "$TMPDIR/perf.script"
>
> # fail if we find any branch type that doesn't match any of the expected ones
> # also consider UNKNOWN branch types (-)
> if [ ! -s "$TMPDIR/perf.script" ]
> then
> - echo "Empty script output"
> + echo "Testing branch stack filtering [Failed empty script output]"
> err=1
> return
> fi
> @@ -154,26 +178,36 @@ test_filter() {
> > "$TMPDIR/perf.script-filtered" || true
> if [ -s "$TMPDIR/perf.script-filtered" ]
> then
> - echo "Unexpected branch filter in script output"
> + echo "Testing branch stack filtering [Failed unexpected branch filter]"
> cat "$TMPDIR/perf.script"
> err=1
> return
> fi
> + echo "Testing branch stack filtering [Passed]"
> }
>
> test_syscall() {
> echo "Testing syscalls"
> # skip if perf doesn't have enough privileges
> - if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
> - echo "skip: not enough privileges"
> + if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then
> + echo "Testing syscalls [Skipped: not enough privileges]"
> + return
> + fi
> + start_err=$err
> + err=0
> + perf record -o $TMPDIR/perf.data --branch-filter \
> + any_call,save_type,u,k -c 10007 -- \
> + perf bench syscall basic --loop 8000 > "$TMPDIR/record.txt" 2>&1
> + perf script -i $TMPDIR/perf.data --fields brstacksym | \
> + tr ' ' '\n' > $TMPDIR/perf.script
> +
> + check_branches "getppid[^ ]*/SYSCALL/"
> +
> + if [ $err -eq 0 ]; then
> + echo "Testing syscalls [Passed]"
> + err=$start_err
> else
> - perf record -o $TMPDIR/perf.data --branch-filter \
> - any_call,save_type,u,k -c 10000 -- \
> - perf bench syscall basic --loop 1000
> - perf script -i $TMPDIR/perf.data --fields brstacksym | \
> - tr ' ' '\n' > $TMPDIR/perf.script
> -
> - check_branches "getppid[^ ]*/SYSCALL/"
> + echo "Testing syscalls [Failed]"
> fi
> }
> set -e
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-04-08 12:37 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-08 6:03 [PATCH v1] perf test: Fixes for check branch stack sampling Ian Rogers
2026-04-08 6:12 ` sashiko-bot
2026-04-08 6:20 ` [PATCH v2] " Ian Rogers
2026-04-08 6:34 ` sashiko-bot
2026-04-08 6:58 ` [PATCH v3] " Ian Rogers
2026-04-08 7:16 ` sashiko-bot
2026-04-08 7:40 ` Ian Rogers
2026-04-08 12:37 ` James Clark
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox