linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] perf/amd/ibs: Introduce load/store SW filter
@ 2025-05-29 12:34 Ravi Bangoria
  2025-05-29 12:34 ` [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU Ravi Bangoria
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Ravi Bangoria @ 2025-05-29 12:34 UTC (permalink / raw)
  To: Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim
  Cc: Ravi Bangoria, Ingo Molnar, Stephane Eranian, Ian Rogers,
	Kan Liang, James Clark, Leo Yan, Joe Mario, linux-kernel,
	linux-perf-users, Santosh Shukla, Ananth Narayan, Sandipan Das

Since current IBS OP PMU does not have the capability to tag only load/
stores instructions, tools like perf mem/c2c ends up recording lots of
unwanted samples. See for example [1]. All these unwanted samples are:

1) Passed from kernel to userspace
2) Stored in the perf.data file
3) Processed every time while running perf mem/c2c report
4) Skews perf mem/c2c overhead computations

So, better to get rid of them early in the IBS NMI handler itself.
Although SW filter is not an ideal solution, it's better compared to
no filter at all.

[1]: https://lore.kernel.org/r/aBTyYv_yXCPkn2d0@x1

Patches are prepated on perf-tools-next/perf-tools-next (4d9b5146f0d9).


Ravi Bangoria (4):
  perf/amd/ibs: Add load/store SW filters to IBS OP PMU
  perf mem/c2c amd: Wire IBS OP PMU load/store SW filter
  perf test amd: Add IBS load/store swfilt tests
  perf doc amd: Update perf-amd-ibs man page

 arch/x86/events/amd/ibs.c                  | 73 ++++++++++++++++++++--
 include/linux/perf_event.h                 | 14 +++++
 tools/perf/Documentation/perf-amd-ibs.txt  | 72 +++++++++++++++------
 tools/perf/arch/x86/util/mem-events.c      | 12 ++++
 tools/perf/arch/x86/util/mem-events.h      |  2 +
 tools/perf/arch/x86/util/pmu.c             | 17 +++--
 tools/perf/tests/shell/amd-ibs-swfilt.sh   | 26 ++++++++
 tools/perf/tests/shell/test_data_symbol.sh | 26 ++++----
 tools/perf/util/mem-events.c               |  2 +-
 9 files changed, 205 insertions(+), 39 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU
  2025-05-29 12:34 [PATCH 0/4] perf/amd/ibs: Introduce load/store SW filter Ravi Bangoria
@ 2025-05-29 12:34 ` Ravi Bangoria
  2025-05-31  7:53   ` Ingo Molnar
  2025-05-29 12:34 ` [PATCH 2/4] perf mem/c2c amd: Wire IBS OP PMU load/store SW filter Ravi Bangoria
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Ravi Bangoria @ 2025-05-29 12:34 UTC (permalink / raw)
  To: Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim
  Cc: Ravi Bangoria, Ingo Molnar, Stephane Eranian, Ian Rogers,
	Kan Liang, James Clark, Leo Yan, Joe Mario, linux-kernel,
	linux-perf-users, Santosh Shukla, Ananth Narayan, Sandipan Das

Since current IBS OP PMU does not have the capability to tag only load/
stores instructions, tools like perf mem/c2c ends up recording lots of
unwanted samples. So, introduce a load/store software filter in the IBS
OP PMU:

  ibs_op/swfilt=1,ldop=1/         --> Only load samples
  ibs_op/swfilt=1,stop=1/         --> Only store samples
  ibs_op/swfilt=1,ldop=1,stop=1/  --> Load OR store samples

Other HW or SW filters in combination with this ldst filter are logical
AND. For ex:

  ibs_op/swfilt=1,ldop=1,stop=1/u is
  "privilege == userspace && (ldop == 1 || stop == 1)"

  ibs_op/swfilt=1,ldop=1,stop=1,l3missonly=1/ is
  "l3missonly == 1 && (ldop == 1 || stop == 1)"

An alternate approach is mem_op BPF filter:

  perf record --filter "mem_op == load || mem_op == store" ...

However, there are few issues with it:
o BPF filter is called after preparing entire perf sample. If the sample
  does not satisfy the filtering criteria, all the efforts of preparing
  perf sample gets wasted.
o BPF filter requires root privilege.

Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
---
 arch/x86/events/amd/ibs.c  | 73 +++++++++++++++++++++++++++++++++++---
 include/linux/perf_event.h | 14 ++++++++
 2 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
index 0252b7ea8bca..d18ce6464b27 100644
--- a/arch/x86/events/amd/ibs.c
+++ b/arch/x86/events/amd/ibs.c
@@ -31,6 +31,10 @@ static u32 ibs_caps;
 /* attr.config2 */
 #define IBS_SW_FILTER_MASK	1
 
