@@ -38,16 +38,22 @@ is_arm64() {
3838 [ " $( uname -m) " = " aarch64" ];
3939}
4040
41+ has_kaslr_bug () {
42+ [ " $( uname -m) " != " aarch64" ];
43+ }
44+
4145check_branches () {
4246 if ! tr -s ' ' ' \n' < " $TMPDIR /perf.script" | grep -E -m1 -q " $1 " ; then
43- echo " Branches missing $1 "
47+ echo " ERROR: Branches missing $1 "
4448 err=1
4549 fi
4650}
4751
4852test_user_branches () {
4953 echo " Testing user branch stack sampling"
5054
55+ start_err=$err
56+ err=0
5157 perf record -o " $TMPDIR /perf.data" --branch-filter any,save_type,u -- ${TESTPROG} > " $TMPDIR /record.txt" 2>&1
5258 perf script -i " $TMPDIR /perf.data" --fields brstacksym > " $TMPDIR /perf.script"
5359
@@ -73,59 +79,88 @@ test_user_branches() {
7379 perf script -i " $TMPDIR /perf.data" --fields brstack | \
7480 tr ' ' ' \n' > " $TMPDIR /perf.script"
7581
76- # There should be no kernel addresses with the u option, in either
77- # source or target addresses.
78- if grep -E -m1 " 0x[89a-f][0-9a-f]{15}" $TMPDIR /perf.script; then
79- echo " ERROR: Kernel address found in user mode"
82+ # There should be no kernel addresses in the target with the u option.
83+ local regex=" 0x[89a-f][0-9a-f]{15}"
84+ if has_kaslr_bug; then
85+ # If the system has a kaslr bug that may leak kernel addresses
86+ # in the source of something like an ERET/SYSRET. Make the regex
87+ # more specific and just check the target address is in user
88+ # code.
89+ regex=" ^0x[0-9a-f]{0,16}/0x[89a-f][0-9a-f]{15}/"
90+ fi
91+ if grep -q -E -m1 " $regex " $TMPDIR /perf.script; then
92+ echo " Testing user branch stack sampling [Failed kernel address found in user mode]"
8093 err=1
8194 fi
8295 # some branch types are still not being tested:
8396 # IND COND_CALL COND_RET SYSRET SERROR NO_TX
97+ if [ $err -eq 0 ]; then
98+ echo " Testing user branch stack sampling [Passed]"
99+ err=$start_err
100+ else
101+ echo " Testing user branch stack sampling [Failed]"
102+ fi
84103}
85104
86105test_trap_eret_branches () {
87106 echo " Testing trap & eret branches"
107+
88108 if ! is_arm64; then
89- echo " skip: not arm64"
109+ echo " Testing trap & eret branches [Skipped not arm64]"
110+ return
111+ fi
112+ start_err=$err
113+ err=0
114+ perf record -o $TMPDIR /perf.data --branch-filter any,save_type,u,k -- \
115+ perf test -w traploop 1000 > " $TMPDIR /record.txt" 2>&1
116+ perf script -i $TMPDIR /perf.data --fields brstacksym | \
117+ tr ' ' ' \n' > $TMPDIR /perf.script
118+
119+ # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
120+ check_branches " ^trap_bench\+[^ ]+/[^ ]/IRQ/"
121+ check_branches " ^[^ ]+/trap_bench\+[^ ]+/ERET/"
122+ if [ $err -eq 0 ]; then
123+ echo " Testing trap & eret branches [Passed]"
124+ err=$start_err
90125 else
91- perf record -o $TMPDIR /perf.data --branch-filter any,save_type,u,k -- \
92- perf test -w traploop 1000
93- perf script -i $TMPDIR /perf.data --fields brstacksym | \
94- tr ' ' ' \n' > $TMPDIR /perf.script
95-
96- # BRBINF<n>.TYPE == TRAP are mapped to PERF_BR_IRQ by the BRBE driver
97- check_branches " ^trap_bench\+[^ ]+/[^ ]/IRQ/"
98- check_branches " ^[^ ]+/trap_bench\+[^ ]+/ERET/"
126+ echo " Testing trap & eret branches [Failed]"
99127 fi
100128}
101129
102130test_kernel_branches () {
103- echo " Testing that k option only includes kernel source addresses "
131+ echo " Testing kernel branch sampling "
104132
105- if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
106- echo " skip: not enough privileges"
133+ if ! perf record --branch-filter any,k -o- -- true > " $TMPDIR /record.txt" 2>&1 ; then
134+ echo " Testing that k option [Skipped not enough privileges]"
135+ return
136+ fi
137+ start_err=$err
138+ err=0
139+ perf record -o $TMPDIR /perf.data --branch-filter any,k -- \
140+ perf bench syscall basic --loop 1000 > " $TMPDIR /record.txt" 2>&1
141+ perf script -i $TMPDIR /perf.data --fields brstack | \
142+ tr ' ' ' \n' > $TMPDIR /perf.script
143+
144+ # Example of branch entries:
145+ # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
146+ # Source addresses come first in user or kernel code. Next is the target
147+ # address that must be in the kernel.
148+
149+ # Look for source addresses with top bit set
150+ if ! grep -q -E -m1 " ^0x[89a-f][0-9a-f]{15}" $TMPDIR /perf.script; then
151+ echo " Testing kernel branch sampling [Failed kernel branches missing]"
152+ err=1
153+ fi
154+ # Look for no target addresses without top bit set
155+ if grep -q -E -m1 " ^0x[0-9a-f]{0,16}/0x[0-7][0-9a-f]{1,15}/" $TMPDIR /perf.script; then
156+ echo " Testing kernel branch sampling [Failed user branches found]"
157+ err=1
158+ fi
159+ if [ $err -eq 0 ]; then
160+ echo " Testing kernel branch sampling [Passed]"
161+ err=$start_err
107162 else
108- perf record -o $TMPDIR /perf.data --branch-filter any,k -- \
109- perf bench syscall basic --loop 1000
110- perf script -i $TMPDIR /perf.data --fields brstack | \
111- tr ' ' ' \n' > $TMPDIR /perf.script
112-
113- # Example of branch entries:
114- # "0xffffffff93bda241/0xffffffff93bda20f/M/-/-/..."
115- # Source addresses come first and target address can be either
116- # userspace or kernel even with k option, as long as the source
117- # is in kernel.
118-
119- # Look for source addresses with top bit set
120- if ! grep -E -m1 " ^0x[89a-f][0-9a-f]{15}" $TMPDIR /perf.script; then
121- echo " ERROR: Kernel branches missing"
122- err=1
123- fi
124- # Look for no source addresses without top bit set
125- if grep -E -m1 " ^0x[0-7][0-9a-f]{0,15}" $TMPDIR /perf.script; then
126- echo " ERROR: User branches found with kernel filter"
127- err=1
128- fi
163+ echo " Testing kernel branch sampling [Failed]"
129164 fi
130165}
131166
@@ -136,14 +171,15 @@ test_filter() {
136171 test_filter_expect=$2
137172
138173 echo " Testing branch stack filtering permutation ($test_filter_filter ,$test_filter_expect )"
139- perf record -o " $TMPDIR /perf.data" --branch-filter " $test_filter_filter ,save_type,u" -- ${TESTPROG} > " $TMPDIR /record.txt" 2>&1
174+ perf record -o " $TMPDIR /perf.data" --branch-filter " $test_filter_filter ,save_type,u" -- \
175+ ${TESTPROG} > " $TMPDIR /record.txt" 2>&1
140176 perf script -i " $TMPDIR /perf.data" --fields brstack > " $TMPDIR /perf.script"
141177
142178 # fail if we find any branch type that doesn't match any of the expected ones
143179 # also consider UNKNOWN branch types (-)
144180 if [ ! -s " $TMPDIR /perf.script" ]
145181 then
146- echo " Empty script output"
182+ echo " Testing branch stack filtering [Failed empty script output] "
147183 err=1
148184 return
149185 fi
@@ -154,26 +190,36 @@ test_filter() {
154190 > " $TMPDIR /perf.script-filtered" || true
155191 if [ -s " $TMPDIR /perf.script-filtered" ]
156192 then
157- echo " Unexpected branch filter in script output "
193+ echo " Testing branch stack filtering [Failed unexpected branch filter] "
158194 cat " $TMPDIR /perf.script"
159195 err=1
160196 return
161197 fi
198+ echo " Testing branch stack filtering [Passed]"
162199}
163200
164201test_syscall () {
165202 echo " Testing syscalls"
166203 # skip if perf doesn't have enough privileges
167- if ! perf record --branch-filter any,k -o- -- true > /dev/null; then
168- echo " skip: not enough privileges"
204+ if ! perf record --branch-filter any,k -o- -- true > " $TMPDIR /record.txt" 2>&1 ; then
205+ echo " Testing syscalls [Skipped: not enough privileges]"
206+ return
207+ fi
208+ start_err=$err
209+ err=0
210+ perf record -o $TMPDIR /perf.data --branch-filter \
211+ any_call,save_type,u,k -c 10007 -- \
212+ perf bench syscall basic --loop 8000 > " $TMPDIR /record.txt" 2>&1
213+ perf script -i $TMPDIR /perf.data --fields brstacksym | \
214+ tr ' ' ' \n' > $TMPDIR /perf.script
215+
216+ check_branches " getppid[^ ]*/SYSCALL/"
217+
218+ if [ $err -eq 0 ]; then
219+ echo " Testing syscalls [Passed]"
220+ err=$start_err
169221 else
170- perf record -o $TMPDIR /perf.data --branch-filter \
171- any_call,save_type,u,k -c 10000 -- \
172- perf bench syscall basic --loop 1000
173- perf script -i $TMPDIR /perf.data --fields brstacksym | \
174- tr ' ' ' \n' > $TMPDIR /perf.script
175-
176- check_branches " getppid[^ ]*/SYSCALL/"
222+ echo " Testing syscalls [Failed]"
177223 fi
178224}
179225set -e
0 commit comments