]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf: arm_spe: Expose event filter
authorLeo Yan <leo.yan@arm.com>
Mon, 1 Sep 2025 12:40:32 +0000 (13:40 +0100)
committerWill Deacon <will@kernel.org>
Thu, 18 Sep 2025 13:17:02 +0000 (14:17 +0100)
Expose an "event_filter" entry in the caps folder to inform user space
about which events can be filtered.

Change the return type of arm_spe_pmu_cap_get() from u32 to u64 to
accommodate the added event filter entry.

Signed-off-by: Leo Yan <leo.yan@arm.com>
Tested-by: Leo Yan <leo.yan@arm.com>
Signed-off-by: James Clark <james.clark@linaro.org>
Signed-off-by: Will Deacon <will@kernel.org>
drivers/perf/arm_spe_pmu.c

index 86c9948ab5a064abf9feefe99acca5ea53103426..ba55bc3db70842ea90e7ccc9f978cf62f8cbe42d 100644 (file)
@@ -116,6 +116,7 @@ enum arm_spe_pmu_capabilities {
        SPE_PMU_CAP_FEAT_MAX,
        SPE_PMU_CAP_CNT_SZ = SPE_PMU_CAP_FEAT_MAX,
        SPE_PMU_CAP_MIN_IVAL,
+       SPE_PMU_CAP_EVENT_FILTER,
 };
 
 static int arm_spe_pmu_feat_caps[SPE_PMU_CAP_FEAT_MAX] = {
@@ -123,7 +124,7 @@ static int arm_spe_pmu_feat_caps[SPE_PMU_CAP_FEAT_MAX] = {
        [SPE_PMU_CAP_ERND]      = SPE_PMU_FEAT_ERND,
 };
 
-static u32 arm_spe_pmu_cap_get(struct arm_spe_pmu *spe_pmu, int cap)
+static u64 arm_spe_pmu_cap_get(struct arm_spe_pmu *spe_pmu, int cap)
 {
        if (cap < SPE_PMU_CAP_FEAT_MAX)
                return !!(spe_pmu->features & arm_spe_pmu_feat_caps[cap]);
@@ -133,6 +134,8 @@ static u32 arm_spe_pmu_cap_get(struct arm_spe_pmu *spe_pmu, int cap)
                return spe_pmu->counter_sz;
        case SPE_PMU_CAP_MIN_IVAL:
                return spe_pmu->min_period;
+       case SPE_PMU_CAP_EVENT_FILTER:
+               return ~spe_pmu->pmsevfr_res0;
        default:
                WARN(1, "unknown cap %d\n", cap);
        }
@@ -149,7 +152,19 @@ static ssize_t arm_spe_pmu_cap_show(struct device *dev,
                container_of(attr, struct dev_ext_attribute, attr);
        int cap = (long)ea->var;
 
-       return sysfs_emit(buf, "%u\n", arm_spe_pmu_cap_get(spe_pmu, cap));
+       return sysfs_emit(buf, "%llu\n", arm_spe_pmu_cap_get(spe_pmu, cap));
+}
+
+static ssize_t arm_spe_pmu_cap_show_hex(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev);
+       struct dev_ext_attribute *ea =
+               container_of(attr, struct dev_ext_attribute, attr);
+       int cap = (long)ea->var;
+
+       return sysfs_emit(buf, "0x%llx\n", arm_spe_pmu_cap_get(spe_pmu, cap));
 }
 
 #define SPE_EXT_ATTR_ENTRY(_name, _func, _var)                         \
@@ -159,12 +174,15 @@ static ssize_t arm_spe_pmu_cap_show(struct device *dev,
 
 #define SPE_CAP_EXT_ATTR_ENTRY(_name, _var)                            \
        SPE_EXT_ATTR_ENTRY(_name, arm_spe_pmu_cap_show, _var)
+#define SPE_CAP_EXT_ATTR_ENTRY_HEX(_name, _var)                                \
+       SPE_EXT_ATTR_ENTRY(_name, arm_spe_pmu_cap_show_hex, _var)
 
 static struct attribute *arm_spe_pmu_cap_attr[] = {
        SPE_CAP_EXT_ATTR_ENTRY(arch_inst, SPE_PMU_CAP_ARCH_INST),
        SPE_CAP_EXT_ATTR_ENTRY(ernd, SPE_PMU_CAP_ERND),
        SPE_CAP_EXT_ATTR_ENTRY(count_size, SPE_PMU_CAP_CNT_SZ),
        SPE_CAP_EXT_ATTR_ENTRY(min_interval, SPE_PMU_CAP_MIN_IVAL),
+       SPE_CAP_EXT_ATTR_ENTRY_HEX(event_filter, SPE_PMU_CAP_EVENT_FILTER),
        NULL,
 };