+/* attr.config1 */
+#define IBS_LDOP_FILTER_MASK	(1UL << 12)
+#define IBS_STOP_FILTER_MASK	(1UL << 13)
+
 /*
  * IBS states:
  *
@@ -308,6 +312,11 @@ static int perf_ibs_init(struct perf_event *event)
 	     event->attr.exclude_hv))
 		return -EINVAL;
 
+	if (!(event->attr.config2 & IBS_SW_FILTER_MASK) &&
+	    (event->attr.config1 & (IBS_LDOP_FILTER_MASK |
+				    IBS_STOP_FILTER_MASK)))
+		return -EINVAL;
+
 	ret = validate_group(event);
 	if (ret)
 		return ret;
@@ -624,6 +633,10 @@ static struct attribute_group empty_caps_group = {
 PMU_FORMAT_ATTR(rand_en,	"config:57");
 PMU_FORMAT_ATTR(cnt_ctl,	"config:19");
 PMU_FORMAT_ATTR(swfilt,		"config2:0");
+PMU_FORMAT_ATTR(ldop,		"config1:12"); /* IBS_LDOP_FILTER_MASK */
+PMU_FORMAT_ATTR(stop,		"config1:13"); /* IBS_STOP_FILTER_MASK */
+PMU_CAP_ATTR(swfilt_ldst,	"1");
+
 PMU_EVENT_ATTR_STRING(l3missonly, fetch_l3missonly, "config:59");
 PMU_EVENT_ATTR_STRING(l3missonly, op_l3missonly, "config:16");
 PMU_EVENT_ATTR_STRING(ldlat, ibs_op_ldlat_format, "config1:0-11");
@@ -724,6 +737,8 @@ cnt_ctl_is_visible(struct kobject *kobj, struct attribute *attr, int i)
 
 static struct attribute *op_attrs[] = {
 	&format_attr_swfilt.attr,
+	&format_attr_ldop.attr,
+	&format_attr_stop.attr,
 	NULL,
 };
 
@@ -737,11 +752,21 @@ static struct attribute *op_l3missonly_attrs[] = {
 	NULL,
 };
 
+static struct attribute *op_attrs_caps[] = {
+	&cap_attr_swfilt_ldst.attr,
+	NULL,
+};
+
 static struct attribute_group group_op_formats = {
 	.name = "format",
 	.attrs = op_attrs,
 };
 
+static struct attribute_group group_op_caps = {
+	.name = "caps",
+	.attrs = op_attrs_caps,
+};
+
 static struct attribute *ibs_op_ldlat_format_attrs[] = {
 	&ibs_op_ldlat_format.attr.attr,
 	NULL,
@@ -761,7 +786,7 @@ static struct attribute_group group_op_l3missonly = {
 
 static const struct attribute_group *op_attr_groups[] = {
 	&group_op_formats,
-	&empty_caps_group,
+	&group_op_caps,
 	NULL,
 };
 
@@ -1148,13 +1173,23 @@ static bool perf_ibs_is_mem_sample_type(struct perf_ibs *perf_ibs,
 			      PERF_SAMPLE_PHYS_ADDR);
 }
 
+static bool perf_ibs_ld_st_filter_event(struct perf_ibs *perf_ibs,
+					struct perf_event *event)
+{
+	return perf_ibs == &perf_ibs_op &&
+	       (event->attr.config2 & IBS_SW_FILTER_MASK) &&
+	       (event->attr.config1 & (IBS_LDOP_FILTER_MASK |
+				       IBS_STOP_FILTER_MASK));
+}
+
 static int perf_ibs_get_offset_max(struct perf_ibs *perf_ibs,
 				   struct perf_event *event,
 				   int check_rip)
 {
 	if (event->attr.sample_type & PERF_SAMPLE_RAW ||
 	    perf_ibs_is_mem_sample_type(perf_ibs, event) ||
-	    perf_ibs_ldlat_event(perf_ibs, event))
+	    perf_ibs_ldlat_event(perf_ibs, event) ||
+	    perf_ibs_ld_st_filter_event(perf_ibs, event))
 		return perf_ibs->offset_max;
 	else if (check_rip)
 		return 3;
@@ -1189,6 +1224,32 @@ static bool perf_ibs_is_kernel_br_target(struct perf_event *event,
 			op_data.op_brn_ret && kernel_ip(br_target));
 }
 
