@@ -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);
232237GEN_PMU_FORMAT_ATTR (load_filter );
233238GEN_PMU_FORMAT_ATTR (store_filter );
234239GEN_PMU_FORMAT_ATTR (event_filter );
240+ GEN_PMU_FORMAT_ATTR (inv_event_filter );
235241GEN_PMU_FORMAT_ATTR (min_latency );
236242
237243static 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+
250270static 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+
358388static 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