Skip to content

Commit 46eafba

Browse files
ouptonjannau
authored andcommitted
drivers/perf: apple_m1: Provide helper for mapping PMUv3 events
Apple M* parts carry some IMP DEF traps for guest accesses to PMUv3 registers, even though the underlying hardware doesn't implement PMUv3. This means it is possible to virtualize PMUv3 for KVM guests. Add a helper for mapping common PMUv3 event IDs onto hardware event IDs, keeping the implementation-specific crud in the PMU driver rather than KVM proper. Populate the pmceid_bitmap based on the supported events so KVM can provide synthetic PMCEID* values to the guest. Tested-by: Janne Grunau <j@jannau.net> Signed-off-by: Oliver Upton <oliver.upton@linux.dev> Reviewed-by: Marc Zyngier <maz@kernel.org>
1 parent b5be5d4 commit 46eafba

1 file changed

Lines changed: 35 additions & 0 deletions

File tree

drivers/perf/apple_m1_cpu_pmu.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include <linux/of.h>
1414
#include <linux/perf/arm_pmu.h>
15+
#include <linux/perf/arm_pmuv3.h>
1516
#include <linux/platform_device.h>
1617

1718
#include <asm/apple_m1_pmu.h>
@@ -172,6 +173,17 @@ static const unsigned m1_pmu_perf_map[PERF_COUNT_HW_MAX] = {
172173
[PERF_COUNT_HW_INSTRUCTIONS] = M1_PMU_PERFCTR_INST_ALL,
173174
};
174175

176+
#define M1_PMUV3_EVENT_MAP(pmuv3_event, m1_event) \
177+
[ARMV8_PMUV3_PERFCTR_##pmuv3_event] = M1_PMU_PERFCTR_##m1_event
178+
179+
static const u16 m1_pmu_pmceid_map[ARMV8_PMUV3_MAX_COMMON_EVENTS] = {
180+
[0 ... ARMV8_PMUV3_MAX_COMMON_EVENTS - 1] = HW_OP_UNSUPPORTED,
181+
M1_PMUV3_EVENT_MAP(INST_RETIRED, INST_ALL),
182+
M1_PMUV3_EVENT_MAP(CPU_CYCLES, CORE_ACTIVE_CYCLE),
183+
M1_PMUV3_EVENT_MAP(BR_RETIRED, INST_BRANCH),
184+
M1_PMUV3_EVENT_MAP(BR_MIS_PRED_RETIRED, BRANCH_MISPRED_NONSPEC),
185+
};
186+
175187
/* sysfs definitions */
176188
static ssize_t m1_pmu_events_sysfs_show(struct device *dev,
177189
struct device_attribute *attr,
@@ -556,6 +568,26 @@ static int m2_pmu_map_event(struct perf_event *event)
556568
return armpmu_map_event(event, &m1_pmu_perf_map, NULL, M1_PMU_CFG_EVENT);
557569
}
558570

571+
static int m1_pmu_map_pmuv3_event(unsigned int eventsel)
572+
{
573+
u16 m1_event = HW_OP_UNSUPPORTED;
574+
575+
if (eventsel < ARMV8_PMUV3_MAX_COMMON_EVENTS)
576+
m1_event = m1_pmu_pmceid_map[eventsel];
577+
578+
return m1_event == HW_OP_UNSUPPORTED ? -EOPNOTSUPP : m1_event;
579+
}
580+
581+
static void m1_pmu_init_pmceid(struct arm_pmu *pmu)
582+
{
583+
unsigned int event;
584+
585+
for (event = 0; event < ARMV8_PMUV3_MAX_COMMON_EVENTS; event++) {
586+
if (m1_pmu_map_pmuv3_event(event) >= 0)
587+
set_bit(event, pmu->pmceid_bitmap);
588+
}
589+
}
590+
559591
static void m1_pmu_reset(void *info)
560592
{
561593
int i;
@@ -616,6 +648,9 @@ static int m1_pmu_init(struct arm_pmu *cpu_pmu, u32 flags)
616648
cpu_pmu->reset = m1_pmu_reset;
617649
cpu_pmu->set_event_filter = m1_pmu_set_event_filter;
618650

651+
cpu_pmu->map_pmuv3_event = m1_pmu_map_pmuv3_event;
652+
m1_pmu_init_pmceid(cpu_pmu);
653+
619654
bitmap_set(cpu_pmu->cntr_mask, 0, M1_PMU_NR_COUNTERS);
620655
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS] = &m1_pmu_events_attr_group;
621656
cpu_pmu->attr_groups[ARMPMU_ATTR_GROUP_FORMATS] = &m1_pmu_format_attr_group;

0 commit comments

Comments
 (0)