+/*
+ * ibs_op/swfilt=1,ldop=1/         --> Only load samples
+ * ibs_op/swfilt=1,stop=1/         --> Only store samples
+ * ibs_op/swfilt=1,ldop=1,stop=1/  --> Load OR store samples
+ */
+static bool perf_ibs_ld_st_filter(struct perf_event *event,
+				  struct perf_ibs_data *ibs_data)
+{
+	union ibs_op_data3 op_data3;
+
+	if (!(event->attr.config1 & (IBS_LDOP_FILTER_MASK |
+				     IBS_STOP_FILTER_MASK))) {
+		return false;
+	}
+
+	op_data3.val = ibs_data->regs[ibs_op_msr_idx(MSR_AMD64_IBSOPDATA3)];
+
+	if ((event->attr.config1 & IBS_LDOP_FILTER_MASK) && op_data3.ld_op)
+		return false;
+
+	if ((event->attr.config1 & IBS_STOP_FILTER_MASK) && op_data3.st_op)
+		return false;
+
+	return true;
+}
+
 static bool perf_ibs_swfilt_discard(struct perf_ibs *perf_ibs, struct perf_event *event,
 				    struct pt_regs *regs, struct perf_ibs_data *ibs_data,
 				    int br_target_idx)
@@ -1196,9 +1257,12 @@ static bool perf_ibs_swfilt_discard(struct perf_ibs *perf_ibs, struct perf_event
 	if (perf_exclude_event(event, regs))
 		return true;
 
-	if (perf_ibs != &perf_ibs_op || !event->attr.exclude_kernel)
+	if (perf_ibs != &perf_ibs_op)
 		return false;
 
+	if (!event->attr.exclude_kernel)
+		goto ldst_filter;
+
 	if (perf_ibs_is_kernel_data_addr(event, ibs_data))
 		return true;
 
@@ -1206,7 +1270,8 @@ static bool perf_ibs_swfilt_discard(struct perf_ibs *perf_ibs, struct perf_event
 	    perf_ibs_is_kernel_br_target(event, ibs_data, br_target_idx))
 		return true;
 
-	return false;
+ldst_filter:
+	return perf_ibs_ld_st_filter(event, ibs_data);
 }
 
 static void perf_ibs_phyaddr_clear(struct perf_ibs *perf_ibs,
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 0069ba6866a4..dedb92d5cd61 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1998,6 +1998,20 @@ _name##_show(struct device *dev,					\
 									\
 static struct device_attribute format_attr_##_name = __ATTR_RO(_name)
 
+#define PMU_CAP_ATTR_SHOW(_name, _cap)					\
+static ssize_t								\
+_name##_show(struct device *dev, struct device_attribute *attr,		\
+	     char *page)						\
+{									\
+	BUILD_BUG_ON(sizeof(_cap) >= PAGE_SIZE);			\
+	return sprintf(page, _cap "\n");				\
+}
+
+#define PMU_CAP_ATTR(_name, _cap)					\
+	PMU_CAP_ATTR_SHOW(_name, _cap)					\
+									\
+static struct device_attribute cap_attr_##_name = __ATTR_RO(_name)
+
 /* Performance counter hotplug functions */
 #ifdef CONFIG_PERF_EVENTS
 int perf_event_init_cpu(unsigned int cpu);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/4] perf mem/c2c amd: Wire IBS OP PMU load/store SW filter
  2025-05-29 12:34 [PATCH 0/4] perf/amd/ibs: Introduce load/store SW filter Ravi Bangoria
  2025-05-29 12:34 ` [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU Ravi Bangoria
@ 2025-05-29 12:34 ` Ravi Bangoria
  2025-05-29 12:34 ` [PATCH 3/4] perf test amd: Add IBS load/store swfilt tests Ravi Bangoria
  2025-05-29 12:34 ` [PATCH 4/4] perf doc amd: Update perf-amd-ibs man page Ravi Bangoria
  3 siblings, 0 replies; 8+ messages in thread
From: Ravi Bangoria @ 2025-05-29 12:34 UTC (permalink / raw)
  To: Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim
  Cc: Ravi Bangoria, Ingo Molnar, Stephane Eranian, Ian Rogers,
	Kan Liang, James Clark, Leo Yan, Joe Mario, linux-kernel,
	linux-perf-users, Santosh Shukla, Ananth Narayan, Sandipan Das

Currently, perf mem/c2c tools on AMD records ibs_op// pmu event, which
has no inherent load/store filtering capability. But with the addition
of a SW based load/store filtering capability in IBS OP PMU, perf mem/
c2c tools can now record load-only, store-only and load-store-only
events. Wire them accordingly.

Before:
  $ perf mem record -v -e list
  mem-ldst     ibs_op//          : available

After:
  $ perf mem record -v -e list
  mem-load     ibs_op/swfilt=1,ldop=1/  : available
  mem-store    ibs_op/swfilt=1,stop=1/  : available
  mem-ldst     ibs_op/swfilt=1,ldop=1,stop=1/: available

Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
---
 tools/perf/arch/x86/util/mem-events.c      | 12 ++++++++++
 tools/perf/arch/x86/util/mem-events.h      |  2 ++
 tools/perf/arch/x86/util/pmu.c             | 17 +++++++++-----
 tools/perf/tests/shell/test_data_symbol.sh | 26 +++++++++++++---------
 tools/perf/util/mem-events.c               |  2 +-
 5 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/tools/perf/arch/x86/util/mem-events.c b/tools/perf/arch/x86/util/mem-events.c
