Skip to content

Commit e6a2729

Browse files
james-c-linarowilldeacon
authored andcommitted
perf: arm_spe: Add support for filtering on data source
SPE_FEAT_FDS adds the ability to filter on the data source of packets. Like the other existing filters, enable filtering with PMSFCR_EL1.FDS when any of the filter bits are set. Each bit position of the 64 bit filter maps to numerical data sources 0-63 described by bits[0:5] in the data source packet (although the full range of data source is 16 bits so higher value data sources can't be filtered on). The filter is an OR of all the filter bits, so for example clearing filter bits 0 and 3 only includes packets from data sources 0 OR 3. Invert the filter given by userspace so that the default value of 0 is equivalent to including all values (no filtering). This allows us to skip adding a new format bit to enable filtering and still support excluding all data sources which would have been a filter value of 0 if not for the inversion. Tested-by: Leo Yan <leo.yan@arm.com> Reviewed-by: Leo Yan <leo.yan@arm.com> Signed-off-by: James Clark <james.clark@linaro.org> Signed-off-by: Will Deacon <will@kernel.org>
1 parent cbbfba4 commit e6a2729

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

drivers/perf/arm_spe_pmu.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ struct arm_spe_pmu {
8787
#define SPE_PMU_FEAT_INV_FILT_EVT (1UL << 6)
8888
#define SPE_PMU_FEAT_DISCARD (1UL << 7)
8989
#define SPE_PMU_FEAT_EFT (1UL << 8)
90+
#define SPE_PMU_FEAT_FDS (1UL << 9)
9091
#define SPE_PMU_FEAT_DEV_PROBED (1UL << 63)
9192
u64 features;
9293

@@ -252,6 +253,10 @@ static const struct attribute_group arm_spe_pmu_cap_group = {
252253
#define ATTR_CFG_FLD_inv_event_filter_LO 0
253254
#define ATTR_CFG_FLD_inv_event_filter_HI 63
254255

256+
#define ATTR_CFG_FLD_inv_data_src_filter_CFG config4 /* inverse of PMSDSFR_EL1 */
257+
#define ATTR_CFG_FLD_inv_data_src_filter_LO 0
258+
#define ATTR_CFG_FLD_inv_data_src_filter_HI 63
259+
255260
GEN_PMU_FORMAT_ATTR(ts_enable);
256261
GEN_PMU_FORMAT_ATTR(pa_enable);
257262
GEN_PMU_FORMAT_ATTR(pct_enable);
@@ -268,6 +273,7 @@ GEN_PMU_FORMAT_ATTR(float_filter);
268273
GEN_PMU_FORMAT_ATTR(float_filter_mask);
269274
GEN_PMU_FORMAT_ATTR(event_filter);
270275
GEN_PMU_FORMAT_ATTR(inv_event_filter);
276+
GEN_PMU_FORMAT_ATTR(inv_data_src_filter);
271277
GEN_PMU_FORMAT_ATTR(min_latency);
272278
GEN_PMU_FORMAT_ATTR(discard);
273279

@@ -288,6 +294,7 @@ static struct attribute *arm_spe_pmu_formats_attr[] = {
288294
&format_attr_float_filter_mask.attr,
289295
&format_attr_event_filter.attr,
290296
&format_attr_inv_event_filter.attr,
297+
&format_attr_inv_data_src_filter.attr,
291298
&format_attr_min_latency.attr,
292299
&format_attr_discard.attr,
293300
NULL,
@@ -306,6 +313,10 @@ static umode_t arm_spe_pmu_format_attr_is_visible(struct kobject *kobj,
306313
if (attr == &format_attr_inv_event_filter.attr && !(spe_pmu->features & SPE_PMU_FEAT_INV_FILT_EVT))
307314
return 0;
308315

316+
if (attr == &format_attr_inv_data_src_filter.attr &&
317+
!(spe_pmu->features & SPE_PMU_FEAT_FDS))
318+
return 0;
319+
309320
if ((attr == &format_attr_branch_filter_mask.attr ||
310321
attr == &format_attr_load_filter_mask.attr ||
311322
attr == &format_attr_store_filter_mask.attr ||
@@ -430,6 +441,9 @@ static u64 arm_spe_event_to_pmsfcr(struct perf_event *event)
430441
if (ATTR_CFG_GET_FLD(attr, inv_event_filter))
431442
reg |= PMSFCR_EL1_FnE;
432443

444+
if (ATTR_CFG_GET_FLD(attr, inv_data_src_filter))
445+
reg |= PMSFCR_EL1_FDS;
446+
433447
if (ATTR_CFG_GET_FLD(attr, min_latency))
434448
reg |= PMSFCR_EL1_FL;
435449

@@ -454,6 +468,17 @@ static u64 arm_spe_event_to_pmslatfr(struct perf_event *event)
454468
return FIELD_PREP(PMSLATFR_EL1_MINLAT, ATTR_CFG_GET_FLD(attr, min_latency));
455469
}
456470

471+
static u64 arm_spe_event_to_pmsdsfr(struct perf_event *event)
472+
{
473+
struct perf_event_attr *attr = &event->attr;
474+
475+
/*
476+
* Data src filter is inverted so that the default value of 0 is
477+
* equivalent to no filtering.
478+
*/
479+
return ~ATTR_CFG_GET_FLD(attr, inv_data_src_filter);
480+
}
481+
457482
static void arm_spe_pmu_pad_buf(struct perf_output_handle *handle, int len)
458483
{
459484
struct arm_spe_pmu_buf *buf = perf_get_aux(handle);
@@ -791,6 +816,10 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
791816
if (arm_spe_event_to_pmsnevfr(event) & spe_pmu->pmsevfr_res0)
792817
return -EOPNOTSUPP;
793818

819+
if (arm_spe_event_to_pmsdsfr(event) != U64_MAX &&
820+
!(spe_pmu->features & SPE_PMU_FEAT_FDS))
821+
return -EOPNOTSUPP;
822+
794823
if (attr->exclude_idle)
795824
return -EOPNOTSUPP;
796825

@@ -866,6 +895,11 @@ static void arm_spe_pmu_start(struct perf_event *event, int flags)
866895
write_sysreg_s(reg, SYS_PMSNEVFR_EL1);
867896
}
868897

898+
if (spe_pmu->features & SPE_PMU_FEAT_FDS) {
899+
reg = arm_spe_event_to_pmsdsfr(event);
900+
write_sysreg_s(reg, SYS_PMSDSFR_EL1);
901+
}
902+
869903
reg = arm_spe_event_to_pmslatfr(event);
870904
write_sysreg_s(reg, SYS_PMSLATFR_EL1);
871905

@@ -1125,6 +1159,9 @@ static void __arm_spe_pmu_dev_probe(void *info)
11251159
if (FIELD_GET(PMSIDR_EL1_EFT, reg))
11261160
spe_pmu->features |= SPE_PMU_FEAT_EFT;
11271161

1162+
if (FIELD_GET(PMSIDR_EL1_FDS, reg))
1163+
spe_pmu->features |= SPE_PMU_FEAT_FDS;
1164+
11281165
/* This field has a spaced out encoding, so just use a look-up */
11291166
fld = FIELD_GET(PMSIDR_EL1_INTERVAL, reg);
11301167
switch (fld) {

0 commit comments

Comments
 (0)