@@ -85,6 +85,7 @@ struct arm_spe_pmu {
85
85
#define SPE_PMU_FEAT_ARCH_INST (1UL << 3)
86
86
#define SPE_PMU_FEAT_LDS (1UL << 4)
87
87
#define SPE_PMU_FEAT_ERND (1UL << 5)
88
+ #define SPE_PMU_FEAT_INV_FILT_EVT (1UL << 6)
88
89
#define SPE_PMU_FEAT_DEV_PROBED (1UL << 63)
89
90
u64 features ;
90
91
@@ -202,6 +203,10 @@ static const struct attribute_group arm_spe_pmu_cap_group = {
202
203
#define ATTR_CFG_FLD_min_latency_LO 0
203
204
#define ATTR_CFG_FLD_min_latency_HI 11
204
205
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
+
205
210
/* Why does everything I do descend into this? */
206
211
#define __GEN_PMU_FORMAT_ATTR (cfg , lo , hi ) \
207
212
(lo) == (hi) ? #cfg ":" #lo "\n" : #cfg ":" #lo "-" #hi
@@ -232,6 +237,7 @@ GEN_PMU_FORMAT_ATTR(branch_filter);
232
237
GEN_PMU_FORMAT_ATTR (load_filter );
233
238
GEN_PMU_FORMAT_ATTR (store_filter );
234
239
GEN_PMU_FORMAT_ATTR (event_filter );
240
+ GEN_PMU_FORMAT_ATTR (inv_event_filter );
235
241
GEN_PMU_FORMAT_ATTR (min_latency );
236
242
237
243
static struct attribute * arm_spe_pmu_formats_attr [] = {
@@ -243,12 +249,27 @@ static struct attribute *arm_spe_pmu_formats_attr[] = {
243
249
& format_attr_load_filter .attr ,
244
250
& format_attr_store_filter .attr ,
245
251
& format_attr_event_filter .attr ,
252
+ & format_attr_inv_event_filter .attr ,
246
253
& format_attr_min_latency .attr ,
247
254
NULL ,
248
255
};
249
256
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
+
250
270
static const struct attribute_group arm_spe_pmu_format_group = {
251
271
.name = "format" ,
272
+ .is_visible = arm_spe_pmu_format_attr_is_visible ,
252
273
.attrs = arm_spe_pmu_formats_attr ,
253
274
};
254
275
@@ -343,6 +364,9 @@ static u64 arm_spe_event_to_pmsfcr(struct perf_event *event)
343
364
if (ATTR_CFG_GET_FLD (attr , event_filter ))
344
365
reg |= PMSFCR_EL1_FE ;
345
366
367
+ if (ATTR_CFG_GET_FLD (attr , inv_event_filter ))
368
+ reg |= PMSFCR_EL1_FnE ;
369
+
346
370
if (ATTR_CFG_GET_FLD (attr , min_latency ))
347
371
reg |= PMSFCR_EL1_FL ;
348
372
@@ -355,6 +379,12 @@ static u64 arm_spe_event_to_pmsevfr(struct perf_event *event)
355
379
return ATTR_CFG_GET_FLD (attr , event_filter );
356
380
}
357
381
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
+
358
388
static u64 arm_spe_event_to_pmslatfr (struct perf_event * event )
359
389
{
360
390
struct perf_event_attr * attr = & event -> attr ;
@@ -703,6 +733,9 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
703
733
if (arm_spe_event_to_pmsevfr (event ) & arm_spe_pmsevfr_res0 (spe_pmu -> pmsver ))
704
734
return - EOPNOTSUPP ;
705
735
736
+ if (arm_spe_event_to_pmsnevfr (event ) & arm_spe_pmsevfr_res0 (spe_pmu -> pmsver ))
737
+ return - EOPNOTSUPP ;
738
+
706
739
if (attr -> exclude_idle )
707
740
return - EOPNOTSUPP ;
708
741
@@ -721,6 +754,10 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
721
754
!(spe_pmu -> features & SPE_PMU_FEAT_FILT_EVT ))
722
755
return - EOPNOTSUPP ;
723
756
757
+ if ((FIELD_GET (PMSFCR_EL1_FnE , reg )) &&
758
+ !(spe_pmu -> features & SPE_PMU_FEAT_INV_FILT_EVT ))
759
+ return - EOPNOTSUPP ;
760
+
724
761
if ((FIELD_GET (PMSFCR_EL1_FT , reg )) &&
725
762
!(spe_pmu -> features & SPE_PMU_FEAT_FILT_TYP ))
726
763
return - EOPNOTSUPP ;
@@ -756,6 +793,11 @@ static void arm_spe_pmu_start(struct perf_event *event, int flags)
756
793
reg = arm_spe_event_to_pmsevfr (event );
757
794
write_sysreg_s (reg , SYS_PMSEVFR_EL1 );
758
795
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
+
759
801
reg = arm_spe_event_to_pmslatfr (event );
760
802
write_sysreg_s (reg , SYS_PMSLATFR_EL1 );
761
803
@@ -990,6 +1032,9 @@ static void __arm_spe_pmu_dev_probe(void *info)
990
1032
if (FIELD_GET (PMSIDR_EL1_FE , reg ))
991
1033
spe_pmu -> features |= SPE_PMU_FEAT_FILT_EVT ;
992
1034
1035
+ if (FIELD_GET (PMSIDR_EL1_FnE , reg ))
1036
+ spe_pmu -> features |= SPE_PMU_FEAT_INV_FILT_EVT ;
1037
+
993
1038
if (FIELD_GET (PMSIDR_EL1_FT , reg ))
994
1039
spe_pmu -> features |= SPE_PMU_FEAT_FILT_TYP ;
995
1040
0 commit comments