index b38f519020ff..0a034317b55c 100644
--- a/tools/perf/arch/x86/util/mem-events.c
+++ b/tools/perf/arch/x86/util/mem-events.c
@@ -32,3 +32,15 @@ struct perf_mem_event perf_mem_events_amd_ldlat[PERF_MEM_EVENTS__MAX] = {
 	E(NULL,		NULL,		NULL,	false,	0),
 	E("mem-ldst",	"%s/ldlat=%u/",	NULL,	true,	0),
 };
+
+struct perf_mem_event perf_mem_events_amd_swfilt[PERF_MEM_EVENTS__MAX] = {
+	E("mem-load",	"%s/swfilt=1,ldop=1/",		NULL,	false,	0),
+	E("mem-store",	"%s/swfilt=1,stop=1/",		NULL,	false,	0),
+	E("mem-ldst",	"%s/swfilt=1,ldop=1,stop=1/",	NULL,	false,	0),
+};
+
+struct perf_mem_event perf_mem_events_amd_ldlat_swfilt[PERF_MEM_EVENTS__MAX] = {
+	E("mem-load",	"%s/ldlat=%u,swfilt=1,ldop=1/",		NULL,	true,	0),
+	E("mem-store",	"%s/swfilt=1,stop=1/",			NULL,	false,	0),
+	E("mem-ldst",	"%s/ldlat=%u,swfilt=1,ldop=1,stop=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 11e09a256f5b..bde1e51f639c 100644
--- a/tools/perf/arch/x86/util/mem-events.h
+++ b/tools/perf/arch/x86/util/mem-events.h
@@ -7,5 +7,7 @@ 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_ldlat[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_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 58113482654b..34f25ec9cca6 100644
--- a/tools/perf/arch/x86/util/pmu.c
+++ b/tools/perf/arch/x86/util/pmu.c
@@ -271,7 +271,7 @@ static void gnr_uncore_cha_imc_adjust_cpumask_for_snc(struct perf_pmu *pmu, bool
 
 void perf_pmu__arch_init(struct perf_pmu *pmu)
 {
-	struct perf_pmu_caps *ldlat_cap;
+	struct perf_pmu_caps *ldlat_cap, *swfilt_ldst_cap;
 
 #ifdef HAVE_AUXTRACE_SUPPORT
 	if (!strcmp(pmu->name, INTEL_PT_PMU_NAME)) {
@@ -295,11 +295,18 @@ void perf_pmu__arch_init(struct perf_pmu *pmu)
 			return;
 
 		ldlat_cap = perf_pmu__get_cap(pmu, "ldlat");
-		if (!ldlat_cap || strcmp(ldlat_cap->value, "1"))
-			return;
+		swfilt_ldst_cap = perf_pmu__get_cap(pmu, "swfilt_ldst");
+
+		if (ldlat_cap && !strcmp(ldlat_cap->value, "1")) {
+			perf_mem_events__loads_ldlat = 0;
 
-		perf_mem_events__loads_ldlat = 0;
-		pmu->mem_events = perf_mem_events_amd_ldlat;
+			if (swfilt_ldst_cap && !strcmp(swfilt_ldst_cap->value, "1"))
+				pmu->mem_events = perf_mem_events_amd_ldlat_swfilt;
+			else
+				pmu->mem_events = perf_mem_events_amd_ldlat;
+		} else if (swfilt_ldst_cap && !strcmp(swfilt_ldst_cap->value, "1")) {
+			pmu->mem_events = perf_mem_events_amd_swfilt;
+		}
 	} 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 d61b5659a46d..e2156c9a4bc9 100755
--- a/tools/perf/tests/shell/test_data_symbol.sh
+++ b/tools/perf/tests/shell/test_data_symbol.sh
@@ -57,7 +57,7 @@ echo "Recording workload..."
 is_amd=$(grep -E -c 'vendor_id.*AuthenticAMD' /proc/cpuinfo)
 if (($is_amd >= 1)); then
 	mem_events="$(perf mem record -v -e list 2>&1)"
-	if ! [[ "$mem_events" =~ ^mem\-ldst.*ibs_op/(.*)/.*available ]]; then
+	if ! [[ "$mem_events" =~ mem\-ldst.*ibs_op/(.*)/.*available ]]; then
 		echo "ERROR: mem-ldst event is not matching"
 		exit 1
 	fi
@@ -65,18 +65,22 @@ 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.
-	ldlat=${BASH_REMATCH[1]}
-	if [[ -n $ldlat ]]; then
-		if ! [[ "$ldlat" =~ ldlat=0 ]]; then
-			echo "ERROR: ldlat not initialized to 0?"
-			exit 1
+	format=${BASH_REMATCH[1]}
+	if [[ $format =~ ldlat=(\d*) ]]; then
+		ldlat=${BASH_REMATCH[1]}
+		if [[ -n $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
+				echo "ERROR: --ldlat not honored?"
+				exit 1
+			fi
 		fi
 
-		mem_events="$(perf mem record -v --ldlat=150 -e list 2>&1)"
-		if ! [[ "$mem_events" =~ ^mem-ldst.*ibs_op/ldlat=150/.*available ]]; then
-			echo "ERROR: --ldlat not honored?"
-			exit 1
-		fi
 	fi
 
 	# perf mem/c2c internally uses IBS PMU on AMD CPU which doesn't
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index 80b3069427bc..24afdd12bed2 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -93,7 +93,7 @@ static const char *perf_pmu__mem_events_name(struct perf_pmu *pmu, int i,
 	if (i == PERF_MEM_EVENTS__LOAD || i == PERF_MEM_EVENTS__LOAD_STORE) {
 		if (e->ldlat) {
 			if (!e->aux_event) {
-				/* ARM and Most of Intel */
+				/* ARM, AMD and Most of Intel */
 				scnprintf(buf, buf_size,
 					  e->name, pmu->name,
 					  perf_mem_events__loads_ldlat);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/4] perf test amd: Add IBS load/store swfilt tests
  2025-05-29 12:34 [PATCH 0/4] perf/amd/ibs: Introduce load/store SW filter Ravi Bangoria
  2025-05-29 12:34 ` [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU Ravi Bangoria
  2025-05-29 12:34 ` [PATCH 2/4] perf mem/c2c amd: Wire IBS OP PMU load/store SW filter Ravi Bangoria
@ 2025-05-29 12:34 ` Ravi Bangoria
  2025-05-29 12:34 ` [PATCH 4/4] perf doc amd: Update perf-amd-ibs man page Ravi Bangoria
  3 siblings, 0 replies; 8+ messages in thread
From: Ravi Bangoria @ 2025-05-29 12:34 UTC (permalink / raw)
  To: Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim
  Cc: Ravi Bangoria, Ingo Molnar, Stephane Eranian, Ian Rogers,
	Kan Liang, James Clark, Leo Yan, Joe Mario, linux-kernel,
	linux-perf-users, Santosh Shukla, Ananth Narayan, Sandipan Das

Add basic sanity tests for load-only, store-only and load-store-only
sampling with IBS OP PMU.

Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
---
 tools/perf/tests/shell/amd-ibs-swfilt.sh | 26 ++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/tools/perf/tests/shell/amd-ibs-swfilt.sh b/tools/perf/tests/shell/amd-ibs-swfilt.sh
index 83937aa687cc..bc052a36a9b4 100755
--- a/tools/perf/tests/shell/amd-ibs-swfilt.sh
+++ b/tools/perf/tests/shell/amd-ibs-swfilt.sh
@@ -65,3 +65,29 @@ if [ ${user_sample} -ne 0 ]; then
     echo "[FAIL] unexpected user samples: " ${user_sample}
     exit 1
 fi
+
+echo "test load/store swfilt"
+
+# load/store swfil
+if [ -f /sys/bus/event_source/devices/ibs_op/caps/swfilt_ldst ]; then
+	# test load only sampling
+	non_load_sample=$(perf record -e ibs_op/swfilt=1,ldop=1/ --raw-samples -o- perf test -w sqrtloop | perf script -D -i- | grep -c "LdOp 0")
+	if [ ${non_load_sample} -ne 0 ]; then
+		echo "[FAIL] unexpected non-load samples: " ${non_load_sample}
+		exit 1;
+	fi
+
+	# test store only sampling
+	non_store_sample=$(perf record -e ibs_op/swfilt=1,stop=1/ --raw-samples -o- perf test -w sqrtloop | perf script -D -i- | grep -c "StOp 0")
+	if [ ${non_store_sample} -ne 0 ]; then
+		echo "[FAIL] unexpected non-store samples: " ${non_store_sample}
+		exit 1;
+	fi
+
+	# test load/store only sampling
+	non_load_store_sample=$(perf record -e ibs_op/swfilt=1,ldop=1,stop=1/ --raw-samples -o- perf test -w sqrtloop | perf script -D -i- | grep -c "LdOp 0 StOp 0")
+	if [ ${non_load_store_sample} -ne 0 ]; then
+		echo "[FAIL] unexpected non-load/store samples: " ${non_load_store_sample}
+		exit 1;
+	fi
+fi
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/4] perf doc amd: Update perf-amd-ibs man page
  2025-05-29 12:34 [PATCH 0/4] perf/amd/ibs: Introduce load/store SW filter Ravi Bangoria
                   ` (2 preceding siblings ...)
  2025-05-29 12:34 ` [PATCH 3/4] perf test amd: Add IBS load/store swfilt tests Ravi Bangoria
@ 2025-05-29 12:34 ` Ravi Bangoria
  3 siblings, 0 replies; 8+ messages in thread
From: Ravi Bangoria @ 2025-05-29 12:34 UTC (permalink / raw)
  To: Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim
  Cc: Ravi Bangoria, Ingo Molnar, Stephane Eranian, Ian Rogers,
	Kan Liang, James Clark, Leo Yan, Joe Mario, linux-kernel,
	linux-perf-users, Santosh Shukla, Ananth Narayan, Sandipan Das

o Document software filtering capabilities provided by IBS kernel
  driver.
o After recent perf-mem hist updates [1], the perf-mem example command
  in the perf-amd-ibs man page renders output differently. Unfortunately,
  there is no way to get the same aggregated output now. So use alternate
  command that can aggregate and show data at the command level.

[1]: https://lore.kernel.org/r/20250430205548.789750-1-namhyung@kernel.org

Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com>
---
 tools/perf/Documentation/perf-amd-ibs.txt | 72 +++++++++++++++++------
 1 file changed, 54 insertions(+), 18 deletions(-)

diff --git a/tools/perf/Documentation/perf-amd-ibs.txt b/tools/perf/Documentation/perf-amd-ibs.txt
index 55f80beae037..a543a68e3c94 100644
--- a/tools/perf/Documentation/perf-amd-ibs.txt
+++ b/tools/perf/Documentation/perf-amd-ibs.txt
@@ -33,9 +33,6 @@ if IBS is supported by the hardware and kernel.
 IBS Op PMU supports two events: cycles and micro ops. IBS Fetch PMU supports
 one event: fetch ops.
 
-IBS PMUs do not have user/kernel filtering capability and thus it requires
-CAP_SYS_ADMIN or CAP_PERFMON privilege.
-
 IBS VS. REGULAR CORE PMU
 ------------------------
 
@@ -160,6 +157,38 @@ System-wide profile, fetch ops event, sampling period: 100000, Random enable
 
 etc.
 
+IBS SW FILTERING
+----------------
+
+IBS PMU driver provides few additional software filtering capabilities. When
+supported, kernel exposes config format through the following files:
+
+  /sys/bus/event_source/devices/ibs_fetch/format/swfilt
+  /sys/bus/event_source/devices/ibs_op/format/swfilt
+
+1. Privilege (user/kernel) filtering. IBS PMUs do not support privilege
+filtering in hardware so IBS driver supports it as a software filter.
+
+  ibs_op/swfilt=1/u               --> Only usermode samples
+  ibs_op/swfilt=1/k               --> Only kernelmode samples
+  ibs_fetch/swfilt=1/u            --> Only usermode samples
+  ibs_fetch/swfilt=1/k            --> Only kernelmode samples
+
+  Privilege filtering is always available when "swfilt" is supported.
+  So, kernel does not expose any separate PMU capability for this.
+
+2. Load/Store sampling. IBS OP PMU do not support load/store filtering in
+hardware, so IBS driver supports it as a software filter.
+
+  ibs_op/swfilt=1,ldop=1/         --> Only load samples
+  ibs_op/swfilt=1,stop=1/         --> Only store samples
+  ibs_op/swfilt=1,ldop=1,stop=1/  --> Load OR store samples
+
+  Kernel creates following PMU capability file when load/store software
+  filtering is supported:
+
+  /sys/bus/event_source/devices/ibs_op/caps/swfilt_ldst
+
 PERF MEM AND PERF C2C
 ---------------------
 
@@ -173,21 +202,28 @@ Below is a simple example of the perf mem tool.
 A normal perf mem report output will provide detailed memory access profile.
 However, it can also be aggregated based on output fields. For example:
 
-	# perf mem report -F mem,sample,snoop
-	Samples: 3M of event 'ibs_op//', Event count (approx.): 23524876
-	Memory access                                 Samples  Snoop
-	N/A                                           1903343  N/A
-	L1 hit                                        1056754  N/A
-	L2 hit                                          75231  N/A
-	L3 hit                                           9496  HitM
-	L3 hit                                           2270  N/A
-	RAM hit                                          8710  N/A
-	Remote node, same socket RAM hit                 3241  N/A
-	Remote core, same node Any cache hit             1572  HitM
-	Remote core, same node Any cache hit              514  N/A
-	Remote node, same socket Any cache hit           1216  HitM
-	Remote node, same socket Any cache hit            350  N/A
-	Uncached hit                                       18  N/A
+	# perf mem report -s comm,mem -H --stdio
+	     Overhead       Samples  Command / Memory access
+	  .........................  ..........................................
+	    66.46%        471728     cc1
+	       34.70%          1393     RAM hit
+	       10.42%           370     Remote node, same socket RAM hit
+		6.73%         10239     L2 hit
+		5.84%        293953     N/A
+		3.26%        163803     L1 hit
+		3.16%          1796     L3 hit
+		1.29%            95     Remote core, same node Any cache hit
+		1.06%            73     Remote node, same socket Any cache hit
+		0.00%             6     Uncached hit
+	     9.45%         44994     sh
+		2.60%           131     RAM hit
+		2.21%           219     Remote core, same node Any cache hit
+		1.89%           190     Remote node, same socket Any cache hit
+		1.02%            52     Remote node, same socket RAM hit
+		0.72%           785     L2 hit
+		0.60%         30149     N/A
+		0.27%         13340     L1 hit
+             ...
 
 Please refer to their man page for more detail.
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU
  2025-05-29 12:34 ` [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU Ravi Bangoria
@ 2025-05-31  7:53   ` Ingo Molnar
  2025-06-03  6:52     ` Namhyung Kim
  0 siblings, 1 reply; 8+ messages in thread
From: Ingo Molnar @ 2025-05-31  7:53 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
	Ingo Molnar, Stephane Eranian, Ian Rogers, Kan Liang, James Clark,
	Leo Yan, Joe Mario, linux-kernel, linux-perf-users,
	Santosh Shukla, Ananth Narayan, Sandipan Das


* Ravi Bangoria <ravi.bangoria@amd.com> wrote:

> Since current IBS OP PMU does not have the capability to tag only load/
> stores instructions, tools like perf mem/c2c ends up recording lots of
> unwanted samples. So, introduce a load/store software filter in the IBS
> OP PMU:
> 
>   ibs_op/swfilt=1,ldop=1/         --> Only load samples
>   ibs_op/swfilt=1,stop=1/         --> Only store samples
>   ibs_op/swfilt=1,ldop=1,stop=1/  --> Load OR store samples
> 
> Other HW or SW filters in combination with this ldst filter are logical
> AND. For ex:
> 
>   ibs_op/swfilt=1,ldop=1,stop=1/u is
>   "privilege == userspace && (ldop == 1 || stop == 1)"
> 
>   ibs_op/swfilt=1,ldop=1,stop=1,l3missonly=1/ is
>   "l3missonly == 1 && (ldop == 1 || stop == 1)"

No objections, but:

> An alternate approach is mem_op BPF filter:
> 
>   perf record --filter "mem_op == load || mem_op == store" ...
> 
> However, there are few issues with it:
> o BPF filter is called after preparing entire perf sample. If the sample
>   does not satisfy the filtering criteria, all the efforts of preparing
>   perf sample gets wasted.

Could we add an 'early' BPF callback point as well, to fast-discard 
samples?

> o BPF filter requires root privilege.

Could we add 'built-in', 'safe' BPF scripts that are specifically 
prepared for perf events filtering purposes, that can be toggled by 
non-root users as well? These could be toggled by tooling via sysfs or 
so, or even via the perf syscall if that turns out to be the better 
approach.

It would give us the flexibility and extensibility of BPF, combining it 
with the safety & compatibility of the filtering functionality being 
provided by the kernel.

It could be provided in the form of a BPF program crypto signature 
registry of upstream-approved BPF scripts for perf BPF callback(s),
or so. (While root could load any BPF script.)

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU
  2025-05-31  7:53   ` Ingo Molnar
@ 2025-06-03  6:52     ` Namhyung Kim
  2025-06-10  5:12       ` Ravi Bangoria
  0 siblings, 1 reply; 8+ messages in thread
From: Namhyung Kim @ 2025-06-03  6:52 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Ravi Bangoria, Peter Zijlstra, Arnaldo Carvalho de Melo,
	Ingo Molnar, Stephane Eranian, Ian Rogers, Kan Liang, James Clark,
	Leo Yan, Joe Mario, linux-kernel, linux-perf-users,
	Santosh Shukla, Ananth Narayan, Sandipan Das, bpf

Hello,

+ bpf list

On Sat, May 31, 2025 at 09:53:44AM +0200, Ingo Molnar wrote:
> 
> * Ravi Bangoria <ravi.bangoria@amd.com> wrote:
> 
> > Since current IBS OP PMU does not have the capability to tag only load/
> > stores instructions, tools like perf mem/c2c ends up recording lots of
> > unwanted samples. So, introduce a load/store software filter in the IBS
> > OP PMU:
> > 
> >   ibs_op/swfilt=1,ldop=1/         --> Only load samples
> >   ibs_op/swfilt=1,stop=1/         --> Only store samples
> >   ibs_op/swfilt=1,ldop=1,stop=1/  --> Load OR store samples
> > 
> > Other HW or SW filters in combination with this ldst filter are logical
> > AND. For ex:
> > 
> >   ibs_op/swfilt=1,ldop=1,stop=1/u is
> >   "privilege == userspace && (ldop == 1 || stop == 1)"
> > 
> >   ibs_op/swfilt=1,ldop=1,stop=1,l3missonly=1/ is
> >   "l3missonly == 1 && (ldop == 1 || stop == 1)"
> 
> No objections, but:
> 
> > An alternate approach is mem_op BPF filter:
> > 
> >   perf record --filter "mem_op == load || mem_op == store" ...
> > 
> > However, there are few issues with it:
> > o BPF filter is called after preparing entire perf sample. If the sample
> >   does not satisfy the filtering criteria, all the efforts of preparing
> >   perf sample gets wasted.
> 
> Could we add an 'early' BPF callback point as well, to fast-discard 
> samples?

I guess that would require a new BPF program type than PERF_EVENT and
handle driver-specific details.

> 
> > o BPF filter requires root privilege.
> 
> Could we add 'built-in', 'safe' BPF scripts that are specifically 
> prepared for perf events filtering purposes, that can be toggled by 
> non-root users as well? These could be toggled by tooling via sysfs or 
> so, or even via the perf syscall if that turns out to be the better 
> approach.

We have BPF filter framework in the perf tools and it can be run as
normal user.  But root user should load and pin the BPF program prior
to use like below.

  $ sudo perf record --setup-filter pin

  $ perf record -d -e ibs_op/swfilt/u --filter 'mem_op == load' ...

Thanks,
Namhyung

> 
> It would give us the flexibility and extensibility of BPF, combining it 
> with the safety & compatibility of the filtering functionality being 
> provided by the kernel.
> 
> It could be provided in the form of a BPF program crypto signature 
> registry of upstream-approved BPF scripts for perf BPF callback(s),
> or so. (While root could load any BPF script.)
> 
> Thanks,
> 
> 	Ingo

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU
  2025-06-03  6:52     ` Namhyung Kim
@ 2025-06-10  5:12       ` Ravi Bangoria
  0 siblings, 0 replies; 8+ messages in thread
From: Ravi Bangoria @ 2025-06-10  5:12 UTC (permalink / raw)
  To: Ingo Molnar, Namhyung Kim
  Cc: Peter Zijlstra, Arnaldo Carvalho de Melo, Ingo Molnar,
	Stephane Eranian, Ian Rogers, Kan Liang, James Clark, Leo Yan,
	Joe Mario, linux-kernel, linux-perf-users, Santosh Shukla,
	Ananth Narayan, Sandipan Das, bpf, Ravi Bangoria

Hi Ingo, Namhyung,

>>> An alternate approach is mem_op BPF filter:
>>>
>>>   perf record --filter "mem_op == load || mem_op == store" ...
>>>
>>> However, there are few issues with it:
>>> o BPF filter is called after preparing entire perf sample. If the sample
>>>   does not satisfy the filtering criteria, all the efforts of preparing
>>>   perf sample gets wasted.
>>
>> Could we add an 'early' BPF callback point as well, to fast-discard 
>> samples?
> 
> I guess that would require a new BPF program type than PERF_EVENT and
> handle driver-specific details.

Right.

>>> o BPF filter requires root privilege.
>>
>> Could we add 'built-in', 'safe' BPF scripts that are specifically 
>> prepared for perf events filtering purposes, that can be toggled by 
>> non-root users as well? These could be toggled by tooling via sysfs or 
>> so, or even via the perf syscall if that turns out to be the better 
>> approach.
> 
> We have BPF filter framework in the perf tools and it can be run as
> normal user.  But root user should load and pin the BPF program prior
> to use like below.
> 
>   $ sudo perf record --setup-filter pin
> 
>   $ perf record -d -e ibs_op/swfilt/u --filter 'mem_op == load' ...

Thanks Namhyung.

Ingo, Do you feel the idea of perf specific 'safe' BPF script is still
worth pursuing despite similar functionality is already provided by
--setup-filter?

Thanks,
Ravi

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2025-06-10  5:12 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-29 12:34 [PATCH 0/4] perf/amd/ibs: Introduce load/store SW filter Ravi Bangoria
2025-05-29 12:34 ` [PATCH 1/4] perf/amd/ibs: Add load/store SW filters to IBS OP PMU Ravi Bangoria
2025-05-31  7:53   ` Ingo Molnar
2025-06-03  6:52     ` Namhyung Kim
2025-06-10  5:12       ` Ravi Bangoria
2025-05-29 12:34 ` [PATCH 2/4] perf mem/c2c amd: Wire IBS OP PMU load/store SW filter Ravi Bangoria
2025-05-29 12:34 ` [PATCH 3/4] perf test amd: Add IBS load/store swfilt tests Ravi Bangoria
2025-05-29 12:34 ` [PATCH 4/4] perf doc amd: Update perf-amd-ibs man page Ravi Bangoria

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).