From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F4E72E0B5C; Sat, 19 Sep 2026 20:41:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789850475; cv=none; b=HvpzKi3ziQ0fFN0FOs9R1o39AOhdWxlcIgSibnHm7GJZMfuRAXZIXPfqYtXXx9OLeRjZuNNSFvwR3i7iBRJ/A2tH4C/oLEpwvxOLRJY2rDp4YMxKKB9mhuvCKKV4hMvQ5CKmW17lE2B41WZ2x4bmHVXaG7c4zYklDKbOXwzVwNs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789850475; c=relaxed/simple; bh=NX5IbQBC9tvW32ED0IkNvx5/a3Fl6E4GFGAoGst6Clw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=arU4n3E4g48Y2IVKhaFS86XHBXgLh3I14Ln7skws87UsHaReBM8pwYX4NDnYCPNJzQhBpJWZOIFnMjYiHwM9JuSElGD3hQoppTJj+CyscE4SjHPzItIcgbqRRxEj8Up/wcydNR/0z485HfuqSENupEAiB28Emf3J5m2GShc5zy8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iOzxflG1; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iOzxflG1" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F2A931F00899; Sat, 19 Sep 2026 20:41:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1789850474; bh=MHL0Zm9FExTTcnRuFH4KvXCWMqeeqIFgEGVtpkRNCVk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=iOzxflG1QP4GXe4iA1fJPjSumtF73V0MQ8eMI+uLknBI07xmSPJSRqIH3BzUHDDJA xl7mveZm/4XEqMUzsKXhxJZiEM+3rCRFiihTxJ0j7TDGnHU+gpl7HTbyWrmAphEqlj DuvAlWUyHO4Qoi4etRJhwEqeu+iK0/pbdbPZs9yEgcKABVmO3OwlsXFeXP7dj5qDka np03f3khR6F0XmuuwvAaFlgiIdy3Kj93LobEhLvyZPeNyPMpUU44zUr/nHAi7PHZUU Welmy38ZUHvsCLzfMQ06NZez+GTHRgQe3gsQW3rcz7VElpvYDVjTYJPNZPK/uaJCUp RQR5XmyQJUScw== From: Arnaldo Carvalho de Melo To: Namhyung Kim Cc: Ingo Molnar , Thomas Gleixner , James Clark , Jiri Olsa , Ian Rogers , Adrian Hunter , Clark Williams , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Arnaldo Carvalho de Melo , Ravi Bangoria Subject: [PATCH 7/7] perf mem record: Use the IBS swfilt filter when available Date: Sat, 19 Sep 2026 17:40:27 -0300 Message-ID: <20260919204027.8504-8-acme@kernel.org> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260919204027.8504-1-acme@kernel.org> References: <20260919204027.8504-1-acme@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Arnaldo Carvalho de Melo IBS events with exclude_{user,kernel} bits, as used for per-thread recording when kernel samples are not allowed, are rejected by the kernel on hardware without the privilege filter, so per-thread 'perf mem record' fails on AMD: $ perf mem record -o /dev/null -- true Error: Failure to open event 'ibs_op/ldlat=0/u' on PMU 'ibs_op' which will be removed. Invalid event (ibs_op/ldlat=0/u) in per-thread mode, enable system wide with '-a'. Kernel v6.14 added swfilt, a software privilege filter exposed as the 'swfilt' format term, making those events usable per-thread: $ perf record -e ibs_op/ldlat=0,swfilt=1/ -- true Give the ibs_op memory events extra tables with the swfilt term in the event names, selected in perf_pmu__arch_init() when the PMU exposes the term, keeping the names that need system wide mode otherwise, with the knowledge that IBS needs this staying in the arch code: the generic mem-events table and name builder don't know about it. The variant is used even for records that end up without exclude bits: 'perf record' adds those bits itself when the first open fails, after the name was built, and that retry needs the term. With the term in the event name, the per-thread 'perf mem record' done by the 'data type profiling' shell test works on AMD kernels with swfilt, so the skip 29f320d2 added to it no longer triggers there, and the 'Test data symbol' shell test adjusts its event regex for the added term. Suggested-by: Namhyung Kim Suggested-by: Ravi Bangoria Assisted-by: LLM Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/arch/x86/util/mem-events.c | 24 ++++++++++++++++++++++ tools/perf/arch/x86/util/mem-events.h | 2 ++ tools/perf/arch/x86/util/pmu.c | 10 +++++++-- tools/perf/tests/shell/test_data_symbol.sh | 6 ++++-- tools/perf/util/mem-events.c | 11 ++++++---- 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/tools/perf/arch/x86/util/mem-events.c b/tools/perf/arch/x86/util/mem-events.c index b38f519020ff8c6f..2052750cd707c7e5 100644 --- a/tools/perf/arch/x86/util/mem-events.c +++ b/tools/perf/arch/x86/util/mem-events.c @@ -21,14 +21,38 @@ struct perf_mem_event perf_mem_events_intel_aux[PERF_MEM_EVENTS__MAX] = { E(NULL, NULL, NULL, false, 0), }; +/* + * IBS events with exclude_{user,kernel} bits set, as used by perf to + * record per-thread when kernel samples are not allowed, are rejected + * by the kernel on hardware without the privilege filter unless the + * swfilt software filter is used, so there are extra sets of tables + * with the swfilt term in the event names, selected in + * perf_pmu__arch_init() when the PMU exposes the term. The term is not + * conditional on the event already having exclude bits: perf record + * adds those bits itself when the first open fails with EACCES on an + * unprivileged setup, after the name was built, and that retry only + * succeeds with the term in it. + */ struct perf_mem_event perf_mem_events_amd[PERF_MEM_EVENTS__MAX] = { E(NULL, NULL, NULL, false, 0), E(NULL, NULL, NULL, false, 0), E("mem-ldst", "%s//", NULL, false, 0), }; +struct perf_mem_event perf_mem_events_amd_swfilt[PERF_MEM_EVENTS__MAX] = { + E(NULL, NULL, NULL, false, 0), + E(NULL, NULL, NULL, false, 0), + E("mem-ldst", "%s/swfilt=1/", NULL, false, 0), +}; + struct perf_mem_event perf_mem_events_amd_ldlat[PERF_MEM_EVENTS__MAX] = { E(NULL, NULL, NULL, false, 0), E(NULL, NULL, NULL, false, 0), E("mem-ldst", "%s/ldlat=%u/", NULL, true, 0), }; + +struct perf_mem_event perf_mem_events_amd_ldlat_swfilt[PERF_MEM_EVENTS__MAX] = { + E(NULL, NULL, NULL, false, 0), + E(NULL, NULL, NULL, false, 0), + E("mem-ldst", "%s/ldlat=%u,swfilt=1/", NULL, true, 0), +}; diff --git a/tools/perf/arch/x86/util/mem-events.h b/tools/perf/arch/x86/util/mem-events.h index 11e09a256f5bb084..f707de38037017c1 100644 --- a/tools/perf/arch/x86/util/mem-events.h +++ b/tools/perf/arch/x86/util/mem-events.h @@ -6,6 +6,8 @@ extern struct perf_mem_event perf_mem_events_intel[PERF_MEM_EVENTS__MAX]; extern struct perf_mem_event perf_mem_events_intel_aux[PERF_MEM_EVENTS__MAX]; extern struct perf_mem_event perf_mem_events_amd[PERF_MEM_EVENTS__MAX]; +extern struct perf_mem_event perf_mem_events_amd_swfilt[PERF_MEM_EVENTS__MAX]; extern struct perf_mem_event perf_mem_events_amd_ldlat[PERF_MEM_EVENTS__MAX]; +extern struct perf_mem_event perf_mem_events_amd_ldlat_swfilt[PERF_MEM_EVENTS__MAX]; #endif /* _X86_MEM_EVENTS_H */ diff --git a/tools/perf/arch/x86/util/pmu.c b/tools/perf/arch/x86/util/pmu.c index 2c24ef3140da5e9b..fd4491fda117e51a 100644 --- a/tools/perf/arch/x86/util/pmu.c +++ b/tools/perf/arch/x86/util/pmu.c @@ -333,6 +333,7 @@ static void uncore_cha_imc_adjust_cpumask_for_snc(struct perf_pmu *pmu, bool cha void perf_pmu__arch_init(struct perf_pmu *pmu) { struct perf_pmu_caps *ldlat_cap; + bool swfilt_format; if (!strcmp(pmu->name, INTEL_PT_PMU_NAME)) { pmu->auxtrace = true; @@ -348,7 +349,10 @@ void perf_pmu__arch_init(struct perf_pmu *pmu) if (strcmp(pmu->name, "ibs_op")) return; - pmu->mem_events = perf_mem_events_amd; + swfilt_format = perf_pmu__has_format(pmu, "swfilt"); + pmu->mem_events = swfilt_format ? + perf_mem_events_amd_swfilt : + perf_mem_events_amd; if (!perf_pmu__caps_parse(pmu)) return; @@ -358,7 +362,9 @@ void perf_pmu__arch_init(struct perf_pmu *pmu) return; perf_mem_events__loads_ldlat = 0; - pmu->mem_events = perf_mem_events_amd_ldlat; + pmu->mem_events = swfilt_format ? + perf_mem_events_amd_ldlat_swfilt : + perf_mem_events_amd_ldlat; } else { if (pmu->is_core) { if (perf_pmu__have_event(pmu, "mem-loads-aux")) diff --git a/tools/perf/tests/shell/test_data_symbol.sh b/tools/perf/tests/shell/test_data_symbol.sh index d61b5659a46d9a77..52c837fddb639595 100755 --- a/tools/perf/tests/shell/test_data_symbol.sh +++ b/tools/perf/tests/shell/test_data_symbol.sh @@ -65,15 +65,17 @@ if (($is_amd >= 1)); then # --ldlat on AMD: # o Zen4 and earlier uarch does not support ldlat # o Even on supported platforms, it's disabled (--ldlat=0) by default. + # o Kernels with the swfilt term add it even when ldlat is not + # supported, so only check ldlat when the term is present. ldlat=${BASH_REMATCH[1]} - if [[ -n $ldlat ]]; then + if [[ $ldlat == *ldlat=* ]]; then if ! [[ "$ldlat" =~ ldlat=0 ]]; then echo "ERROR: ldlat not initialized to 0?" exit 1 fi mem_events="$(perf mem record -v --ldlat=150 -e list 2>&1)" - if ! [[ "$mem_events" =~ ^mem-ldst.*ibs_op/ldlat=150/.*available ]]; then + if ! [[ "$mem_events" =~ ^mem-ldst.*ibs_op/ldlat=150[,/].*available ]]; then echo "ERROR: --ldlat not honored?" exit 1 fi diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c index 0b49fce251fcc184..0b07011939d7d7c3 100644 --- a/tools/perf/util/mem-events.c +++ b/tools/perf/util/mem-events.c @@ -82,6 +82,7 @@ static const char *perf_pmu__mem_events_name(struct perf_pmu *pmu, int i, char *buf, size_t buf_size) { struct perf_mem_event *e; + const char *name; if (i >= PERF_MEM_EVENTS__MAX || !pmu) return NULL; @@ -90,24 +91,26 @@ static const char *perf_pmu__mem_events_name(struct perf_pmu *pmu, int i, if (!e || !e->name) return NULL; + name = e->name; + if (i == PERF_MEM_EVENTS__LOAD || i == PERF_MEM_EVENTS__LOAD_STORE) { if (e->ldlat) { if (!e->aux_event) { /* ARM and Most of Intel */ scnprintf(buf, buf_size, - e->name, pmu->name, + name, pmu->name, perf_mem_events__loads_ldlat); } else { /* Intel with mem-loads-aux event */ scnprintf(buf, buf_size, - e->name, pmu->name, pmu->name, + name, pmu->name, pmu->name, perf_mem_events__loads_ldlat); } } else { if (!e->aux_event) { /* AMD and POWER */ scnprintf(buf, buf_size, - e->name, pmu->name); + name, pmu->name); } else { return NULL; } @@ -117,7 +120,7 @@ static const char *perf_pmu__mem_events_name(struct perf_pmu *pmu, int i, if (i == PERF_MEM_EVENTS__STORE) { scnprintf(buf, buf_size, - e->name, pmu->name); + name, pmu->name); return buf; } -- 2.53.0