diff options
author | Pratyush Anand <panand@redhat.com> | 2017-07-01 12:03:35 +0530 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2017-08-08 14:33:13 +0100 |
commit | 1031a1592908ccd3240f4a5731c96c382c932310 (patch) | |
tree | dc0cae0b5281438118b5a0c16bd244e9f5e1d400 | |
parent | aae4e7a8bc44722fe70d58920a36916b1043195e (diff) |
arm64: perf: Allow more than one cycle counter to be used
Currently:
$ perf stat -e cycles:u -e cycles:k true
Performance counter stats for 'true':
2,24,699 cycles:u
<not counted> cycles:k (0.00%)
0.000788087 seconds time elapsed
We can not count more than one cycle counter in one instance,because we
allow to map cycle counter into PMCCNTR_EL0 only. However, if I did not
miss anything then specification do not prohibit to use PMEVCNTR<n>_EL0
for cycle count as well.
Modify the code so that it still prefers to use PMCCNTR_EL0 for cycle
counter, however allow to use PMEVCNTR<n>_EL0 if PMCCNTR_EL0 is already
in use.
After this patch:
$ perf stat -e cycles:u -e cycles:k true
Performance counter stats for 'true':
2,17,310 cycles:u
7,40,009 cycles:k
0.000764149 seconds time elapsed
Signed-off-by: Pratyush Anand <panand@redhat.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | arch/arm64/kernel/perf_event.c | 11 |
1 files changed, 4 insertions, 7 deletions
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index b5798ba21189..372317667773 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -846,17 +846,14 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc, struct hw_perf_event *hwc = &event->hw; unsigned long evtype = hwc->config_base & ARMV8_PMU_EVTYPE_EVENT; - /* Always place a cycle counter into the cycle counter. */ + /* Always prefer to place a cycle counter into the cycle counter. */ if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) { - if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) - return -EAGAIN; - - return ARMV8_IDX_CYCLE_COUNTER; + if (!test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask)) + return ARMV8_IDX_CYCLE_COUNTER; } /* - * For anything other than a cycle counter, try and use - * the events counters + * Otherwise use events counters */ for (idx = ARMV8_IDX_COUNTER0; idx < cpu_pmu->num_events; ++idx) { if (!test_and_set_bit(idx, cpuc->used_mask)) |