Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf test: Fixes for check branch stack sampling

When filtering branch stack samples on user events they sample in user
land but may have come from the kernel. Aarch64 avoids leaking the
kernel address for kaslr reasons but other platforms, for now,
don't. Be more permissive in allowing kernel addresses in the source
of user branch stacks.

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. Aarch64 may not
leak the user land addresses (making them 0) but other platforms
do. As the kernel address sampling implies privelege, just allow this.

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>
Reviewed-by: James Clark <james.clark@linaro.org>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
86d1095f c7fe4e56

+97 -51
+97 -51
tools/perf/tests/shell/test_brstack.sh
··· 38 38 [ "$(uname -m)" = "aarch64" ]; 39 39 } 40 40 41 + has_kaslr_bug() { 42 + [ "$(uname -m)" != "aarch64" ]; 43 + } 44 + 41 45 check_branches() { 42 46 if ! tr -s ' ' '\n' < "$TMPDIR/perf.script" | grep -E -m1 -q "$1"; then 43 - echo "Branches missing $1" 47 + echo "ERROR: Branches missing $1" 44 48 err=1 45 49 fi 46 50 } ··· 52 48 test_user_branches() { 53 49 echo "Testing user branch stack sampling" 54 50 51 + start_err=$err 52 + err=0 55 53 perf record -o "$TMPDIR/perf.data" --branch-filter any,save_type,u -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 56 54 perf script -i "$TMPDIR/perf.data" --fields brstacksym > "$TMPDIR/perf.script" 57 55 ··· 79 73 perf script -i "$TMPDIR/perf.data" --fields brstack | \ 80 74 tr ' ' '\n' > "$TMPDIR/perf.script" 81 75 82 - # There should be no kernel addresses with the u option, in either 83 - # source or target addresses. 84 - if grep -E -m1 "0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then 85 - echo "ERROR: Kernel address found in user mode" 76 + # There should be no kernel addresses in the target with the u option. 77 + local regex="0x[89a-f][0-9a-f]{15}" 78 + if has_kaslr_bug; then 79 + # If the system has a kaslr bug that may leak kernel addresses 80 + # in the source of something like an ERET/SYSRET. Make the regex 81 + # more specific and just check the target address is in user 82 + # code. 83 + regex="^0x[0-9a-f]{0,16}/0x[89a-f][0-9a-f]{15}/" 84 + fi 85 + if grep -q -E -m1 "$regex" $TMPDIR/perf.script; then 86 + echo "Testing user branch stack sampling [Failed kernel address found in user mode]" 86 87 err=1 87 88 fi 88 89 # some branch types are still not being tested: 89 90 # IND COND_CALL COND_RET SYSRET SERROR NO_TX 91 + if [ $err -eq 0 ]; then 92 + echo "Testing user branch stack sampling [Passed]" 93 + err=$start_err 94 + else 95 + echo "Testing user branch stack sampling [Failed]" 96 + fi 90 97 } 91 98 92 99 test_trap_eret_branches() { 93 100 echo "Testing trap & eret branches" 94 - if ! is_arm64; then 95 - echo "skip: not arm64" 96 - else 97 - perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \ 98 - perf test -w traploop 1000 99 - perf script -i $TMPDIR/perf.data --fields brstacksym | \ 100 - tr ' ' '\n' > $TMPDIR/perf.script 101 101 102 - # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver 103 - check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/" 104 - check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/" 102 + if ! is_arm64; then 103 + echo "Testing trap & eret branches [Skipped not arm64]" 104 + return 105 + fi 106 + start_err=$err 107 + err=0 108 + perf record -o $TMPDIR/perf.data --branch-filter any,save_type,u,k -- \ 109 + perf test -w traploop 1000 > "$TMPDIR/record.txt" 2>&1 110 + perf script -i $TMPDIR/perf.data --fields brstacksym | \ 111 + tr ' ' '\n' > $TMPDIR/perf.script 112 + 113 + # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver 114 + check_branches "^trap_bench\+[^ ]+/[^ ]/IRQ/" 115 + check_branches "^[^ ]+/trap_bench\+[^ ]+/ERET/" 116 + if [ $err -eq 0 ]; then 117 + echo "Testing trap & eret branches [Passed]" 118 + err=$start_err 119 + else 120 + echo "Testing trap & eret branches [Failed]" 105 121 fi 106 122 } 107 123 108 124 test_kernel_branches() { 109 - echo "Testing that k option only includes kernel source addresses" 125 + echo "Testing kernel branch sampling" 110 126 111 - if ! perf record --branch-filter any,k -o- -- true > /dev/null; then 112 - echo "skip: not enough privileges" 127 + if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then 128 + echo "Testing that k option [Skipped not enough privileges]" 129 + return 130 + fi 131 + start_err=$err 132 + err=0 133 + perf record -o $TMPDIR/perf.data --branch-filter any,k -- \ 134 + perf bench syscall basic --loop 1000 > "$TMPDIR/record.txt" 2>&1 135 + perf script -i $TMPDIR/perf.data --fields brstack | \ 136 + tr ' ' '\n' > $TMPDIR/perf.script 137 + 138 + # Example of branch entries: 139 + # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..." 140 + # Source addresses come first in user or kernel code. Next is the target 141 + # address that must be in the kernel. 142 + 143 + # Look for source addresses with top bit set 144 + if ! grep -q -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then 145 + echo "Testing kernel branch sampling [Failed kernel branches missing]" 146 + err=1 147 + fi 148 + # Look for no target addresses without top bit set 149 + if grep -q -E -m1 "^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{1,15}/" $TMPDIR/perf.script; then 150 + echo "Testing kernel branch sampling [Failed user branches found]" 151 + err=1 152 + fi 153 + if [ $err -eq 0 ]; then 154 + echo "Testing kernel branch sampling [Passed]" 155 + err=$start_err 113 156 else 114 - perf record -o $TMPDIR/perf.data --branch-filter any,k -- \ 115 - perf bench syscall basic --loop 1000 116 - perf script -i $TMPDIR/perf.data --fields brstack | \ 117 - tr ' ' '\n' > $TMPDIR/perf.script 118 - 119 - # Example of branch entries: 120 - # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..." 121 - # Source addresses come first and target address can be either 122 - # userspace or kernel even with k option, as long as the source 123 - # is in kernel. 124 - 125 - #Look for source addresses with top bit set 126 - if ! grep -E -m1 "^0x[89a-f][0-9a-f]{15}" $TMPDIR/perf.script; then 127 - echo "ERROR: Kernel branches missing" 128 - err=1 129 - fi 130 - # Look for no source addresses without top bit set 131 - if grep -E -m1 "^0x[0-7][0-9a-f]{0,15}" $TMPDIR/perf.script; then 132 - echo "ERROR: User branches found with kernel filter" 133 - err=1 134 - fi 157 + echo "Testing kernel branch sampling [Failed]" 135 158 fi 136 159 } 137 160 ··· 171 136 test_filter_expect=$2 172 137 173 138 echo "Testing branch stack filtering permutation ($test_filter_filter,$test_filter_expect)" 174 - perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 139 + perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,save_type,u" -- \ 140 + ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 175 141 perf script -i "$TMPDIR/perf.data" --fields brstack > "$TMPDIR/perf.script" 176 142 177 143 # fail if we find any branch type that doesn't match any of the expected ones 178 144 # also consider UNKNOWN branch types (-) 179 145 if [ ! -s "$TMPDIR/perf.script" ] 180 146 then 181 - echo "Empty script output" 147 + echo "Testing branch stack filtering [Failed empty script output]" 182 148 err=1 183 149 return 184 150 fi ··· 190 154 > "$TMPDIR/perf.script-filtered" || true 191 155 if [ -s "$TMPDIR/perf.script-filtered" ] 192 156 then 193 - echo "Unexpected branch filter in script output" 157 + echo "Testing branch stack filtering [Failed unexpected branch filter]" 194 158 cat "$TMPDIR/perf.script" 195 159 err=1 196 160 return 197 161 fi 162 + echo "Testing branch stack filtering [Passed]" 198 163 } 199 164 200 165 test_syscall() { 201 166 echo "Testing syscalls" 202 167 # skip if perf doesn't have enough privileges 203 - if ! perf record --branch-filter any,k -o- -- true > /dev/null; then 204 - echo "skip: not enough privileges" 205 - else 206 - perf record -o $TMPDIR/perf.data --branch-filter \ 207 - any_call,save_type,u,k -c 10000 -- \ 208 - perf bench syscall basic --loop 1000 209 - perf script -i $TMPDIR/perf.data --fields brstacksym | \ 210 - tr ' ' '\n' > $TMPDIR/perf.script 168 + if ! perf record --branch-filter any,k -o- -- true > "$TMPDIR/record.txt" 2>&1; then 169 + echo "Testing syscalls [Skipped: not enough privileges]" 170 + return 171 + fi 172 + start_err=$err 173 + err=0 174 + perf record -o $TMPDIR/perf.data --branch-filter \ 175 + any_call,save_type,u,k -c 10007 -- \ 176 + perf bench syscall basic --loop 8000 > "$TMPDIR/record.txt" 2>&1 177 + perf script -i $TMPDIR/perf.data --fields brstacksym | \ 178 + tr ' ' '\n' > $TMPDIR/perf.script 211 179 212 - check_branches "getppid[^ ]*/SYSCALL/" 180 + check_branches "getppid[^ ]*/SYSCALL/" 181 + 182 + if [ $err -eq 0 ]; then 183 + echo "Testing syscalls [Passed]" 184 + err=$start_err 185 + else 186 + echo "Testing syscalls [Failed]" 213 187 fi 214 188 } 215 189 set -e