Re: [PATCH v3] perf test: Fixes for check branch stack sampling
Ian Rogers <[email protected]>
| Newsgroups | org.kernel.vger.linux-perf-users,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAP-5=fWoWEa-zuzMHTP1bL7ww6zcHPQra3vt_-4TxN27C0sqtA@mail.gmail.com> |
On Sat, Aug 8, 2026 at 9:16 PM Ian Rogers <[email protected]> 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. > > 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 <[email protected]> Sorry, sent in error. This change is already merged. Thanks, Ian > --- > 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 >