Skip to content

Commit a30b87e

Browse files
Stephane Eranianwilldeacon
authored andcommitted
arm64: pmuv3: dynamically map PERF_COUNT_HW_BRANCH_INSTRUCTIONS
The mapping of perf_events generic hardware events to actual PMU events on ARM PMUv3 may not always be correct. This is in particular true for the PERF_COUNT_HW_BRANCH_INSTRUCTIONS event. Although the mapping points to an architected event, it may not always be available. This can be seen with a simple: $ perf stat -e branches sleep 0 Performance counter stats for 'sleep 0': <not supported> branches 0.001401081 seconds time elapsed Yet the hardware does have an event that could be used for branches. Dynamically check for a supported hardware event which can be used for PERF_COUNT_HW_BRANCH_INSTRUCTIONS at mapping time. And with that: $ perf stat -e branches sleep 0 Performance counter stats for 'sleep 0': 166,739 branches 0.000832163 seconds time elapsed Co-developed-by: Stephane Eranian <[email protected]> Signed-off-by: Stephane Eranian <[email protected]> Co-developed-by: Mark Rutland <[email protected]> Signed-off-by: Mark Rutland <[email protected]> Co-developed-by: Peter Newman <[email protected]> Signed-off-by: Peter Newman <[email protected]> Link: https://lore.kernel.org/all/YvunKCJHSXKz%2FkZB@FVFF77S0Q05N Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent 23b2fd8 commit a30b87e

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

drivers/perf/arm_pmuv3.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
4646
[PERF_COUNT_HW_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_INST_RETIRED,
4747
[PERF_COUNT_HW_CACHE_REFERENCES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE,
4848
[PERF_COUNT_HW_CACHE_MISSES] = ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL,
49-
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
5049
[PERF_COUNT_HW_BRANCH_MISSES] = ARMV8_PMUV3_PERFCTR_BR_MIS_PRED,
5150
[PERF_COUNT_HW_BUS_CYCLES] = ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
5251
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
@@ -985,6 +984,28 @@ static void armv8pmu_reset(void *info)
985984
armv8pmu_pmcr_write(pmcr);
986985
}
987986

987+
static int __armv8_pmuv3_map_event_id(struct arm_pmu *armpmu,
988+
struct perf_event *event)
989+
{
990+
if (event->attr.type == PERF_TYPE_HARDWARE &&
991+
event->attr.config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) {
992+
993+
if (test_bit(ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED,
994+
armpmu->pmceid_bitmap))
995+
return ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED;
996+
997+
if (test_bit(ARMV8_PMUV3_PERFCTR_BR_RETIRED,
998+
armpmu->pmceid_bitmap))
999+
return ARMV8_PMUV3_PERFCTR_BR_RETIRED;
1000+
1001+
return HW_OP_UNSUPPORTED;
1002+
}
1003+
1004+
return armpmu_map_event(event, &armv8_pmuv3_perf_map,
1005+
&armv8_pmuv3_perf_cache_map,
1006+
ARMV8_PMU_EVTYPE_EVENT);
1007+
}
1008+
9881009
static int __armv8_pmuv3_map_event(struct perf_event *event,
9891010
const unsigned (*extra_event_map)
9901011
[PERF_COUNT_HW_MAX],
@@ -996,9 +1017,7 @@ static int __armv8_pmuv3_map_event(struct perf_event *event,
9961017
int hw_event_id;
9971018
struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
9981019

999-
hw_event_id = armpmu_map_event(event, &armv8_pmuv3_perf_map,
1000-
&armv8_pmuv3_perf_cache_map,
1001-
ARMV8_PMU_EVTYPE_EVENT);
1020+
hw_event_id = __armv8_pmuv3_map_event_id(armpmu, event);
10021021

10031022
/*
10041023
* CHAIN events only work when paired with an adjacent counter, and it

0 commit comments

Comments
 (0)