* [PATCH v2 0/5] perf/arm_cspmu: Preparatory patches for NVIDIA T410 PMU
@ 2025-09-23 0:18 Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get Besar Wicaksono
` (4 more replies)
0 siblings, 5 replies; 15+ messages in thread
From: Besar Wicaksono @ 2025-09-23 0:18 UTC (permalink / raw)
To: will, robin.murphy, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, suzuki.poulose,
mark.rutland, treding, jonathanh, vsethi, rwiley, sdonthineni,
Besar Wicaksono
This series contains initial patches before adding support for upcoming
NVIDIA T410 PMUs.
Thanks,
Besar
Changes from v1:
* Add Reviewed-by from Ilkka for patch #3 and #4
* Drop change to [1/5] on making arm_cspmu_apmt_node public
* Replace it with new API arm_cspmu_acpi_dev_get
Thanks to Ilkka and Robin for the review comments.
v1: https://lore.kernel.org/all/20250812233411.1694012-1-bwicaksono@nvidia.com/T/#t
Besar Wicaksono (5):
perf/arm_cspmu: Add arm_cspmu_acpi_dev_get
perf/arm_cspmu: Add callback to reset filter config
perf/arm_cspmu: Add pmpidr support
perf/arm_cspmu: nvidia: Add revision id matching
perf/arm_cspmu: nvidia: Add pmevfiltr2 support
drivers/perf/arm_cspmu/arm_cspmu.c | 70 +++++++++-
drivers/perf/arm_cspmu/arm_cspmu.h | 48 ++++++-
drivers/perf/arm_cspmu/nvidia_cspmu.c | 194 +++++++++++++++++++-------
3 files changed, 253 insertions(+), 59 deletions(-)
--
2.50.1
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get
2025-09-23 0:18 [PATCH v2 0/5] perf/arm_cspmu: Preparatory patches for NVIDIA T410 PMU Besar Wicaksono
@ 2025-09-23 0:18 ` Besar Wicaksono
2025-09-24 20:05 ` Ilkka Koskinen
2025-09-25 8:30 ` Suzuki K Poulose
2025-09-23 0:18 ` [PATCH v2 2/5] perf/arm_cspmu: Add callback to reset filter config Besar Wicaksono
` (3 subsequent siblings)
4 siblings, 2 replies; 15+ messages in thread
From: Besar Wicaksono @ 2025-09-23 0:18 UTC (permalink / raw)
To: will, robin.murphy, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, suzuki.poulose,
mark.rutland, treding, jonathanh, vsethi, rwiley, sdonthineni,
Besar Wicaksono
Add interface to get ACPI device associated with the
PMU. This ACPI device may contain additional properties
not covered by the standard properties.
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
drivers/perf/arm_cspmu/arm_cspmu.c | 22 ++++++++++++++++++++++
drivers/perf/arm_cspmu/arm_cspmu.h | 9 +++++++++
2 files changed, 31 insertions(+)
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index efa9b229e701..75b2d80f783e 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -1090,6 +1090,28 @@ static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
return 0;
}
+
+struct acpi_device *arm_cspmu_acpi_dev_get(const struct arm_cspmu *cspmu)
+{
+ char hid[16];
+ char uid[16];
+ struct acpi_device *adev;
+ const struct acpi_apmt_node *apmt_node;
+
+ apmt_node = arm_cspmu_apmt_node(cspmu->dev);
+ if (!apmt_node || apmt_node->type != ACPI_APMT_NODE_TYPE_ACPI)
+ return NULL;
+
+ memset(hid, 0, sizeof(hid));
+ memset(uid, 0, sizeof(uid));
+
+ memcpy(hid, &apmt_node->inst_primary, sizeof(apmt_node->inst_primary));
+ sprintf(uid, "%u", apmt_node->inst_secondary);
+
+ adev = acpi_dev_get_first_match_dev(hid, uid, -1);
+ return adev;
+}
+EXPORT_SYMBOL_GPL(arm_cspmu_acpi_dev_get);
#else
static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
{
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index 19684b76bd96..9c5f11f98acd 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -8,6 +8,7 @@
#ifndef __ARM_CSPMU_H__
#define __ARM_CSPMU_H__
+#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/cpumask.h>
#include <linux/device.h>
@@ -222,4 +223,12 @@ int arm_cspmu_impl_register(const struct arm_cspmu_impl_match *impl_match);
/* Unregister vendor backend. */
void arm_cspmu_impl_unregister(const struct arm_cspmu_impl_match *impl_match);
+#if defined(CONFIG_ACPI)
+/**
+ * Get ACPI device associated with the PMU.
+ * The caller is responsible for calling acpi_dev_put() on the returned device.
+ */
+struct acpi_device *arm_cspmu_acpi_dev_get(const struct arm_cspmu *cspmu);
+#endif
+
#endif /* __ARM_CSPMU_H__ */
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 2/5] perf/arm_cspmu: Add callback to reset filter config
2025-09-23 0:18 [PATCH v2 0/5] perf/arm_cspmu: Preparatory patches for NVIDIA T410 PMU Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get Besar Wicaksono
@ 2025-09-23 0:18 ` Besar Wicaksono
2025-09-24 20:06 ` Ilkka Koskinen
2025-09-25 9:23 ` Suzuki K Poulose
2025-09-23 0:18 ` [PATCH v2 3/5] perf/arm_cspmu: Add pmpidr support Besar Wicaksono
` (2 subsequent siblings)
4 siblings, 2 replies; 15+ messages in thread
From: Besar Wicaksono @ 2025-09-23 0:18 UTC (permalink / raw)
To: will, robin.murphy, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, suzuki.poulose,
mark.rutland, treding, jonathanh, vsethi, rwiley, sdonthineni,
Besar Wicaksono
Implementer may need to reset a filter config when
stopping a counter, thus adding a callback for this.
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
drivers/perf/arm_cspmu/arm_cspmu.c | 4 ++++
drivers/perf/arm_cspmu/arm_cspmu.h | 4 +++-
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index 75b2d80f783e..43770c8ecd14 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -815,6 +815,10 @@ static void arm_cspmu_stop(struct perf_event *event, int pmu_flags)
return;
arm_cspmu_disable_counter(cspmu, hwc->idx);
+
+ if (cspmu->impl.ops.reset_ev_filter)
+ cspmu->impl.ops.reset_ev_filter(cspmu, event);
+
arm_cspmu_event_update(event);
hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index 9c5f11f98acd..21d7e6e2f2da 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -153,11 +153,13 @@ struct arm_cspmu_impl_ops {
bool (*is_cycle_counter_event)(const struct perf_event *event);
/* Decode event type/id from configs */
u32 (*event_type)(const struct perf_event *event);
- /* Set event filters */
+ /* Set/reset event filters */
void (*set_cc_filter)(struct arm_cspmu *cspmu,
const struct perf_event *event);
void (*set_ev_filter)(struct arm_cspmu *cspmu,
const struct perf_event *event);
+ void (*reset_ev_filter)(struct arm_cspmu *cspmu,
+ const struct perf_event *event);
/* Implementation specific event validation */
int (*validate_event)(struct arm_cspmu *cspmu,
struct perf_event *event);
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 3/5] perf/arm_cspmu: Add pmpidr support
2025-09-23 0:18 [PATCH v2 0/5] perf/arm_cspmu: Preparatory patches for NVIDIA T410 PMU Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 2/5] perf/arm_cspmu: Add callback to reset filter config Besar Wicaksono
@ 2025-09-23 0:18 ` Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 4/5] perf/arm_cspmu: nvidia: Add revision id matching Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support Besar Wicaksono
4 siblings, 0 replies; 15+ messages in thread
From: Besar Wicaksono @ 2025-09-23 0:18 UTC (permalink / raw)
To: will, robin.murphy, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, suzuki.poulose,
mark.rutland, treding, jonathanh, vsethi, rwiley, sdonthineni,
Besar Wicaksono
The PMIIDR value is composed by the values in PMPIDR registers.
We can use PMPIDR registers as alternative for device
identification for systems that do not implement PMIIDR.
Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
drivers/perf/arm_cspmu/arm_cspmu.c | 44 +++++++++++++++++++++++++--
drivers/perf/arm_cspmu/arm_cspmu.h | 35 +++++++++++++++++++--
drivers/perf/arm_cspmu/nvidia_cspmu.c | 2 +-
3 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
index 43770c8ecd14..d0ec1eb8272f 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.c
+++ b/drivers/perf/arm_cspmu/arm_cspmu.c
@@ -322,14 +322,14 @@ static struct arm_cspmu_impl_match impl_match[] = {
{
.module_name = "nvidia_cspmu",
.pmiidr_val = ARM_CSPMU_IMPL_ID_NVIDIA,
- .pmiidr_mask = ARM_CSPMU_PMIIDR_IMPLEMENTER,
+ .pmiidr_mask = PMIIDR_IMPLEMENTER,
.module = NULL,
.impl_init_ops = NULL,
},
{
.module_name = "ampere_cspmu",
.pmiidr_val = ARM_CSPMU_IMPL_ID_AMPERE,
- .pmiidr_mask = ARM_CSPMU_PMIIDR_IMPLEMENTER,
+ .pmiidr_mask = PMIIDR_IMPLEMENTER,
.module = NULL,
.impl_init_ops = NULL,
},
@@ -351,6 +351,44 @@ static struct arm_cspmu_impl_match *arm_cspmu_impl_match_get(u32 pmiidr)
return NULL;
}
+static u32 arm_cspmu_get_pmiidr(struct arm_cspmu *cspmu)
+{
+ u32 pmiidr, pmpidr;
+
+ pmiidr = readl(cspmu->base0 + PMIIDR);
+
+ if (pmiidr != 0)
+ return pmiidr;
+
+ /* Construct PMIIDR value from PMPIDRs. */
+
+ pmpidr = readl(cspmu->base0 + PMPIDR0);
+ pmiidr |= FIELD_PREP(PMIIDR_PRODUCTID_PART_0,
+ FIELD_GET(PMPIDR0_PART_0, pmpidr));
+
+ pmpidr = readl(cspmu->base0 + PMPIDR1);
+ pmiidr |= FIELD_PREP(PMIIDR_PRODUCTID_PART_1,
+ FIELD_GET(PMPIDR1_PART_1, pmpidr));
+ pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_0,
+ FIELD_GET(PMPIDR1_DES_0, pmpidr));
+
+ pmpidr = readl(cspmu->base0 + PMPIDR2);
+ pmiidr |= FIELD_PREP(PMIIDR_VARIANT,
+ FIELD_GET(PMPIDR2_REVISION, pmpidr));
+ pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_1,
+ FIELD_GET(PMPIDR2_DES_1, pmpidr));
+
+ pmpidr = readl(cspmu->base0 + PMPIDR3);
+ pmiidr |= FIELD_PREP(PMIIDR_REVISION,
+ FIELD_GET(PMPIDR3_REVAND, pmpidr));
+
+ pmpidr = readl(cspmu->base0 + PMPIDR4);
+ pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_2,
+ FIELD_GET(PMPIDR4_DES_2, pmpidr));
+
+ return pmiidr;
+}
+
#define DEFAULT_IMPL_OP(name) .name = arm_cspmu_##name
static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
@@ -361,7 +399,7 @@ static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu)
/* Start with a default PMU implementation */
cspmu->impl.module = THIS_MODULE;
- cspmu->impl.pmiidr = readl(cspmu->base0 + PMIIDR);
+ cspmu->impl.pmiidr = arm_cspmu_get_pmiidr(cspmu);
cspmu->impl.ops = (struct arm_cspmu_impl_ops) {
DEFAULT_IMPL_OP(get_event_attrs),
DEFAULT_IMPL_OP(get_format_attrs),
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index 21d7e6e2f2da..16799d596e9a 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -87,6 +87,11 @@
#define PMCFGR 0xE00
#define PMCR 0xE04
#define PMIIDR 0xE08
+#define PMPIDR0 0xFE0
+#define PMPIDR1 0xFE4
+#define PMPIDR2 0xFE8
+#define PMPIDR3 0xFEC
+#define PMPIDR4 0xFD0
/* PMCFGR register field */
#define PMCFGR_NCG GENMASK(31, 28)
@@ -116,8 +121,34 @@
#define PMCR_E BIT(0)
/* PMIIDR register field */
-#define ARM_CSPMU_PMIIDR_IMPLEMENTER GENMASK(11, 0)
-#define ARM_CSPMU_PMIIDR_PRODUCTID GENMASK(31, 20)
+#define PMIIDR_IMPLEMENTER GENMASK(11, 0)
+#define PMIIDR_IMPLEMENTER_DES_0 GENMASK(3, 0)
+#define PMIIDR_IMPLEMENTER_DES_1 GENMASK(6, 4)
+#define PMIIDR_IMPLEMENTER_DES_2 GENMASK(11, 8)
+#define PMIIDR_REVISION GENMASK(15, 12)
+#define PMIIDR_VARIANT GENMASK(19, 16)
+#define PMIIDR_PRODUCTID GENMASK(31, 20)
+#define PMIIDR_PRODUCTID_PART_0 GENMASK(27, 20)
+#define PMIIDR_PRODUCTID_PART_1 GENMASK(31, 28)
+
+/* PMPIDR0 register field */
+#define PMPIDR0_PART_0 GENMASK(7, 0)
+
+/* PMPIDR1 register field */
+#define PMPIDR1_DES_0 GENMASK(7, 4)
+#define PMPIDR1_PART_1 GENMASK(3, 0)
+
+/* PMPIDR2 register field */
+#define PMPIDR2_REVISION GENMASK(7, 4)
+#define PMPIDR2_DES_1 GENMASK(2, 0)
+
+/* PMPIDR3 register field */
+#define PMPIDR3_REVAND GENMASK(7, 4)
+#define PMPIDR3_CMOD GENMASK(3, 0)
+
+/* PMPIDR4 register field */
+#define PMPIDR4_SIZE GENMASK(7, 4)
+#define PMPIDR4_DES_2 GENMASK(3, 0)
/* JEDEC-assigned JEP106 identification code */
#define ARM_CSPMU_IMPL_ID_NVIDIA 0x36B
diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
index dc6d4e3e2a1b..b6cec351a142 100644
--- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
+++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
@@ -322,7 +322,7 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
if (!ctx)
return -ENOMEM;
- prodid = FIELD_GET(ARM_CSPMU_PMIIDR_PRODUCTID, cspmu->impl.pmiidr);
+ prodid = FIELD_GET(PMIIDR_PRODUCTID, cspmu->impl.pmiidr);
/* Find matching PMU. */
for (; match->prodid; match++) {
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 4/5] perf/arm_cspmu: nvidia: Add revision id matching
2025-09-23 0:18 [PATCH v2 0/5] perf/arm_cspmu: Preparatory patches for NVIDIA T410 PMU Besar Wicaksono
` (2 preceding siblings ...)
2025-09-23 0:18 ` [PATCH v2 3/5] perf/arm_cspmu: Add pmpidr support Besar Wicaksono
@ 2025-09-23 0:18 ` Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support Besar Wicaksono
4 siblings, 0 replies; 15+ messages in thread
From: Besar Wicaksono @ 2025-09-23 0:18 UTC (permalink / raw)
To: will, robin.murphy, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, suzuki.poulose,
mark.rutland, treding, jonathanh, vsethi, rwiley, sdonthineni,
Besar Wicaksono
Distinguish NVIDIA devices by revision and variant bits
in PMIIDR register in addition to product id.
Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
drivers/perf/arm_cspmu/nvidia_cspmu.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
index b6cec351a142..ac91dc46501d 100644
--- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
+++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
@@ -23,7 +23,7 @@
#define NV_GENERIC_FILTER_ID_MASK GENMASK_ULL(31, 0)
-#define NV_PRODID_MASK GENMASK(31, 0)
+#define NV_PRODID_MASK (PMIIDR_PRODUCTID | PMIIDR_VARIANT | PMIIDR_REVISION)
#define NV_FORMAT_NAME_GENERIC 0
@@ -220,7 +220,7 @@ struct nv_cspmu_match {
static const struct nv_cspmu_match nv_cspmu_match[] = {
{
- .prodid = 0x103,
+ .prodid = 0x10300000,
.prodid_mask = NV_PRODID_MASK,
.filter_mask = NV_PCIE_FILTER_ID_MASK,
.filter_default_val = NV_PCIE_FILTER_ID_MASK,
@@ -230,7 +230,7 @@ static const struct nv_cspmu_match nv_cspmu_match[] = {
.format_attr = pcie_pmu_format_attrs
},
{
- .prodid = 0x104,
+ .prodid = 0x10400000,
.prodid_mask = NV_PRODID_MASK,
.filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
.filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
@@ -240,7 +240,7 @@ static const struct nv_cspmu_match nv_cspmu_match[] = {
.format_attr = nvlink_c2c_pmu_format_attrs
},
{
- .prodid = 0x105,
+ .prodid = 0x10500000,
.prodid_mask = NV_PRODID_MASK,
.filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
.filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
@@ -250,7 +250,7 @@ static const struct nv_cspmu_match nv_cspmu_match[] = {
.format_attr = nvlink_c2c_pmu_format_attrs
},
{
- .prodid = 0x106,
+ .prodid = 0x10600000,
.prodid_mask = NV_PRODID_MASK,
.filter_mask = NV_CNVL_FILTER_ID_MASK,
.filter_default_val = NV_CNVL_FILTER_ID_MASK,
@@ -260,7 +260,7 @@ static const struct nv_cspmu_match nv_cspmu_match[] = {
.format_attr = cnvlink_pmu_format_attrs
},
{
- .prodid = 0x2CF,
+ .prodid = 0x2CF00000,
.prodid_mask = NV_PRODID_MASK,
.filter_mask = 0x0,
.filter_default_val = 0x0,
@@ -312,7 +312,6 @@ static char *nv_cspmu_format_name(const struct arm_cspmu *cspmu,
static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
{
- u32 prodid;
struct nv_cspmu_ctx *ctx;
struct device *dev = cspmu->dev;
struct arm_cspmu_impl_ops *impl_ops = &cspmu->impl.ops;
@@ -322,13 +321,12 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
if (!ctx)
return -ENOMEM;
- prodid = FIELD_GET(PMIIDR_PRODUCTID, cspmu->impl.pmiidr);
-
/* Find matching PMU. */
for (; match->prodid; match++) {
const u32 prodid_mask = match->prodid_mask;
- if ((match->prodid & prodid_mask) == (prodid & prodid_mask))
+ if ((match->prodid & prodid_mask) ==
+ (cspmu->impl.pmiidr & prodid_mask))
break;
}
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support
2025-09-23 0:18 [PATCH v2 0/5] perf/arm_cspmu: Preparatory patches for NVIDIA T410 PMU Besar Wicaksono
` (3 preceding siblings ...)
2025-09-23 0:18 ` [PATCH v2 4/5] perf/arm_cspmu: nvidia: Add revision id matching Besar Wicaksono
@ 2025-09-23 0:18 ` Besar Wicaksono
2025-09-24 20:10 ` Ilkka Koskinen
2025-09-26 10:32 ` Robin Murphy
4 siblings, 2 replies; 15+ messages in thread
From: Besar Wicaksono @ 2025-09-23 0:18 UTC (permalink / raw)
To: will, robin.murphy, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, suzuki.poulose,
mark.rutland, treding, jonathanh, vsethi, rwiley, sdonthineni,
Besar Wicaksono
Support NVIDIA PMU that utilizes the optional event filter2 register.
Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
---
drivers/perf/arm_cspmu/nvidia_cspmu.c | 176 +++++++++++++++++++-------
1 file changed, 133 insertions(+), 43 deletions(-)
diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
index ac91dc46501d..e06a06d3407b 100644
--- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
+++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
@@ -40,10 +40,21 @@
struct nv_cspmu_ctx {
const char *name;
- u32 filter_mask;
- u32 filter_default_val;
+
struct attribute **event_attr;
struct attribute **format_attr;
+
+ u32 filter_mask;
+ u32 filter_default_val;
+ u32 filter2_mask;
+ u32 filter2_default_val;
+
+ u32 (*get_filter)(const struct perf_event *event);
+ u32 (*get_filter2)(const struct perf_event *event);
+
+ void *data;
+
+ int (*init_data)(struct arm_cspmu *cspmu);
};
static struct attribute *scf_pmu_event_attrs[] = {
@@ -144,6 +155,7 @@ static struct attribute *cnvlink_pmu_format_attrs[] = {
static struct attribute *generic_pmu_format_attrs[] = {
ARM_CSPMU_FORMAT_EVENT_ATTR,
ARM_CSPMU_FORMAT_FILTER_ATTR,
+ ARM_CSPMU_FORMAT_FILTER2_ATTR,
NULL,
};
@@ -184,13 +196,36 @@ static u32 nv_cspmu_event_filter(const struct perf_event *event)
return filter_val;
}
+static u32 nv_cspmu_event_filter2(const struct perf_event *event)
+{
+ const struct nv_cspmu_ctx *ctx =
+ to_nv_cspmu_ctx(to_arm_cspmu(event->pmu));
+
+ const u32 filter_val = event->attr.config2 & ctx->filter2_mask;
+
+ if (filter_val == 0)
+ return ctx->filter2_default_val;
+
+ return filter_val;
+}
+
static void nv_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
const struct perf_event *event)
{
- u32 filter = nv_cspmu_event_filter(event);
- u32 offset = PMEVFILTR + (4 * event->hw.idx);
+ u32 filter, offset;
+ const struct nv_cspmu_ctx *ctx =
+ to_nv_cspmu_ctx(to_arm_cspmu(event->pmu));
+ offset = 4 * event->hw.idx;
- writel(filter, cspmu->base0 + offset);
+ if (ctx->get_filter) {
+ filter = ctx->get_filter(event);
+ writel(filter, cspmu->base0 + PMEVFILTR + offset);
+ }
+
+ if (ctx->get_filter2) {
+ filter = ctx->get_filter2(event);
+ writel(filter, cspmu->base0 + PMEVFILT2R + offset);
+ }
}
static void nv_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
@@ -210,74 +245,120 @@ enum nv_cspmu_name_fmt {
struct nv_cspmu_match {
u32 prodid;
u32 prodid_mask;
- u64 filter_mask;
- u32 filter_default_val;
const char *name_pattern;
enum nv_cspmu_name_fmt name_fmt;
- struct attribute **event_attr;
- struct attribute **format_attr;
+ struct nv_cspmu_ctx template_ctx;
+ struct arm_cspmu_impl_ops ops;
};
static const struct nv_cspmu_match nv_cspmu_match[] = {
{
.prodid = 0x10300000,
.prodid_mask = NV_PRODID_MASK,
- .filter_mask = NV_PCIE_FILTER_ID_MASK,
- .filter_default_val = NV_PCIE_FILTER_ID_MASK,
.name_pattern = "nvidia_pcie_pmu_%u",
.name_fmt = NAME_FMT_SOCKET,
- .event_attr = mcf_pmu_event_attrs,
- .format_attr = pcie_pmu_format_attrs
+ .template_ctx = {
+ .event_attr = mcf_pmu_event_attrs,
+ .format_attr = pcie_pmu_format_attrs,
+ .filter_mask = NV_PCIE_FILTER_ID_MASK,
+ .filter_default_val = NV_PCIE_FILTER_ID_MASK,
+ .filter2_mask = 0x0,
+ .filter2_default_val = 0x0,
+ .get_filter = nv_cspmu_event_filter,
+ .get_filter2 = NULL,
+ .data = NULL,
+ .init_data = NULL
+ },
},
{
.prodid = 0x10400000,
.prodid_mask = NV_PRODID_MASK,
- .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
- .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
.name_pattern = "nvidia_nvlink_c2c1_pmu_%u",
.name_fmt = NAME_FMT_SOCKET,
- .event_attr = mcf_pmu_event_attrs,
- .format_attr = nvlink_c2c_pmu_format_attrs
+ .template_ctx = {
+ .event_attr = mcf_pmu_event_attrs,
+ .format_attr = nvlink_c2c_pmu_format_attrs,
+ .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
+ .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
+ .filter2_mask = 0x0,
+ .filter2_default_val = 0x0,
+ .get_filter = nv_cspmu_event_filter,
+ .get_filter2 = NULL,
+ .data = NULL,
+ .init_data = NULL
+ },
},
{
.prodid = 0x10500000,
.prodid_mask = NV_PRODID_MASK,
- .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
- .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
.name_pattern = "nvidia_nvlink_c2c0_pmu_%u",
.name_fmt = NAME_FMT_SOCKET,
- .event_attr = mcf_pmu_event_attrs,
- .format_attr = nvlink_c2c_pmu_format_attrs
+ .template_ctx = {
+ .event_attr = mcf_pmu_event_attrs,
+ .format_attr = nvlink_c2c_pmu_format_attrs,
+ .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
+ .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
+ .filter2_mask = 0x0,
+ .filter2_default_val = 0x0,
+ .get_filter = nv_cspmu_event_filter,
+ .get_filter2 = NULL,
+ .data = NULL,
+ .init_data = NULL
+ },
},
{
.prodid = 0x10600000,
.prodid_mask = NV_PRODID_MASK,
- .filter_mask = NV_CNVL_FILTER_ID_MASK,
- .filter_default_val = NV_CNVL_FILTER_ID_MASK,
.name_pattern = "nvidia_cnvlink_pmu_%u",
.name_fmt = NAME_FMT_SOCKET,
- .event_attr = mcf_pmu_event_attrs,
- .format_attr = cnvlink_pmu_format_attrs
+ .template_ctx = {
+ .event_attr = mcf_pmu_event_attrs,
+ .format_attr = cnvlink_pmu_format_attrs,
+ .filter_mask = NV_CNVL_FILTER_ID_MASK,
+ .filter_default_val = NV_CNVL_FILTER_ID_MASK,
+ .filter2_mask = 0x0,
+ .filter2_default_val = 0x0,
+ .get_filter = nv_cspmu_event_filter,
+ .get_filter2 = NULL,
+ .data = NULL,
+ .init_data = NULL
+ },
},
{
.prodid = 0x2CF00000,
.prodid_mask = NV_PRODID_MASK,
- .filter_mask = 0x0,
- .filter_default_val = 0x0,
.name_pattern = "nvidia_scf_pmu_%u",
.name_fmt = NAME_FMT_SOCKET,
- .event_attr = scf_pmu_event_attrs,
- .format_attr = scf_pmu_format_attrs
+ .template_ctx = {
+ .event_attr = scf_pmu_event_attrs,
+ .format_attr = scf_pmu_format_attrs,
+ .filter_mask = 0x0,
+ .filter_default_val = 0x0,
+ .filter2_mask = 0x0,
+ .filter2_default_val = 0x0,
+ .get_filter = nv_cspmu_event_filter,
+ .get_filter2 = NULL,
+ .data = NULL,
+ .init_data = NULL
+ },
},
{
.prodid = 0,
.prodid_mask = 0,
- .filter_mask = NV_GENERIC_FILTER_ID_MASK,
- .filter_default_val = NV_GENERIC_FILTER_ID_MASK,
.name_pattern = "nvidia_uncore_pmu_%u",
.name_fmt = NAME_FMT_GENERIC,
- .event_attr = generic_pmu_event_attrs,
- .format_attr = generic_pmu_format_attrs
+ .template_ctx = {
+ .event_attr = generic_pmu_event_attrs,
+ .format_attr = generic_pmu_format_attrs,
+ .filter_mask = NV_GENERIC_FILTER_ID_MASK,
+ .filter_default_val = NV_GENERIC_FILTER_ID_MASK,
+ .filter2_mask = NV_GENERIC_FILTER_ID_MASK,
+ .filter2_default_val = NV_GENERIC_FILTER_ID_MASK,
+ .get_filter = nv_cspmu_event_filter,
+ .get_filter2 = nv_cspmu_event_filter2,
+ .data = NULL,
+ .init_data = NULL
+ },
},
};
@@ -310,6 +391,14 @@ static char *nv_cspmu_format_name(const struct arm_cspmu *cspmu,
return name;
}
+#define SET_OP(name, impl, match, default_op) \
+ do { \
+ if (match->ops.name) \
+ impl->name = match->ops.name; \
+ else if (default_op != NULL) \
+ impl->name = default_op; \
+ } while (false)
+
static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
{
struct nv_cspmu_ctx *ctx;
@@ -330,20 +419,21 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
break;
}
- ctx->name = nv_cspmu_format_name(cspmu, match);
- ctx->filter_mask = match->filter_mask;
- ctx->filter_default_val = match->filter_default_val;
- ctx->event_attr = match->event_attr;
- ctx->format_attr = match->format_attr;
+ /* Initialize the context with the matched template. */
+ memcpy(ctx, &match->template_ctx, sizeof(struct nv_cspmu_ctx));
+ ctx->name = nv_cspmu_format_name(cspmu, match);
cspmu->impl.ctx = ctx;
/* NVIDIA specific callbacks. */
- impl_ops->set_cc_filter = nv_cspmu_set_cc_filter;
- impl_ops->set_ev_filter = nv_cspmu_set_ev_filter;
- impl_ops->get_event_attrs = nv_cspmu_get_event_attrs;
- impl_ops->get_format_attrs = nv_cspmu_get_format_attrs;
- impl_ops->get_name = nv_cspmu_get_name;
+ SET_OP(set_cc_filter, impl_ops, match, nv_cspmu_set_cc_filter);
+ SET_OP(set_ev_filter, impl_ops, match, nv_cspmu_set_ev_filter);
+ SET_OP(get_event_attrs, impl_ops, match, nv_cspmu_get_event_attrs);
+ SET_OP(get_format_attrs, impl_ops, match, nv_cspmu_get_format_attrs);
+ SET_OP(get_name, impl_ops, match, nv_cspmu_get_name);
+
+ if (ctx->init_data)
+ return ctx->init_data(cspmu);
return 0;
}
--
2.50.1
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get
2025-09-23 0:18 ` [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get Besar Wicaksono
@ 2025-09-24 20:05 ` Ilkka Koskinen
2025-09-25 8:30 ` Suzuki K Poulose
1 sibling, 0 replies; 15+ messages in thread
From: Ilkka Koskinen @ 2025-09-24 20:05 UTC (permalink / raw)
To: Besar Wicaksono
Cc: will, robin.murphy, ilkka, linux-arm-kernel, linux-kernel,
linux-tegra, suzuki.poulose, mark.rutland, treding, jonathanh,
vsethi, rwiley, sdonthineni
On Tue, 23 Sep 2025, Besar Wicaksono wrote:
> Add interface to get ACPI device associated with the
> PMU. This ACPI device may contain additional properties
> not covered by the standard properties.
>
> Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
> ---
> drivers/perf/arm_cspmu/arm_cspmu.c | 22 ++++++++++++++++++++++
> drivers/perf/arm_cspmu/arm_cspmu.h | 9 +++++++++
> 2 files changed, 31 insertions(+)
>
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
> index efa9b229e701..75b2d80f783e 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> @@ -1090,6 +1090,28 @@ static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
>
> return 0;
> }
> +
> +struct acpi_device *arm_cspmu_acpi_dev_get(const struct arm_cspmu *cspmu)
> +{
> + char hid[16];
> + char uid[16];
> + struct acpi_device *adev;
> + const struct acpi_apmt_node *apmt_node;
> +
> + apmt_node = arm_cspmu_apmt_node(cspmu->dev);
> + if (!apmt_node || apmt_node->type != ACPI_APMT_NODE_TYPE_ACPI)
> + return NULL;
> +
> + memset(hid, 0, sizeof(hid));
> + memset(uid, 0, sizeof(uid));
> +
> + memcpy(hid, &apmt_node->inst_primary, sizeof(apmt_node->inst_primary));
> + sprintf(uid, "%u", apmt_node->inst_secondary);
> +
> + adev = acpi_dev_get_first_match_dev(hid, uid, -1);
> + return adev;
I would rather drop adev completely and just do
"return acpi_dev_get_first_match_dev(hid, uid, -1);"
Regardless,
Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
Cheers, Ilkka
> +}
> +EXPORT_SYMBOL_GPL(arm_cspmu_acpi_dev_get);
> #else
> static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
> {
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
> index 19684b76bd96..9c5f11f98acd 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.h
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.h
> @@ -8,6 +8,7 @@
> #ifndef __ARM_CSPMU_H__
> #define __ARM_CSPMU_H__
>
> +#include <linux/acpi.h>
> #include <linux/bitfield.h>
> #include <linux/cpumask.h>
> #include <linux/device.h>
> @@ -222,4 +223,12 @@ int arm_cspmu_impl_register(const struct arm_cspmu_impl_match *impl_match);
> /* Unregister vendor backend. */
> void arm_cspmu_impl_unregister(const struct arm_cspmu_impl_match *impl_match);
>
> +#if defined(CONFIG_ACPI)
> +/**
> + * Get ACPI device associated with the PMU.
> + * The caller is responsible for calling acpi_dev_put() on the returned device.
> + */
> +struct acpi_device *arm_cspmu_acpi_dev_get(const struct arm_cspmu *cspmu);
> +#endif
> +
> #endif /* __ARM_CSPMU_H__ */
> --
> 2.50.1
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 2/5] perf/arm_cspmu: Add callback to reset filter config
2025-09-23 0:18 ` [PATCH v2 2/5] perf/arm_cspmu: Add callback to reset filter config Besar Wicaksono
@ 2025-09-24 20:06 ` Ilkka Koskinen
2025-09-25 9:23 ` Suzuki K Poulose
1 sibling, 0 replies; 15+ messages in thread
From: Ilkka Koskinen @ 2025-09-24 20:06 UTC (permalink / raw)
To: Besar Wicaksono
Cc: will, robin.murphy, ilkka, linux-arm-kernel, linux-kernel,
linux-tegra, suzuki.poulose, mark.rutland, treding, jonathanh,
vsethi, rwiley, sdonthineni
On Tue, 23 Sep 2025, Besar Wicaksono wrote:
> Implementer may need to reset a filter config when
> stopping a counter, thus adding a callback for this.
>
> Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
> ---
> drivers/perf/arm_cspmu/arm_cspmu.c | 4 ++++
> drivers/perf/arm_cspmu/arm_cspmu.h | 4 +++-
> 2 files changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
> index 75b2d80f783e..43770c8ecd14 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> @@ -815,6 +815,10 @@ static void arm_cspmu_stop(struct perf_event *event, int pmu_flags)
> return;
>
> arm_cspmu_disable_counter(cspmu, hwc->idx);
> +
> + if (cspmu->impl.ops.reset_ev_filter)
> + cspmu->impl.ops.reset_ev_filter(cspmu, event);
> +
> arm_cspmu_event_update(event);
>
> hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
> index 9c5f11f98acd..21d7e6e2f2da 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.h
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.h
> @@ -153,11 +153,13 @@ struct arm_cspmu_impl_ops {
> bool (*is_cycle_counter_event)(const struct perf_event *event);
> /* Decode event type/id from configs */
> u32 (*event_type)(const struct perf_event *event);
> - /* Set event filters */
> + /* Set/reset event filters */
> void (*set_cc_filter)(struct arm_cspmu *cspmu,
> const struct perf_event *event);
> void (*set_ev_filter)(struct arm_cspmu *cspmu,
> const struct perf_event *event);
> + void (*reset_ev_filter)(struct arm_cspmu *cspmu,
> + const struct perf_event *event);
> /* Implementation specific event validation */
> int (*validate_event)(struct arm_cspmu *cspmu,
> struct perf_event *event);
> --
> 2.50.1
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support
2025-09-23 0:18 ` [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support Besar Wicaksono
@ 2025-09-24 20:10 ` Ilkka Koskinen
2025-09-26 10:32 ` Robin Murphy
1 sibling, 0 replies; 15+ messages in thread
From: Ilkka Koskinen @ 2025-09-24 20:10 UTC (permalink / raw)
To: Besar Wicaksono
Cc: will, robin.murphy, ilkka, linux-arm-kernel, linux-kernel,
linux-tegra, suzuki.poulose, mark.rutland, treding, jonathanh,
vsethi, rwiley, sdonthineni
On Tue, 23 Sep 2025, Besar Wicaksono wrote:
> Support NVIDIA PMU that utilizes the optional event filter2 register.
>
> Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
Reviewed-by: Ilkka Koskinen <ilkka@os.amperecomputing.com>
> ---
> drivers/perf/arm_cspmu/nvidia_cspmu.c | 176 +++++++++++++++++++-------
> 1 file changed, 133 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
> index ac91dc46501d..e06a06d3407b 100644
> --- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
> +++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
> @@ -40,10 +40,21 @@
>
> struct nv_cspmu_ctx {
> const char *name;
> - u32 filter_mask;
> - u32 filter_default_val;
> +
> struct attribute **event_attr;
> struct attribute **format_attr;
> +
> + u32 filter_mask;
> + u32 filter_default_val;
> + u32 filter2_mask;
> + u32 filter2_default_val;
> +
> + u32 (*get_filter)(const struct perf_event *event);
> + u32 (*get_filter2)(const struct perf_event *event);
> +
> + void *data;
> +
> + int (*init_data)(struct arm_cspmu *cspmu);
> };
>
> static struct attribute *scf_pmu_event_attrs[] = {
> @@ -144,6 +155,7 @@ static struct attribute *cnvlink_pmu_format_attrs[] = {
> static struct attribute *generic_pmu_format_attrs[] = {
> ARM_CSPMU_FORMAT_EVENT_ATTR,
> ARM_CSPMU_FORMAT_FILTER_ATTR,
> + ARM_CSPMU_FORMAT_FILTER2_ATTR,
> NULL,
> };
>
> @@ -184,13 +196,36 @@ static u32 nv_cspmu_event_filter(const struct perf_event *event)
> return filter_val;
> }
>
> +static u32 nv_cspmu_event_filter2(const struct perf_event *event)
> +{
> + const struct nv_cspmu_ctx *ctx =
> + to_nv_cspmu_ctx(to_arm_cspmu(event->pmu));
> +
> + const u32 filter_val = event->attr.config2 & ctx->filter2_mask;
> +
> + if (filter_val == 0)
> + return ctx->filter2_default_val;
> +
> + return filter_val;
> +}
> +
> static void nv_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
> const struct perf_event *event)
> {
> - u32 filter = nv_cspmu_event_filter(event);
> - u32 offset = PMEVFILTR + (4 * event->hw.idx);
> + u32 filter, offset;
> + const struct nv_cspmu_ctx *ctx =
> + to_nv_cspmu_ctx(to_arm_cspmu(event->pmu));
> + offset = 4 * event->hw.idx;
>
> - writel(filter, cspmu->base0 + offset);
> + if (ctx->get_filter) {
> + filter = ctx->get_filter(event);
> + writel(filter, cspmu->base0 + PMEVFILTR + offset);
> + }
> +
> + if (ctx->get_filter2) {
> + filter = ctx->get_filter2(event);
> + writel(filter, cspmu->base0 + PMEVFILT2R + offset);
> + }
> }
>
> static void nv_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
> @@ -210,74 +245,120 @@ enum nv_cspmu_name_fmt {
> struct nv_cspmu_match {
> u32 prodid;
> u32 prodid_mask;
> - u64 filter_mask;
> - u32 filter_default_val;
> const char *name_pattern;
> enum nv_cspmu_name_fmt name_fmt;
> - struct attribute **event_attr;
> - struct attribute **format_attr;
> + struct nv_cspmu_ctx template_ctx;
> + struct arm_cspmu_impl_ops ops;
> };
>
> static const struct nv_cspmu_match nv_cspmu_match[] = {
> {
> .prodid = 0x10300000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = NV_PCIE_FILTER_ID_MASK,
> - .filter_default_val = NV_PCIE_FILTER_ID_MASK,
> .name_pattern = "nvidia_pcie_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = mcf_pmu_event_attrs,
> - .format_attr = pcie_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = mcf_pmu_event_attrs,
> + .format_attr = pcie_pmu_format_attrs,
> + .filter_mask = NV_PCIE_FILTER_ID_MASK,
> + .filter_default_val = NV_PCIE_FILTER_ID_MASK,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0x10400000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
> - .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
> .name_pattern = "nvidia_nvlink_c2c1_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = mcf_pmu_event_attrs,
> - .format_attr = nvlink_c2c_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = mcf_pmu_event_attrs,
> + .format_attr = nvlink_c2c_pmu_format_attrs,
> + .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
> + .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0x10500000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
> - .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
> .name_pattern = "nvidia_nvlink_c2c0_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = mcf_pmu_event_attrs,
> - .format_attr = nvlink_c2c_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = mcf_pmu_event_attrs,
> + .format_attr = nvlink_c2c_pmu_format_attrs,
> + .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
> + .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0x10600000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = NV_CNVL_FILTER_ID_MASK,
> - .filter_default_val = NV_CNVL_FILTER_ID_MASK,
> .name_pattern = "nvidia_cnvlink_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = mcf_pmu_event_attrs,
> - .format_attr = cnvlink_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = mcf_pmu_event_attrs,
> + .format_attr = cnvlink_pmu_format_attrs,
> + .filter_mask = NV_CNVL_FILTER_ID_MASK,
> + .filter_default_val = NV_CNVL_FILTER_ID_MASK,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0x2CF00000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = 0x0,
> - .filter_default_val = 0x0,
> .name_pattern = "nvidia_scf_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = scf_pmu_event_attrs,
> - .format_attr = scf_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = scf_pmu_event_attrs,
> + .format_attr = scf_pmu_format_attrs,
> + .filter_mask = 0x0,
> + .filter_default_val = 0x0,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0,
> .prodid_mask = 0,
> - .filter_mask = NV_GENERIC_FILTER_ID_MASK,
> - .filter_default_val = NV_GENERIC_FILTER_ID_MASK,
> .name_pattern = "nvidia_uncore_pmu_%u",
> .name_fmt = NAME_FMT_GENERIC,
> - .event_attr = generic_pmu_event_attrs,
> - .format_attr = generic_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = generic_pmu_event_attrs,
> + .format_attr = generic_pmu_format_attrs,
> + .filter_mask = NV_GENERIC_FILTER_ID_MASK,
> + .filter_default_val = NV_GENERIC_FILTER_ID_MASK,
> + .filter2_mask = NV_GENERIC_FILTER_ID_MASK,
> + .filter2_default_val = NV_GENERIC_FILTER_ID_MASK,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = nv_cspmu_event_filter2,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> };
>
> @@ -310,6 +391,14 @@ static char *nv_cspmu_format_name(const struct arm_cspmu *cspmu,
> return name;
> }
>
> +#define SET_OP(name, impl, match, default_op) \
> + do { \
> + if (match->ops.name) \
> + impl->name = match->ops.name; \
> + else if (default_op != NULL) \
> + impl->name = default_op; \
> + } while (false)
> +
> static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
> {
> struct nv_cspmu_ctx *ctx;
> @@ -330,20 +419,21 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
> break;
> }
>
> - ctx->name = nv_cspmu_format_name(cspmu, match);
> - ctx->filter_mask = match->filter_mask;
> - ctx->filter_default_val = match->filter_default_val;
> - ctx->event_attr = match->event_attr;
> - ctx->format_attr = match->format_attr;
> + /* Initialize the context with the matched template. */
> + memcpy(ctx, &match->template_ctx, sizeof(struct nv_cspmu_ctx));
> + ctx->name = nv_cspmu_format_name(cspmu, match);
>
> cspmu->impl.ctx = ctx;
>
> /* NVIDIA specific callbacks. */
> - impl_ops->set_cc_filter = nv_cspmu_set_cc_filter;
> - impl_ops->set_ev_filter = nv_cspmu_set_ev_filter;
> - impl_ops->get_event_attrs = nv_cspmu_get_event_attrs;
> - impl_ops->get_format_attrs = nv_cspmu_get_format_attrs;
> - impl_ops->get_name = nv_cspmu_get_name;
> + SET_OP(set_cc_filter, impl_ops, match, nv_cspmu_set_cc_filter);
> + SET_OP(set_ev_filter, impl_ops, match, nv_cspmu_set_ev_filter);
> + SET_OP(get_event_attrs, impl_ops, match, nv_cspmu_get_event_attrs);
> + SET_OP(get_format_attrs, impl_ops, match, nv_cspmu_get_format_attrs);
> + SET_OP(get_name, impl_ops, match, nv_cspmu_get_name);
> +
> + if (ctx->init_data)
> + return ctx->init_data(cspmu);
>
> return 0;
> }
> --
> 2.50.1
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get
2025-09-23 0:18 ` [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get Besar Wicaksono
2025-09-24 20:05 ` Ilkka Koskinen
@ 2025-09-25 8:30 ` Suzuki K Poulose
2025-09-25 17:13 ` Besar Wicaksono
1 sibling, 1 reply; 15+ messages in thread
From: Suzuki K Poulose @ 2025-09-25 8:30 UTC (permalink / raw)
To: Besar Wicaksono, will, robin.murphy, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, mark.rutland,
treding, jonathanh, vsethi, rwiley, sdonthineni
On 23/09/2025 01:18, Besar Wicaksono wrote:
> Add interface to get ACPI device associated with the
> PMU. This ACPI device may contain additional properties
> not covered by the standard properties.
>
Ok, but who needs this ? I couldn't see any users in the series.
Did I miss something ?
> Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
> ---
> drivers/perf/arm_cspmu/arm_cspmu.c | 22 ++++++++++++++++++++++
> drivers/perf/arm_cspmu/arm_cspmu.h | 9 +++++++++
> 2 files changed, 31 insertions(+)
>
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c b/drivers/perf/arm_cspmu/arm_cspmu.c
> index efa9b229e701..75b2d80f783e 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> @@ -1090,6 +1090,28 @@ static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
>
> return 0;
> }
> +
> +struct acpi_device *arm_cspmu_acpi_dev_get(const struct arm_cspmu *cspmu)
> +{
> + char hid[16];
> + char uid[16];
> + struct acpi_device *adev;
> + const struct acpi_apmt_node *apmt_node;
> +
> + apmt_node = arm_cspmu_apmt_node(cspmu->dev);
> + if (!apmt_node || apmt_node->type != ACPI_APMT_NODE_TYPE_ACPI)
> + return NULL;
> +
> + memset(hid, 0, sizeof(hid));
> + memset(uid, 0, sizeof(uid));
> +
> + memcpy(hid, &apmt_node->inst_primary, sizeof(apmt_node->inst_primary));
> + sprintf(uid, "%u", apmt_node->inst_secondary);
> +
> + adev = acpi_dev_get_first_match_dev(hid, uid, -1);
> + return adev;
> +}
> +EXPORT_SYMBOL_GPL(arm_cspmu_acpi_dev_get);
> #else
> static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
> {
> diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
> index 19684b76bd96..9c5f11f98acd 100644
> --- a/drivers/perf/arm_cspmu/arm_cspmu.h
> +++ b/drivers/perf/arm_cspmu/arm_cspmu.h
> @@ -8,6 +8,7 @@
> #ifndef __ARM_CSPMU_H__
> #define __ARM_CSPMU_H__
>
> +#include <linux/acpi.h>
> #include <linux/bitfield.h>
> #include <linux/cpumask.h>
> #include <linux/device.h>
> @@ -222,4 +223,12 @@ int arm_cspmu_impl_register(const struct arm_cspmu_impl_match *impl_match);
> /* Unregister vendor backend. */
> void arm_cspmu_impl_unregister(const struct arm_cspmu_impl_match *impl_match);
>
> +#if defined(CONFIG_ACPI)
> +/**
> + * Get ACPI device associated with the PMU.
> + * The caller is responsible for calling acpi_dev_put() on the returned device.
> + */
> +struct acpi_device *arm_cspmu_acpi_dev_get(const struct arm_cspmu *cspmu);
> +#endif
If we need this, why not add an empty stub for !CONFIG_ACPI case ?
Similar to what we do for other cases.
Suzuki
> +
> #endif /* __ARM_CSPMU_H__ */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 2/5] perf/arm_cspmu: Add callback to reset filter config
2025-09-23 0:18 ` [PATCH v2 2/5] perf/arm_cspmu: Add callback to reset filter config Besar Wicaksono
2025-09-24 20:06 ` Ilkka Koskinen
@ 2025-09-25 9:23 ` Suzuki K Poulose
1 sibling, 0 replies; 15+ messages in thread
From: Suzuki K Poulose @ 2025-09-25 9:23 UTC (permalink / raw)
To: Besar Wicaksono, will, robin.murphy, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, mark.rutland,
treding, jonathanh, vsethi, rwiley, sdonthineni
On 23/09/2025 01:18, Besar Wicaksono wrote:
> Implementer may need to reset a filter config when
> stopping a counter, thus adding a callback for this.
>
> Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get
2025-09-25 8:30 ` Suzuki K Poulose
@ 2025-09-25 17:13 ` Besar Wicaksono
2025-09-26 10:01 ` Suzuki K Poulose
0 siblings, 1 reply; 15+ messages in thread
From: Besar Wicaksono @ 2025-09-25 17:13 UTC (permalink / raw)
To: Suzuki K Poulose, will@kernel.org, robin.murphy@arm.com,
ilkka@os.amperecomputing.com
Cc: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
mark.rutland@arm.com, Thierry Reding, Jon Hunter, Vikram Sethi,
Rich Wiley, Shanker Donthineni
> -----Original Message-----
> From: Suzuki K Poulose <suzuki.poulose@arm.com>
> Sent: Thursday, September 25, 2025 3:31 AM
> To: Besar Wicaksono <bwicaksono@nvidia.com>; will@kernel.org;
> robin.murphy@arm.com; ilkka@os.amperecomputing.com
> Cc: linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org; linux-
> tegra@vger.kernel.org; mark.rutland@arm.com; Thierry Reding
> <treding@nvidia.com>; Jon Hunter <jonathanh@nvidia.com>; Vikram Sethi
> <vsethi@nvidia.com>; Rich Wiley <rwiley@nvidia.com>; Shanker Donthineni
> <sdonthineni@nvidia.com>
> Subject: Re: [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get
>
> External email: Use caution opening links or attachments
>
>
> On 23/09/2025 01:18, Besar Wicaksono wrote:
> > Add interface to get ACPI device associated with the
> > PMU. This ACPI device may contain additional properties
> > not covered by the standard properties.
> >
>
> Ok, but who needs this ? I couldn't see any users in the series.
> Did I miss something ?
NVIDIA will need it to support upcoming PMU devices.
I am still preparing the follow up patch series containing the use case
on these new devices.
>
> > Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
> > ---
> > drivers/perf/arm_cspmu/arm_cspmu.c | 22 ++++++++++++++++++++++
> > drivers/perf/arm_cspmu/arm_cspmu.h | 9 +++++++++
> > 2 files changed, 31 insertions(+)
> >
> > diff --git a/drivers/perf/arm_cspmu/arm_cspmu.c
> b/drivers/perf/arm_cspmu/arm_cspmu.c
> > index efa9b229e701..75b2d80f783e 100644
> > --- a/drivers/perf/arm_cspmu/arm_cspmu.c
> > +++ b/drivers/perf/arm_cspmu/arm_cspmu.c
> > @@ -1090,6 +1090,28 @@ static int arm_cspmu_acpi_get_cpus(struct
> arm_cspmu *cspmu)
> >
> > return 0;
> > }
> > +
> > +struct acpi_device *arm_cspmu_acpi_dev_get(const struct arm_cspmu
> *cspmu)
> > +{
> > + char hid[16];
> > + char uid[16];
> > + struct acpi_device *adev;
> > + const struct acpi_apmt_node *apmt_node;
> > +
> > + apmt_node = arm_cspmu_apmt_node(cspmu->dev);
> > + if (!apmt_node || apmt_node->type != ACPI_APMT_NODE_TYPE_ACPI)
> > + return NULL;
> > +
> > + memset(hid, 0, sizeof(hid));
> > + memset(uid, 0, sizeof(uid));
> > +
> > + memcpy(hid, &apmt_node->inst_primary, sizeof(apmt_node-
> >inst_primary));
> > + sprintf(uid, "%u", apmt_node->inst_secondary);
> > +
> > + adev = acpi_dev_get_first_match_dev(hid, uid, -1);
> > + return adev;
> > +}
> > +EXPORT_SYMBOL_GPL(arm_cspmu_acpi_dev_get);
> > #else
> > static int arm_cspmu_acpi_get_cpus(struct arm_cspmu *cspmu)
> > {
> > diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h
> b/drivers/perf/arm_cspmu/arm_cspmu.h
> > index 19684b76bd96..9c5f11f98acd 100644
> > --- a/drivers/perf/arm_cspmu/arm_cspmu.h
> > +++ b/drivers/perf/arm_cspmu/arm_cspmu.h
> > @@ -8,6 +8,7 @@
> > #ifndef __ARM_CSPMU_H__
> > #define __ARM_CSPMU_H__
> >
> > +#include <linux/acpi.h>
> > #include <linux/bitfield.h>
> > #include <linux/cpumask.h>
> > #include <linux/device.h>
> > @@ -222,4 +223,12 @@ int arm_cspmu_impl_register(const struct
> arm_cspmu_impl_match *impl_match);
> > /* Unregister vendor backend. */
> > void arm_cspmu_impl_unregister(const struct arm_cspmu_impl_match
> *impl_match);
> >
> > +#if defined(CONFIG_ACPI)
> > +/**
> > + * Get ACPI device associated with the PMU.
> > + * The caller is responsible for calling acpi_dev_put() on the returned device.
> > + */
> > +struct acpi_device *arm_cspmu_acpi_dev_get(const struct arm_cspmu
> *cspmu);
> > +#endif
> If we need this, why not add an empty stub for !CONFIG_ACPI case ?
> Similar to what we do for other cases.
Right, this is an oversight. I thought the ACPI code is not portable. But just found
out linux/acpi.h takes care of it. I will fix it on next version.
Thanks,
Besar
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get
2025-09-25 17:13 ` Besar Wicaksono
@ 2025-09-26 10:01 ` Suzuki K Poulose
0 siblings, 0 replies; 15+ messages in thread
From: Suzuki K Poulose @ 2025-09-26 10:01 UTC (permalink / raw)
To: Besar Wicaksono, will@kernel.org, robin.murphy@arm.com,
ilkka@os.amperecomputing.com
Cc: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
mark.rutland@arm.com, Thierry Reding, Jon Hunter, Vikram Sethi,
Rich Wiley, Shanker Donthineni
On 25/09/2025 18:13, Besar Wicaksono wrote:
>
>
>> -----Original Message-----
>> From: Suzuki K Poulose <suzuki.poulose@arm.com>
>> Sent: Thursday, September 25, 2025 3:31 AM
>> To: Besar Wicaksono <bwicaksono@nvidia.com>; will@kernel.org;
>> robin.murphy@arm.com; ilkka@os.amperecomputing.com
>> Cc: linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org; linux-
>> tegra@vger.kernel.org; mark.rutland@arm.com; Thierry Reding
>> <treding@nvidia.com>; Jon Hunter <jonathanh@nvidia.com>; Vikram Sethi
>> <vsethi@nvidia.com>; Rich Wiley <rwiley@nvidia.com>; Shanker Donthineni
>> <sdonthineni@nvidia.com>
>> Subject: Re: [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get
>>
>> External email: Use caution opening links or attachments
>>
>>
>> On 23/09/2025 01:18, Besar Wicaksono wrote:
>>> Add interface to get ACPI device associated with the
>>> PMU. This ACPI device may contain additional properties
>>> not covered by the standard properties.
>>>
>>
>> Ok, but who needs this ? I couldn't see any users in the series.
>> Did I miss something ?
>
> NVIDIA will need it to support upcoming PMU devices.
> I am still preparing the follow up patch series containing the use case
> on these new devices.
Thanks for the explanation. It would be good to post something with a
user. You could post this patch, with the future series then.
Suzuki
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support
2025-09-23 0:18 ` [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support Besar Wicaksono
2025-09-24 20:10 ` Ilkka Koskinen
@ 2025-09-26 10:32 ` Robin Murphy
2025-09-26 16:35 ` Besar Wicaksono
1 sibling, 1 reply; 15+ messages in thread
From: Robin Murphy @ 2025-09-26 10:32 UTC (permalink / raw)
To: Besar Wicaksono, will, ilkka
Cc: linux-arm-kernel, linux-kernel, linux-tegra, suzuki.poulose,
mark.rutland, treding, jonathanh, vsethi, rwiley, sdonthineni
On 2025-09-23 1:18 am, Besar Wicaksono wrote:
> Support NVIDIA PMU that utilizes the optional event filter2 register.
>
> Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
> ---
> drivers/perf/arm_cspmu/nvidia_cspmu.c | 176 +++++++++++++++++++-------
> 1 file changed, 133 insertions(+), 43 deletions(-)
>
> diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c b/drivers/perf/arm_cspmu/nvidia_cspmu.c
> index ac91dc46501d..e06a06d3407b 100644
> --- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
> +++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
> @@ -40,10 +40,21 @@
>
> struct nv_cspmu_ctx {
> const char *name;
> - u32 filter_mask;
> - u32 filter_default_val;
> +
> struct attribute **event_attr;
> struct attribute **format_attr;
> +
> + u32 filter_mask;
> + u32 filter_default_val;
> + u32 filter2_mask;
> + u32 filter2_default_val;
> +
> + u32 (*get_filter)(const struct perf_event *event);
> + u32 (*get_filter2)(const struct perf_event *event);
Callbacks for this seem like complete overkill - you already know
whether a given implementation cares about each filter via
.filter{,2}_mask being nonzero, so unless you intend to have wildly
different event encodings across implementations, a simple conditional
extension of the existing nv_cspmu_event_filter() logic should be all
you need.
Thanks,
Robin.
> +
> + void *data;
> +
> + int (*init_data)(struct arm_cspmu *cspmu);
> };
>
> static struct attribute *scf_pmu_event_attrs[] = {
> @@ -144,6 +155,7 @@ static struct attribute *cnvlink_pmu_format_attrs[] = {
> static struct attribute *generic_pmu_format_attrs[] = {
> ARM_CSPMU_FORMAT_EVENT_ATTR,
> ARM_CSPMU_FORMAT_FILTER_ATTR,
> + ARM_CSPMU_FORMAT_FILTER2_ATTR,
> NULL,
> };
>
> @@ -184,13 +196,36 @@ static u32 nv_cspmu_event_filter(const struct perf_event *event)
> return filter_val;
> }
>
> +static u32 nv_cspmu_event_filter2(const struct perf_event *event)
> +{
> + const struct nv_cspmu_ctx *ctx =
> + to_nv_cspmu_ctx(to_arm_cspmu(event->pmu));
> +
> + const u32 filter_val = event->attr.config2 & ctx->filter2_mask;
> +
> + if (filter_val == 0)
> + return ctx->filter2_default_val;
> +
> + return filter_val;
> +}
> +
> static void nv_cspmu_set_ev_filter(struct arm_cspmu *cspmu,
> const struct perf_event *event)
> {
> - u32 filter = nv_cspmu_event_filter(event);
> - u32 offset = PMEVFILTR + (4 * event->hw.idx);
> + u32 filter, offset;
> + const struct nv_cspmu_ctx *ctx =
> + to_nv_cspmu_ctx(to_arm_cspmu(event->pmu));
> + offset = 4 * event->hw.idx;
>
> - writel(filter, cspmu->base0 + offset);
> + if (ctx->get_filter) {
> + filter = ctx->get_filter(event);
> + writel(filter, cspmu->base0 + PMEVFILTR + offset);
> + }
> +
> + if (ctx->get_filter2) {
> + filter = ctx->get_filter2(event);
> + writel(filter, cspmu->base0 + PMEVFILT2R + offset);
> + }
> }
>
> static void nv_cspmu_set_cc_filter(struct arm_cspmu *cspmu,
> @@ -210,74 +245,120 @@ enum nv_cspmu_name_fmt {
> struct nv_cspmu_match {
> u32 prodid;
> u32 prodid_mask;
> - u64 filter_mask;
> - u32 filter_default_val;
> const char *name_pattern;
> enum nv_cspmu_name_fmt name_fmt;
> - struct attribute **event_attr;
> - struct attribute **format_attr;
> + struct nv_cspmu_ctx template_ctx;
> + struct arm_cspmu_impl_ops ops;
> };
>
> static const struct nv_cspmu_match nv_cspmu_match[] = {
> {
> .prodid = 0x10300000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = NV_PCIE_FILTER_ID_MASK,
> - .filter_default_val = NV_PCIE_FILTER_ID_MASK,
> .name_pattern = "nvidia_pcie_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = mcf_pmu_event_attrs,
> - .format_attr = pcie_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = mcf_pmu_event_attrs,
> + .format_attr = pcie_pmu_format_attrs,
> + .filter_mask = NV_PCIE_FILTER_ID_MASK,
> + .filter_default_val = NV_PCIE_FILTER_ID_MASK,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0x10400000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
> - .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
> .name_pattern = "nvidia_nvlink_c2c1_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = mcf_pmu_event_attrs,
> - .format_attr = nvlink_c2c_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = mcf_pmu_event_attrs,
> + .format_attr = nvlink_c2c_pmu_format_attrs,
> + .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
> + .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0x10500000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
> - .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
> .name_pattern = "nvidia_nvlink_c2c0_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = mcf_pmu_event_attrs,
> - .format_attr = nvlink_c2c_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = mcf_pmu_event_attrs,
> + .format_attr = nvlink_c2c_pmu_format_attrs,
> + .filter_mask = NV_NVL_C2C_FILTER_ID_MASK,
> + .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0x10600000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = NV_CNVL_FILTER_ID_MASK,
> - .filter_default_val = NV_CNVL_FILTER_ID_MASK,
> .name_pattern = "nvidia_cnvlink_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = mcf_pmu_event_attrs,
> - .format_attr = cnvlink_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = mcf_pmu_event_attrs,
> + .format_attr = cnvlink_pmu_format_attrs,
> + .filter_mask = NV_CNVL_FILTER_ID_MASK,
> + .filter_default_val = NV_CNVL_FILTER_ID_MASK,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0x2CF00000,
> .prodid_mask = NV_PRODID_MASK,
> - .filter_mask = 0x0,
> - .filter_default_val = 0x0,
> .name_pattern = "nvidia_scf_pmu_%u",
> .name_fmt = NAME_FMT_SOCKET,
> - .event_attr = scf_pmu_event_attrs,
> - .format_attr = scf_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = scf_pmu_event_attrs,
> + .format_attr = scf_pmu_format_attrs,
> + .filter_mask = 0x0,
> + .filter_default_val = 0x0,
> + .filter2_mask = 0x0,
> + .filter2_default_val = 0x0,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = NULL,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> {
> .prodid = 0,
> .prodid_mask = 0,
> - .filter_mask = NV_GENERIC_FILTER_ID_MASK,
> - .filter_default_val = NV_GENERIC_FILTER_ID_MASK,
> .name_pattern = "nvidia_uncore_pmu_%u",
> .name_fmt = NAME_FMT_GENERIC,
> - .event_attr = generic_pmu_event_attrs,
> - .format_attr = generic_pmu_format_attrs
> + .template_ctx = {
> + .event_attr = generic_pmu_event_attrs,
> + .format_attr = generic_pmu_format_attrs,
> + .filter_mask = NV_GENERIC_FILTER_ID_MASK,
> + .filter_default_val = NV_GENERIC_FILTER_ID_MASK,
> + .filter2_mask = NV_GENERIC_FILTER_ID_MASK,
> + .filter2_default_val = NV_GENERIC_FILTER_ID_MASK,
> + .get_filter = nv_cspmu_event_filter,
> + .get_filter2 = nv_cspmu_event_filter2,
> + .data = NULL,
> + .init_data = NULL
> + },
> },
> };
>
> @@ -310,6 +391,14 @@ static char *nv_cspmu_format_name(const struct arm_cspmu *cspmu,
> return name;
> }
>
> +#define SET_OP(name, impl, match, default_op) \
> + do { \
> + if (match->ops.name) \
> + impl->name = match->ops.name; \
> + else if (default_op != NULL) \
> + impl->name = default_op; \
> + } while (false)
> +
> static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
> {
> struct nv_cspmu_ctx *ctx;
> @@ -330,20 +419,21 @@ static int nv_cspmu_init_ops(struct arm_cspmu *cspmu)
> break;
> }
>
> - ctx->name = nv_cspmu_format_name(cspmu, match);
> - ctx->filter_mask = match->filter_mask;
> - ctx->filter_default_val = match->filter_default_val;
> - ctx->event_attr = match->event_attr;
> - ctx->format_attr = match->format_attr;
> + /* Initialize the context with the matched template. */
> + memcpy(ctx, &match->template_ctx, sizeof(struct nv_cspmu_ctx));
> + ctx->name = nv_cspmu_format_name(cspmu, match);
>
> cspmu->impl.ctx = ctx;
>
> /* NVIDIA specific callbacks. */
> - impl_ops->set_cc_filter = nv_cspmu_set_cc_filter;
> - impl_ops->set_ev_filter = nv_cspmu_set_ev_filter;
> - impl_ops->get_event_attrs = nv_cspmu_get_event_attrs;
> - impl_ops->get_format_attrs = nv_cspmu_get_format_attrs;
> - impl_ops->get_name = nv_cspmu_get_name;
> + SET_OP(set_cc_filter, impl_ops, match, nv_cspmu_set_cc_filter);
> + SET_OP(set_ev_filter, impl_ops, match, nv_cspmu_set_ev_filter);
> + SET_OP(get_event_attrs, impl_ops, match, nv_cspmu_get_event_attrs);
> + SET_OP(get_format_attrs, impl_ops, match, nv_cspmu_get_format_attrs);
> + SET_OP(get_name, impl_ops, match, nv_cspmu_get_name);
> +
> + if (ctx->init_data)
> + return ctx->init_data(cspmu);
>
> return 0;
> }
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support
2025-09-26 10:32 ` Robin Murphy
@ 2025-09-26 16:35 ` Besar Wicaksono
0 siblings, 0 replies; 15+ messages in thread
From: Besar Wicaksono @ 2025-09-26 16:35 UTC (permalink / raw)
To: Robin Murphy, will@kernel.org, ilkka@os.amperecomputing.com
Cc: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org,
suzuki.poulose@arm.com, mark.rutland@arm.com, Thierry Reding,
Jon Hunter, Vikram Sethi, Rich Wiley, Shanker Donthineni
> -----Original Message-----
> From: Robin Murphy <robin.murphy@arm.com>
> Sent: Friday, September 26, 2025 5:32 AM
> To: Besar Wicaksono <bwicaksono@nvidia.com>; will@kernel.org;
> ilkka@os.amperecomputing.com
> Cc: linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org; linux-
> tegra@vger.kernel.org; suzuki.poulose@arm.com; mark.rutland@arm.com;
> Thierry Reding <treding@nvidia.com>; Jon Hunter <jonathanh@nvidia.com>;
> Vikram Sethi <vsethi@nvidia.com>; Rich Wiley <rwiley@nvidia.com>; Shanker
> Donthineni <sdonthineni@nvidia.com>
> Subject: Re: [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support
>
> External email: Use caution opening links or attachments
>
>
> On 2025-09-23 1:18 am, Besar Wicaksono wrote:
> > Support NVIDIA PMU that utilizes the optional event filter2 register.
> >
> > Signed-off-by: Besar Wicaksono <bwicaksono@nvidia.com>
> > ---
> > drivers/perf/arm_cspmu/nvidia_cspmu.c | 176 +++++++++++++++++++---
> ----
> > 1 file changed, 133 insertions(+), 43 deletions(-)
> >
> > diff --git a/drivers/perf/arm_cspmu/nvidia_cspmu.c
> b/drivers/perf/arm_cspmu/nvidia_cspmu.c
> > index ac91dc46501d..e06a06d3407b 100644
> > --- a/drivers/perf/arm_cspmu/nvidia_cspmu.c
> > +++ b/drivers/perf/arm_cspmu/nvidia_cspmu.c
> > @@ -40,10 +40,21 @@
> >
> > struct nv_cspmu_ctx {
> > const char *name;
> > - u32 filter_mask;
> > - u32 filter_default_val;
> > +
> > struct attribute **event_attr;
> > struct attribute **format_attr;
> > +
> > + u32 filter_mask;
> > + u32 filter_default_val;
> > + u32 filter2_mask;
> > + u32 filter2_default_val;
> > +
> > + u32 (*get_filter)(const struct perf_event *event);
> > + u32 (*get_filter2)(const struct perf_event *event);
>
> Callbacks for this seem like complete overkill - you already know
> whether a given implementation cares about each filter via
> .filter{,2}_mask being nonzero, so unless you intend to have wildly
> different event encodings across implementations, a simple conditional
> extension of the existing nv_cspmu_event_filter() logic should be all
> you need.
>
Indeed, this is the reason. All the new PMUs we are planning to support
have unique requirements on the filter configuration.
Regards,
Besar
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2025-09-26 16:35 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-23 0:18 [PATCH v2 0/5] perf/arm_cspmu: Preparatory patches for NVIDIA T410 PMU Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 1/5] perf/arm_cspmu: Add arm_cspmu_acpi_dev_get Besar Wicaksono
2025-09-24 20:05 ` Ilkka Koskinen
2025-09-25 8:30 ` Suzuki K Poulose
2025-09-25 17:13 ` Besar Wicaksono
2025-09-26 10:01 ` Suzuki K Poulose
2025-09-23 0:18 ` [PATCH v2 2/5] perf/arm_cspmu: Add callback to reset filter config Besar Wicaksono
2025-09-24 20:06 ` Ilkka Koskinen
2025-09-25 9:23 ` Suzuki K Poulose
2025-09-23 0:18 ` [PATCH v2 3/5] perf/arm_cspmu: Add pmpidr support Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 4/5] perf/arm_cspmu: nvidia: Add revision id matching Besar Wicaksono
2025-09-23 0:18 ` [PATCH v2 5/5] perf/arm_cspmu: nvidia: Add pmevfiltr2 support Besar Wicaksono
2025-09-24 20:10 ` Ilkka Koskinen
2025-09-26 10:32 ` Robin Murphy
2025-09-26 16:35 ` Besar Wicaksono
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox