diff options
| author | Neil Leeder <nleeder@codeaurora.org> | 2014-10-30 13:17:08 -0400 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:58:10 -0700 |
| commit | 0e4ee435ac293483d156db59cabb14a8445f5979 (patch) | |
| tree | 04fd2eea5d09e732bdf5154b646e93cfe278f19c /arch | |
| parent | 86cd54bb1953eaebbd8d466672851c545342ead0 (diff) | |
Perf: arm64: support hotplug and power collapse
Add notifiers for hotplug and power collapse in perf events.
Preserve counters and user enables across these events.
Disable and enable interrupts across events.
This allows perf-events to be used in an environment where
cores are power collapsing and being hotplugged.
Change-Id: Id27ac3b1c0733677e0bc9740ce7534c3e5fdac7c
Signed-off-by: Neil Leeder <nleeder@codeaurora.org>
[satyap: merge conflict resolution and move changes in
arch/arm64/kernel/perf_event.c to drivers/perf/arm_pmu.c
to align with kernel 4.4]
Signed-off-by: Satya Durga Srinivasu Prabhala <satyap@codeaurora.org>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/arm64/kernel/perf_debug.c | 1 | ||||
| -rw-r--r-- | arch/arm64/kernel/perf_event.c | 33 |
2 files changed, 33 insertions, 1 deletions
diff --git a/arch/arm64/kernel/perf_debug.c b/arch/arm64/kernel/perf_debug.c index ef3313fd16c6..08e93a71fa7d 100644 --- a/arch/arm64/kernel/perf_debug.c +++ b/arch/arm64/kernel/perf_debug.c @@ -24,6 +24,7 @@ static char *descriptions = " 0 arm64: perf: add debug patch logging framework\n" " 1 Perf: arm64: Add L1 counters to tracepoints\n" + " 4 Perf: arm64: support hotplug and power collapse\n" " 5 Perf: arm64: add perf user-mode permissions\n" " 6 Perf: arm64: Add debugfs node to clear PMU\n" " 7 Perf: arm64: Update PMU force reset\n" diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index a03c001a19e7..ce8eb8f565e1 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -25,6 +25,8 @@ #include <linux/perf/arm_pmu.h> #include <linux/platform_device.h> +static DEFINE_PER_CPU(u32, armv8_pm_pmuserenr); + /* * ARMv8 PMUv3 Performance Events handling code. * Common event types. @@ -366,6 +368,7 @@ static void armv8pmu_enable_event(struct perf_event *event) struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu); struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events); int idx = hwc->idx; + u64 prev_count = local64_read(&hwc->prev_count); /* * Enable counter and interrupt, and set the counter to count @@ -389,6 +392,11 @@ static void armv8pmu_enable_event(struct perf_event *event) armv8pmu_enable_intens(idx); /* + * Restore previous value + */ + armv8pmu_write_counter(event, prev_count & 0xffffffff); + + /* * Enable counter */ armv8pmu_enable_counter(idx); @@ -599,6 +607,27 @@ static int armv8_pmuv3_map_event(struct perf_event *event) ARMV8_EVTYPE_EVENT); } +static void armv8pmu_save_pm_registers(void *hcpu) +{ + u32 val; + u64 lcpu = (u64)hcpu; + int cpu = (int)lcpu; + + asm volatile("mrs %0, pmuserenr_el0" : "=r" (val)); + per_cpu(armv8_pm_pmuserenr, cpu) = val; +} + +static void armv8pmu_restore_pm_registers(void *hcpu) +{ + u32 val; + u64 lcpu = (u64)hcpu; + int cpu = (int)lcpu; + + val = per_cpu(armv8_pm_pmuserenr, cpu); + if (val != 0) + asm volatile("msr pmuserenr_el0, %0" :: "r" (val)); +} + static int armv8_a53_map_event(struct perf_event *event) { return armpmu_map_event(event, &armv8_a53_perf_map, @@ -642,6 +671,8 @@ void armv8_pmu_init(struct arm_pmu *cpu_pmu) cpu_pmu->start = armv8pmu_start, cpu_pmu->stop = armv8pmu_stop, cpu_pmu->reset = armv8pmu_reset, + cpu_pmu->save_pm_registers = armv8pmu_save_pm_registers, + cpu_pmu->restore_pm_registers = armv8pmu_restore_pm_registers, cpu_pmu->max_period = (1LLU << 32) - 1, cpu_pmu->set_event_filter = armv8pmu_set_event_filter; } @@ -674,7 +705,7 @@ static const struct of_device_id armv8_pmu_of_device_ids[] = { {.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_init}, {.compatible = "arm,cortex-a53-pmu", .data = armv8_a53_pmu_init}, {.compatible = "arm,cortex-a57-pmu", .data = armv8_a57_pmu_init}, - {.compatible = "qcom,kryo-pmuv3", .data = kryo_pmu_init}, + {.compatible = "qcom,kryo-pmuv3", .data = kryo_pmu_init}, {}, }; |
