Skip to content

Commit dad9603

Browse files
james-c-linarowilldeacon
authored andcommitted
perf: arm_spe: Add support for FEAT_SPE_EFT extended filtering
FEAT_SPE_EFT (optional from Armv9.4) adds mask bits for the existing load, store and branch filters. It also adds two new filter bits for SIMD and floating point with their own associated mask bits. The current filters only allow OR filtering on samples that are load OR store etc, and the new mask bits allow setting part of the filter to an AND, for example filtering samples that are store AND SIMD. With mask bits set to 0, the OR behavior is preserved, so the unless any masks are explicitly set old filters will behave the same. Add them all and make them behave the same way as existing format bits, hidden and return EOPNOTSUPP if set when the feature doesn't exist. Reviewed-by: Leo Yan <[email protected]> Tested-by: Leo Yan <[email protected]> Signed-off-by: James Clark <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 51b9f16 commit dad9603

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

drivers/perf/arm_spe_pmu.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ struct arm_spe_pmu {
8686
#define SPE_PMU_FEAT_ERND (1UL << 5)
8787
#define SPE_PMU_FEAT_INV_FILT_EVT (1UL << 6)
8888
#define SPE_PMU_FEAT_DISCARD (1UL << 7)
89+
#define SPE_PMU_FEAT_EFT (1UL << 8)
8990
#define SPE_PMU_FEAT_DEV_PROBED (1UL << 63)
9091
u64 features;
9192

@@ -216,6 +217,27 @@ static const struct attribute_group arm_spe_pmu_cap_group = {
216217
#define ATTR_CFG_FLD_discard_CFG config /* PMBLIMITR_EL1.FM = DISCARD */
217218
#define ATTR_CFG_FLD_discard_LO 35
218219
#define ATTR_CFG_FLD_discard_HI 35
220+
#define ATTR_CFG_FLD_branch_filter_mask_CFG config /* PMSFCR_EL1.Bm */
221+
#define ATTR_CFG_FLD_branch_filter_mask_LO 36
222+
#define ATTR_CFG_FLD_branch_filter_mask_HI 36
223+
#define ATTR_CFG_FLD_load_filter_mask_CFG config /* PMSFCR_EL1.LDm */
224+
#define ATTR_CFG_FLD_load_filter_mask_LO 37
225+
#define ATTR_CFG_FLD_load_filter_mask_HI 37
226+
#define ATTR_CFG_FLD_store_filter_mask_CFG config /* PMSFCR_EL1.STm */
227+
#define ATTR_CFG_FLD_store_filter_mask_LO 38
228+
#define ATTR_CFG_FLD_store_filter_mask_HI 38
229+
#define ATTR_CFG_FLD_simd_filter_CFG config /* PMSFCR_EL1.SIMD */
230+
#define ATTR_CFG_FLD_simd_filter_LO 39
231+
#define ATTR_CFG_FLD_simd_filter_HI 39
232+
#define ATTR_CFG_FLD_simd_filter_mask_CFG config /* PMSFCR_EL1.SIMDm */
233+
#define ATTR_CFG_FLD_simd_filter_mask_LO 40
234+
#define ATTR_CFG_FLD_simd_filter_mask_HI 40
235+
#define ATTR_CFG_FLD_float_filter_CFG config /* PMSFCR_EL1.FP */
236+
#define ATTR_CFG_FLD_float_filter_LO 41
237+
#define ATTR_CFG_FLD_float_filter_HI 41
238+
#define ATTR_CFG_FLD_float_filter_mask_CFG config /* PMSFCR_EL1.FPm */
239+
#define ATTR_CFG_FLD_float_filter_mask_LO 42
240+
#define ATTR_CFG_FLD_float_filter_mask_HI 42
219241

220242
#define ATTR_CFG_FLD_event_filter_CFG config1 /* PMSEVFR_EL1 */
221243
#define ATTR_CFG_FLD_event_filter_LO 0
@@ -234,8 +256,15 @@ GEN_PMU_FORMAT_ATTR(pa_enable);
234256
GEN_PMU_FORMAT_ATTR(pct_enable);
235257
GEN_PMU_FORMAT_ATTR(jitter);
236258
GEN_PMU_FORMAT_ATTR(branch_filter);
259+
GEN_PMU_FORMAT_ATTR(branch_filter_mask);
237260
GEN_PMU_FORMAT_ATTR(load_filter);
261+
GEN_PMU_FORMAT_ATTR(load_filter_mask);
238262
GEN_PMU_FORMAT_ATTR(store_filter);
263+
GEN_PMU_FORMAT_ATTR(store_filter_mask);
264+
GEN_PMU_FORMAT_ATTR(simd_filter);
265+
GEN_PMU_FORMAT_ATTR(simd_filter_mask);
266+
GEN_PMU_FORMAT_ATTR(float_filter);
267+
GEN_PMU_FORMAT_ATTR(float_filter_mask);
239268
GEN_PMU_FORMAT_ATTR(event_filter);
240269
GEN_PMU_FORMAT_ATTR(inv_event_filter);
241270
GEN_PMU_FORMAT_ATTR(min_latency);
@@ -247,8 +276,15 @@ static struct attribute *arm_spe_pmu_formats_attr[] = {
247276
&format_attr_pct_enable.attr,
248277
&format_attr_jitter.attr,
249278
&format_attr_branch_filter.attr,
279+
&format_attr_branch_filter_mask.attr,
250280
&format_attr_load_filter.attr,
281+
&format_attr_load_filter_mask.attr,
251282
&format_attr_store_filter.attr,
283+
&format_attr_store_filter_mask.attr,
284+
&format_attr_simd_filter.attr,
285+
&format_attr_simd_filter_mask.attr,
286+
&format_attr_float_filter.attr,
287+
&format_attr_float_filter_mask.attr,
252288
&format_attr_event_filter.attr,
253289
&format_attr_inv_event_filter.attr,
254290
&format_attr_min_latency.attr,
@@ -269,6 +305,16 @@ static umode_t arm_spe_pmu_format_attr_is_visible(struct kobject *kobj,
269305
if (attr == &format_attr_inv_event_filter.attr && !(spe_pmu->features & SPE_PMU_FEAT_INV_FILT_EVT))
270306
return 0;
271307

308+
if ((attr == &format_attr_branch_filter_mask.attr ||
309+
attr == &format_attr_load_filter_mask.attr ||
310+
attr == &format_attr_store_filter_mask.attr ||
311+
attr == &format_attr_simd_filter.attr ||
312+
attr == &format_attr_simd_filter_mask.attr ||
313+
attr == &format_attr_float_filter.attr ||
314+
attr == &format_attr_float_filter_mask.attr) &&
315+
!(spe_pmu->features & SPE_PMU_FEAT_EFT))
316+
return 0;
317+
272318
return attr->mode;
273319
}
274320

@@ -364,8 +410,15 @@ static u64 arm_spe_event_to_pmsfcr(struct perf_event *event)
364410
u64 reg = 0;
365411

366412
reg |= FIELD_PREP(PMSFCR_EL1_LD, ATTR_CFG_GET_FLD(attr, load_filter));
413+
reg |= FIELD_PREP(PMSFCR_EL1_LDm, ATTR_CFG_GET_FLD(attr, load_filter_mask));
367414
reg |= FIELD_PREP(PMSFCR_EL1_ST, ATTR_CFG_GET_FLD(attr, store_filter));
415+
reg |= FIELD_PREP(PMSFCR_EL1_STm, ATTR_CFG_GET_FLD(attr, store_filter_mask));
368416
reg |= FIELD_PREP(PMSFCR_EL1_B, ATTR_CFG_GET_FLD(attr, branch_filter));
417+
reg |= FIELD_PREP(PMSFCR_EL1_Bm, ATTR_CFG_GET_FLD(attr, branch_filter_mask));
418+
reg |= FIELD_PREP(PMSFCR_EL1_SIMD, ATTR_CFG_GET_FLD(attr, simd_filter));
419+
reg |= FIELD_PREP(PMSFCR_EL1_SIMDm, ATTR_CFG_GET_FLD(attr, simd_filter_mask));
420+
reg |= FIELD_PREP(PMSFCR_EL1_FP, ATTR_CFG_GET_FLD(attr, float_filter));
421+
reg |= FIELD_PREP(PMSFCR_EL1_FPm, ATTR_CFG_GET_FLD(attr, float_filter_mask));
369422

370423
if (reg)
371424
reg |= PMSFCR_EL1_FT;
@@ -767,6 +820,16 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
767820
!(spe_pmu->features & SPE_PMU_FEAT_FILT_LAT))
768821
return -EOPNOTSUPP;
769822

823+
if ((FIELD_GET(PMSFCR_EL1_LDm, reg) ||
824+
FIELD_GET(PMSFCR_EL1_STm, reg) ||
825+
FIELD_GET(PMSFCR_EL1_Bm, reg) ||
826+
FIELD_GET(PMSFCR_EL1_SIMD, reg) ||
827+
FIELD_GET(PMSFCR_EL1_SIMDm, reg) ||
828+
FIELD_GET(PMSFCR_EL1_FP, reg) ||
829+
FIELD_GET(PMSFCR_EL1_FPm, reg)) &&
830+
!(spe_pmu->features & SPE_PMU_FEAT_EFT))
831+
return -EOPNOTSUPP;
832+
770833
if (ATTR_CFG_GET_FLD(&event->attr, discard) &&
771834
!(spe_pmu->features & SPE_PMU_FEAT_DISCARD))
772835
return -EOPNOTSUPP;
@@ -1058,6 +1121,9 @@ static void __arm_spe_pmu_dev_probe(void *info)
10581121
if (spe_pmu->pmsver >= ID_AA64DFR0_EL1_PMSVer_V1P2)
10591122
spe_pmu->features |= SPE_PMU_FEAT_DISCARD;
10601123

1124+
if (FIELD_GET(PMSIDR_EL1_EFT, reg))
1125+
spe_pmu->features |= SPE_PMU_FEAT_EFT;
1126+
10611127
/* This field has a spaced out encoding, so just use a look-up */
10621128
fld = FIELD_GET(PMSIDR_EL1_INTERVAL, reg);
10631129
switch (fld) {

0 commit comments

Comments
 (0)