Skip to content

Commit d28d95b

Browse files
james-c-linarowilldeacon
authored andcommitted
perf: arm_spe: Add format option for discard mode
FEAT_SPEv1p2 (optional from Armv8.6) adds a discard mode that allows all SPE data to be discarded rather than written to memory. Add a format bit for this mode. If the mode isn't supported, the format bit isn't published and attempts to use it will result in -EOPNOTSUPP. Allocating an aux buffer is still allowed even though it won't be written to so that old tools continue to work, but updated tools can choose to skip this step. Signed-off-by: James Clark <james.clark@linaro.org> Reviewd-by: Yeoreum Yun <yeoreum.yun@arm.com> Link: https://lore.kernel.org/r/20250108142904.401139-2-james.clark@linaro.org Signed-off-by: Will Deacon <will@kernel.org>
1 parent d00f343 commit d28d95b

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

drivers/perf/arm_spe_pmu.c

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

@@ -193,6 +194,9 @@ static const struct attribute_group arm_spe_pmu_cap_group = {
193194
#define ATTR_CFG_FLD_store_filter_CFG config /* PMSFCR_EL1.ST */
194195
#define ATTR_CFG_FLD_store_filter_LO 34
195196
#define ATTR_CFG_FLD_store_filter_HI 34
197+
#define ATTR_CFG_FLD_discard_CFG config /* PMBLIMITR_EL1.FM = DISCARD */
198+
#define ATTR_CFG_FLD_discard_LO 35
199+
#define ATTR_CFG_FLD_discard_HI 35
196200

197201
#define ATTR_CFG_FLD_event_filter_CFG config1 /* PMSEVFR_EL1 */
198202
#define ATTR_CFG_FLD_event_filter_LO 0
@@ -216,6 +220,7 @@ GEN_PMU_FORMAT_ATTR(store_filter);
216220
GEN_PMU_FORMAT_ATTR(event_filter);
217221
GEN_PMU_FORMAT_ATTR(inv_event_filter);
218222
GEN_PMU_FORMAT_ATTR(min_latency);
223+
GEN_PMU_FORMAT_ATTR(discard);
219224

220225
static struct attribute *arm_spe_pmu_formats_attr[] = {
221226
&format_attr_ts_enable.attr,
@@ -228,6 +233,7 @@ static struct attribute *arm_spe_pmu_formats_attr[] = {
228233
&format_attr_event_filter.attr,
229234
&format_attr_inv_event_filter.attr,
230235
&format_attr_min_latency.attr,
236+
&format_attr_discard.attr,
231237
NULL,
232238
};
233239

@@ -238,6 +244,9 @@ static umode_t arm_spe_pmu_format_attr_is_visible(struct kobject *kobj,
238244
struct device *dev = kobj_to_dev(kobj);
239245
struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev);
240246

247+
if (attr == &format_attr_discard.attr && !(spe_pmu->features & SPE_PMU_FEAT_DISCARD))
248+
return 0;
249+
241250
if (attr == &format_attr_inv_event_filter.attr && !(spe_pmu->features & SPE_PMU_FEAT_INV_FILT_EVT))
242251
return 0;
243252

@@ -502,6 +511,12 @@ static void arm_spe_perf_aux_output_begin(struct perf_output_handle *handle,
502511
u64 base, limit;
503512
struct arm_spe_pmu_buf *buf;
504513

514+
if (ATTR_CFG_GET_FLD(&event->attr, discard)) {
515+
limit = FIELD_PREP(PMBLIMITR_EL1_FM, PMBLIMITR_EL1_FM_DISCARD);
516+
limit |= PMBLIMITR_EL1_E;
517+
goto out_write_limit;
518+
}
519+
505520
/* Start a new aux session */
506521
buf = perf_aux_output_begin(handle, event);
507522
if (!buf) {
@@ -743,6 +758,10 @@ static int arm_spe_pmu_event_init(struct perf_event *event)
743758
!(spe_pmu->features & SPE_PMU_FEAT_FILT_LAT))
744759
return -EOPNOTSUPP;
745760

761+
if (ATTR_CFG_GET_FLD(&event->attr, discard) &&
762+
!(spe_pmu->features & SPE_PMU_FEAT_DISCARD))
763+
return -EOPNOTSUPP;
764+
746765
set_spe_event_has_cx(event);
747766
reg = arm_spe_event_to_pmscr(event);
748767
if (reg & (PMSCR_EL1_PA | PMSCR_EL1_PCT))
@@ -1027,6 +1046,9 @@ static void __arm_spe_pmu_dev_probe(void *info)
10271046
if (FIELD_GET(PMSIDR_EL1_ERND, reg))
10281047
spe_pmu->features |= SPE_PMU_FEAT_ERND;
10291048

1049+
if (spe_pmu->pmsver >= ID_AA64DFR0_EL1_PMSVer_V1P2)
1050+
spe_pmu->features |= SPE_PMU_FEAT_DISCARD;
1051+
10301052
/* This field has a spaced out encoding, so just use a look-up */
10311053
fld = FIELD_GET(PMSIDR_EL1_INTERVAL, reg);
10321054
switch (fld) {

0 commit comments

Comments
 (0)