From nobody Mon Jun 15 05:17:01 2026 Received: from mail-pf1-f202.google.com (mail-pf1-f202.google.com [209.85.210.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F12C840DFAB for ; Thu, 9 Apr 2026 00:02:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775692945; cv=none; b=kPrjvsqLc7QtDVvgnszMxsCYhJW/pwg4Wz3a3EGG1G7gO/8AjMxc14TUujj+LiBjZD+WNnVF3lgQGXlV/QU/F5he/4dC8MY22wSYZvAn4DNZ6WrDzacMAYWG3AnVvJVb1tNgJzTpv4XX5+SifqM8Z7+tMaQqbXukFUXQ7p8hAhU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775692945; c=relaxed/simple; bh=xtZT6jWz/NdPjKHL5D/uPuJbnI/ZL806oDT2ganbFLc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=JNECoY25VESLr+R7IA2+EUXfrkf3mKBU5cnpXwcp5luMOQijI19Ery7uLywyjmeTy8qRUS0d1RvXgJgjU5IQE6nkZ/r/OYcAxk0E8raVWDP0foB8OYUd/imxZ8pTSgJEEVMwkyFNT/gkzBTY+HQ6ZHc77nXRHKUWqXcm2/4D1zs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=gpxdRKAa; arc=none smtp.client-ip=209.85.210.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="gpxdRKAa" Received: by mail-pf1-f202.google.com with SMTP id d2e1a72fcca58-82c1e1a6cfbso384244b3a.0 for ; Wed, 08 Apr 2026 17:02:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1775692942; x=1776297742; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=spcypqH9luxeMnySjiMhFj/Ht5EwbIf6/33hdACP4b8=; b=gpxdRKAawW57dO54/BtDvT4/oETru2zZikqDLTvMBnoEUnLlrB6qfm3gVcQM3PEpcM O1gQGb5gEWp6MfZXf+LQVkp1lYLXNsPHfiSWhQxTwY+xPdEQSCS9wfBeSrERlJxXAEGX nVkHlk+4cao3o62pBv0/lomlj0wm9qAFfnSg08ZHGf2vFb5+6eIxT5uex0mLID/oSHOp g8z20qU7UNx+Tu4TBgOT8ph5tNdRRgCBWfSzuWsQIt+JTOWGXl4BuJUGOUnMjkGbiQ/b jr0qeqh2Jw3BYsIuwb7QhBiqOgW1XIFcdj5PY+2WZi1t7yIPo83Bik0zoaITDZGZyOt0 0WuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775692942; x=1776297742; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=spcypqH9luxeMnySjiMhFj/Ht5EwbIf6/33hdACP4b8=; b=UG5nYGaU8yTa07Lmwt93zcBEUpCA9P3/yyvyWhHz5aF/quS6oM3TKrHriGv2u6XCZb upaeZHXbidj3vHERb+KzBFoD2Q5rhfUEPDKowOBobYduATXO/H71dD1J8o7uKHCNNtJk HUdH5oQALo5cOd9f7w5ViNU03pADFbRdHVJKhARSUUwQNSTH7VxqQ6vJYwoqFsMfVK7U QsUN0XAgUpN3P4tev4A0YtbdIVhv3GxEXg0oXzGk48jDLRA0xxO8WZdyIMhTv++DmQC9 OrMGx3VT2HskbGqO8glQqL1PypH5HqJB7ehRqV3bxjz4nQMyxhnnd4zK5BYd5Q6oCPFB lSfg== X-Forwarded-Encrypted: i=1; AJvYcCUBgKu+qfuSritApfVMjqpcVfTZaRdEkD5twq346gjD8YVGtNjm4pM4BxjQaALiLi9lDiDkuEyGn+UzVao=@vger.kernel.org X-Gm-Message-State: AOJu0Ywel5F9uFqTVJ2HOgrk+aN23TBiN+h+Bh8afccYpeFUeqE7wAu4 6OeUiIrqz6K4MOY8Qt7nA+qKTIIg9a7XY3X8SSpkuv9vX69DwUvsQ2NdOsNaKjAk5zaJvbJ3Pd4 VMhifjQXhHA== X-Received: from pfbid9.prod.google.com ([2002:a05:6a00:8a89:b0:829:7bc1:d9bd]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a00:9509:b0:82c:e1a0:3453 with SMTP id d2e1a72fcca58-82dd8a92047mr1596319b3a.26.1775692941945; Wed, 08 Apr 2026 17:02:21 -0700 (PDT) Date: Wed, 8 Apr 2026 17:02:16 -0700 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.53.0.1213.gd9a14994de-goog Message-ID: <20260409000216.196083-1-irogers@google.com> Subject: [PATCH v4] perf test: Fixes for check branch stack sampling From: Ian Rogers To: james.clark@linaro.org Cc: irogers@google.com, acme@kernel.org, adrian.hunter@intel.com, alexander.shishkin@linux.intel.com, german.gomez@arm.com, jolsa@kernel.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, mingo@redhat.com, namhyung@kernel.org, peterz@infradead.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: James Clark --- v4: Address feedback from James Clark. v2,v3: Address Sashiko feedback. --- tools/perf/tests/shell/test_brstack.sh | 146 ++++++++++++++++--------- 1 file changed, 96 insertions(+), 50 deletions(-) diff --git a/tools/perf/tests/shell/test_brstack.sh b/tools/perf/tests/shel= l/test_brstack.sh index 85233d435be6..eb5837f82e39 100755 --- a/tools/perf/tests/shell/test_brstack.sh +++ b/tools/perf/tests/shell/test_brstack.sh @@ -38,9 +38,13 @@ is_arm64() { [ "$(uname -m)" =3D "aarch64" ]; } =20 +has_kaslr_bug() { + [ "$(uname -m)" !=3D "aarch64" ]; +} + 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=3D1 fi } @@ -48,6 +52,8 @@ check_branches() { test_user_branches() { echo "Testing user branch stack sampling" =20 + start_err=3D$err + err=3D0 perf record -o "$TMPDIR/perf.data" --branch-filter any,save_type,u -- ${T= ESTPROG} > "$TMPDIR/record.txt" 2>&1 perf script -i "$TMPDIR/perf.data" --fields brstacksym > "$TMPDIR/perf.sc= ript" =20 @@ -73,59 +79,88 @@ test_user_branches() { perf script -i "$TMPDIR/perf.data" --fields brstack | \ tr ' ' '\n' > "$TMPDIR/perf.script" =20 - # 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. + local regex=3D"0x[89a-f][0-9a-f]{15}" + if has_kaslr_bug; then + # If the system has a kaslr bug that may leak kernel addresses + # in the source of something like an ERET/SYSRET. Make the regex + # more specific and just check the target address is in user + # code. + regex=3D"^0x[0-9a-f]{0,16}/0x[89a-f][0-9a-f]{15}/" + fi + if grep -q -E -m1 "$regex" $TMPDIR/perf.script; then + echo "Testing user branch stack sampling [Failed kernel address found in= user mode]" err=3D1 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=3D$start_err + else + echo "Testing user branch stack sampling [Failed]" + fi } =20 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=3D$err + err=3D0 + 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.TYPE =3D=3D 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=3D$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.TYPE =3D=3D 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 } =20 test_kernel_branches() { - echo "Testing that k option only includes kernel source addresses" + echo "Testing kernel branch sampling" =20 - 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=3D$err + err=3D0 + 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=3D1 + 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]{1,15}/" $TMPDIR/perf= .script; then + echo "Testing kernel branch sampling [Failed user branches found]" + err=3D1 + fi + if [ $err -eq 0 ]; then + echo "Testing kernel branch sampling [Passed]" + err=3D$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=3D1 - 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=3D1 - fi + echo "Testing kernel branch sampling [Failed]" fi } =20 @@ -136,14 +171,15 @@ test_filter() { test_filter_expect=3D$2 =20 echo "Testing branch stack filtering permutation ($test_filter_filter,$te= st_filter_expect)" - perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,s= ave_type,u" -- ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 + perf record -o "$TMPDIR/perf.data" --branch-filter "$test_filter_filter,s= ave_type,u" -- \ + ${TESTPROG} > "$TMPDIR/record.txt" 2>&1 perf script -i "$TMPDIR/perf.data" --fields brstack > "$TMPDIR/perf.scrip= t" =20 # 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=3D1 return fi @@ -154,26 +190,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=3D1 return fi + echo "Testing branch stack filtering [Passed]" } =20 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=3D$err + err=3D0 + 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=3D$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 --=20 2.53.0.1213.gd9a14994de-goog