Skip to content

Commit 8d9190f

Browse files
robherringwilldeacon
authored andcommitted
perf: arm_spe: Add support for SPEv1.2 inverted event filtering
Arm SPEv1.2 (Arm v8.7/v9.2) adds a new feature called Inverted Event Filter which excludes samples matching the event filter. The feature mirrors the existing event filter in PMSEVFR_EL1 adding a new register, PMSNEVFR_EL1, which has the same event bit assignments. Tested-by: James Clark <[email protected]> Signed-off-by: Rob Herring <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 09519ec commit 8d9190f

File tree

1 file changed

+45
-0
lines changed

1 file changed

+45
-0
lines changed

drivers/perf/arm_spe_pmu.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ struct arm_spe_pmu {
8585
#define SPE_PMU_FEAT_ARCH_INST (1UL << 3)
8686
#define SPE_PMU_FEAT_LDS (1UL << 4)
8787
#define SPE_PMU_FEAT_ERND (1UL << 5)
88+
#define SPE_PMU_FEAT_INV_FILT_EVT (1UL << 6)
8889
#define SPE_PMU_FEAT_DEV_PROBED (1UL << 63)
8990
u64 features;
9091

@@ -202,6 +203,10 @@ static const struct attribute_group arm_spe_pmu_cap_group = {
202203
#define ATTR_CFG_FLD_min_latency_LO 0
203204
#define ATTR_CFG_FLD_min_latency_HI 11
204205

206+
#define ATTR_CFG_FLD_inv_event_filter_CFG config3 /* PMSNEVFR_EL1 */
207+
#define ATTR_CFG_FLD_inv_event_filter_LO 0
208+
#define ATTR_CFG_FLD_inv_event_filter_HI 63
209+
205210
/* Why does everything I do descend into this? */
206211
#define __GEN_PMU_FORMAT_ATTR(cfg, lo, hi) \
207212
(lo) == (hi) ? #cfg ":" #lo "\n" : #cfg ":" #lo "-" #hi
@@ -232,6 +237,7 @@ GEN_PMU_FORMAT_ATTR(branch_filter);
232237
GEN_PMU_FORMAT_ATTR(load_filter);
233238
GEN_PMU_FORMAT_ATTR(store_filter);
234239
GEN_PMU_FORMAT_ATTR(event_filter);
240+
GEN_PMU_FORMAT_ATTR(inv_event_filter);
235241
GEN_PMU_FORMAT_ATTR(min_latency);
236242

237243
static struct attribute *arm_spe_pmu_formats_attr[] = {
@@ -243,12 +249,27 @@ static struct attribute *arm_spe_pmu_formats_attr[] = {
243249
&format_attr_load_filter.attr,
244250
&format_attr_store_filter.attr,
245251
&format_attr_event_filter.attr,
252+
&format_attr_inv_event_filter.attr,
246253
&format_attr_min_latency.attr,
247254
NULL,
248255
};
249256

257+
static umode_t arm_spe_pmu_format_attr_is_visible(struct kobject *kobj,
258+
struct attribute *attr,
259+
int unused)
260+
{
261+
struct device *dev = kobj_to_dev(kobj);
262+
struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev);
263+
264+
if (attr == &format_attr_inv_event_filter.attr && !(spe_pmu->features & SPE_PMU_FEAT_INV_FILT_EVT))
265+
return 0;
266+
267+
return attr->mode;
268+
}
269+
250270
static const struct attribute_group arm_spe_pmu_format_group = {
251271
.name = "format",
272+
.is_visible = arm_spe_pmu_format_attr_is_visible,
252273
.attrs = arm_spe_pmu_formats_attr,
253274
};
254275

@@ -343,6 +364,9 @@ static u64 arm_spe_event_to_pmsfcr(struct perf_event *event)
343364
if (ATTR_CFG_GET_FLD(attr, event_filter))
344365
reg |= PMSFCR_EL1_FE;
345366

367+
if (ATTR_CFG_GET_FLD(attr, inv_event_filter))
368+
reg |= PMSFCR_EL1_FnE;
369+
346370
if (ATTR_CFG_GET_FLD(attr, min_latency))
347371
reg |= PMSFCR_EL1_FL;
348372

@@ -355,6 +379,12 @@ static u64 arm_spe_event_to_pmsevfr(struct perf_event *event)
355379
return ATTR_CFG_GET_FLD(attr, event_filter);
356380
}
357381

382+
static u64 arm_spe_event_to_pmsnevfr(struct perf_event *event)
383+
{
384+
struct perf_event_attr *attr = &event->attr;
385+
return ATTR_CFG_GET_FLD(attr, inv_event_filter);
386+
}
387+
358388
static u64 arm_spe_event_to_pmslatfr(struct perf_event *event)
359389
{
360390
struct perf_event_attr *attr = &event->attr;
@@ -703,6 +733,9 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
703733
if (arm_spe_event_to_pmsevfr(event) & arm_spe_pmsevfr_res0(spe_pmu->pmsver))
704734
return -EOPNOTSUPP;
705735

736+
if (arm_spe_event_to_pmsnevfr(event) & arm_spe_pmsevfr_res0(spe_pmu->pmsver))
737+
return -EOPNOTSUPP;
738+
706739
if (attr->exclude_idle)
707740
return -EOPNOTSUPP;
708741

@@ -721,6 +754,10 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
721754
!(spe_pmu->features & SPE_PMU_FEAT_FILT_EVT))
722755
return -EOPNOTSUPP;
723756

757+
if ((FIELD_GET(PMSFCR_EL1_FnE, reg)) &&
758+
!(spe_pmu->features & SPE_PMU_FEAT_INV_FILT_EVT))
759+
return -EOPNOTSUPP;
760+
724761
if ((FIELD_GET(PMSFCR_EL1_FT, reg)) &&
725762
!(spe_pmu->features & SPE_PMU_FEAT_FILT_TYP))
726763
return -EOPNOTSUPP;
@@ -756,6 +793,11 @@ static void arm_spe_pmu_start(struct perf_event *event, int flags)
756793
reg = arm_spe_event_to_pmsevfr(event);
757794
write_sysreg_s(reg, SYS_PMSEVFR_EL1);
758795

796+
if (spe_pmu->features & SPE_PMU_FEAT_INV_FILT_EVT) {
797+
reg = arm_spe_event_to_pmsnevfr(event);
798+
write_sysreg_s(reg, SYS_PMSNEVFR_EL1);
799+
}
800+
759801
reg = arm_spe_event_to_pmslatfr(event);
760802
write_sysreg_s(reg, SYS_PMSLATFR_EL1);
761803

@@ -990,6 +1032,9 @@ static void __arm_spe_pmu_dev_probe(void *info)
9901032
if (FIELD_GET(PMSIDR_EL1_FE, reg))
9911033
spe_pmu->features |= SPE_PMU_FEAT_FILT_EVT;
9921034

1035+
if (FIELD_GET(PMSIDR_EL1_FnE, reg))
1036+
spe_pmu->features |= SPE_PMU_FEAT_INV_FILT_EVT;
1037+
9931038
if (FIELD_GET(PMSIDR_EL1_FT, reg))
9941039
spe_pmu->features |= SPE_PMU_FEAT_FILT_TYP;
9951040

0 commit comments

Comments
 (0)