On Thu, Apr 21, 2016 at 05:58:44AM -0700, Ashok Kumar wrote: > The complete common architectural and micro-architectural > event number structure is filtered based on PMCEIDn_EL0 and > exposed to /sys using is_visibile function pointer in events > attribute_group. > To filter the events in is_visible function, pmceid based bitmap > is stored in arm_pmu structure and the id field from > perf_pmu_events_attr is used to check against the bitmap. > > The function which derives event bitmap from PMCEIDn_EL0 is > executed in the cpus, which has the pmu being initialized, > for heterogeneous pmu support. > > Signed-off-by: Ashok Kumar <ashoks@xxxxxxxxxxxx> Acked-by: Mark Rutland <mark.rutland@xxxxxxx> Mark. > --- > arch/arm64/kernel/perf_event.c | 70 +++++++++++++++++++++++++++++++++--------- > include/linux/perf/arm_pmu.h | 2 ++ > 2 files changed, 57 insertions(+), 15 deletions(-) > > diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c > index 946ce4b..e6a0fdb 100644 > --- a/arch/arm64/kernel/perf_event.c > +++ b/arch/arm64/kernel/perf_event.c > @@ -326,10 +326,22 @@ static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] > [C(BPU)][C(OP_WRITE)][C(RESULT_MISS)] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED, > }; > > + > +static ssize_t > +armv8pmu_events_sysfs_show(struct device *dev, > + struct device_attribute *attr, char *page) > +{ > + struct perf_pmu_events_attr *pmu_attr; > + > + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr); > + > + return sprintf(page, "event=0x%03llx\n", pmu_attr->id); > +} > + > #define ARMV8_EVENT_ATTR_RESOLVE(m) #m > #define ARMV8_EVENT_ATTR(name, config) \ > - PMU_EVENT_ATTR_STRING(name, armv8_event_attr_##name, \ > - "event=" ARMV8_EVENT_ATTR_RESOLVE(config)) > + PMU_EVENT_ATTR(name, armv8_event_attr_##name, \ > + config, armv8pmu_events_sysfs_show) > > ARMV8_EVENT_ATTR(sw_incr, ARMV8_PMUV3_PERFCTR_SW_INCR); > ARMV8_EVENT_ATTR(l1i_cache_refill, ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL); > @@ -434,9 +446,27 @@ static struct attribute *armv8_pmuv3_event_attrs[] = { > NULL, > }; > > +static umode_t > +armv8pmu_event_attr_is_visible(struct kobject *kobj, > + struct attribute *attr, int unused) > +{ > + struct device *dev = kobj_to_dev(kobj); > + struct pmu *pmu = dev_get_drvdata(dev); > + struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu); > + struct perf_pmu_events_attr *pmu_attr; > + > + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr); > + > + if (test_bit(pmu_attr->id, cpu_pmu->pmceid_bitmap)) > + return attr->mode; > + > + return 0; > +} > + > static struct attribute_group armv8_pmuv3_events_attr_group = { > .name = "events", > .attrs = armv8_pmuv3_event_attrs, > + .is_visible = armv8pmu_event_attr_is_visible, > }; > > PMU_FORMAT_ATTR(event, "config:0-9"); > @@ -859,22 +889,31 @@ static int armv8_thunder_map_event(struct perf_event *event) > ARMV8_PMU_EVTYPE_EVENT); > } > > -static void armv8pmu_read_num_pmnc_events(void *info) > +static void __armv8pmu_probe_pmu(void *info) > { > - int *nb_cnt = info; > + struct arm_pmu *cpu_pmu = info; > + u32 pmceid[2]; > > /* Read the nb of CNTx counters supported from PMNC */ > - *nb_cnt = (armv8pmu_pmcr_read() >> ARMV8_PMU_PMCR_N_SHIFT) & ARMV8_PMU_PMCR_N_MASK; > + cpu_pmu->num_events = (armv8pmu_pmcr_read() >> ARMV8_PMU_PMCR_N_SHIFT) > + & ARMV8_PMU_PMCR_N_MASK; > > /* Add the CPU cycles counter */ > - *nb_cnt += 1; > + cpu_pmu->num_events += 1; > + > + pmceid[0] = read_sysreg(pmceid0_el0); > + pmceid[1] = read_sysreg(pmceid1_el0); > + > + bitmap_from_u32array(cpu_pmu->pmceid_bitmap, > + ARMV8_PMUV3_MAX_COMMON_EVENTS, pmceid, > + ARRAY_SIZE(pmceid)); > } > > -static int armv8pmu_probe_num_events(struct arm_pmu *arm_pmu) > +static int armv8pmu_probe_pmu(struct arm_pmu *cpu_pmu) > { > - return smp_call_function_any(&arm_pmu->supported_cpus, > - armv8pmu_read_num_pmnc_events, > - &arm_pmu->num_events, 1); > + return smp_call_function_any(&cpu_pmu->supported_cpus, > + __armv8pmu_probe_pmu, > + cpu_pmu, 1); > } > > static void armv8_pmu_init(struct arm_pmu *cpu_pmu) > @@ -897,7 +936,8 @@ static int armv8_pmuv3_init(struct arm_pmu *cpu_pmu) > armv8_pmu_init(cpu_pmu); > cpu_pmu->name = "armv8_pmuv3"; > cpu_pmu->map_event = armv8_pmuv3_map_event; > - return armv8pmu_probe_num_events(cpu_pmu); > + cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; > + return armv8pmu_probe_pmu(cpu_pmu); > } > > static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu) > @@ -906,7 +946,7 @@ static int armv8_a53_pmu_init(struct arm_pmu *cpu_pmu) > cpu_pmu->name = "armv8_cortex_a53"; > cpu_pmu->map_event = armv8_a53_map_event; > cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; > - return armv8pmu_probe_num_events(cpu_pmu); > + return armv8pmu_probe_pmu(cpu_pmu); > } > > static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu) > @@ -915,7 +955,7 @@ static int armv8_a57_pmu_init(struct arm_pmu *cpu_pmu) > cpu_pmu->name = "armv8_cortex_a57"; > cpu_pmu->map_event = armv8_a57_map_event; > cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; > - return armv8pmu_probe_num_events(cpu_pmu); > + return armv8pmu_probe_pmu(cpu_pmu); > } > > static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu) > @@ -924,7 +964,7 @@ static int armv8_a72_pmu_init(struct arm_pmu *cpu_pmu) > cpu_pmu->name = "armv8_cortex_a72"; > cpu_pmu->map_event = armv8_a57_map_event; > cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; > - return armv8pmu_probe_num_events(cpu_pmu); > + return armv8pmu_probe_pmu(cpu_pmu); > } > > static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu) > @@ -933,7 +973,7 @@ static int armv8_thunder_pmu_init(struct arm_pmu *cpu_pmu) > cpu_pmu->name = "armv8_cavium_thunder"; > cpu_pmu->map_event = armv8_thunder_map_event; > cpu_pmu->pmu.attr_groups = armv8_pmuv3_attr_groups; > - return armv8pmu_probe_num_events(cpu_pmu); > + return armv8pmu_probe_pmu(cpu_pmu); > } > > static const struct of_device_id armv8_pmu_of_device_ids[] = { > diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h > index 4196c90..d28ac05 100644 > --- a/include/linux/perf/arm_pmu.h > +++ b/include/linux/perf/arm_pmu.h > @@ -105,6 +105,8 @@ struct arm_pmu { > struct mutex reserve_mutex; > u64 max_period; > bool secure_access; /* 32-bit ARM only */ > +#define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40 > + DECLARE_BITMAP(pmceid_bitmap, ARMV8_PMUV3_MAX_COMMON_EVENTS); > struct platform_device *plat_device; > struct pmu_hw_events __percpu *hw_events; > struct notifier_block hotplug_nb; > -- > 2.1.0 > -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html