From: Lorenzo Pieralisi <hidden> Date: 2016-02-23 18:22:39
When a CPU is suspended (either through suspend-to-RAM or CPUidle),
its PMU registers content can be lost, which means that counters
registers values that were initialized on power down entry have to be
reprogrammed on power-up to make sure the counters set-up is preserved
(ie on power-up registers take the reset values on Cold or Warm reset,
which can be architecturally UNKNOWN).
To guarantee seamless profiling conditions across a core power down
this patch adds a CPU PM notifier to ARM pmus, that upon CPU PM
entry/exit from low-power states saves/restores the pmu registers
set-up (by using the ARM perf API), so that the power-down/up cycle does
not affect the perf behaviour (apart from a black-out period between
power-up/down CPU PM notifications that is unavoidable).
Signed-off-by: Lorenzo Pieralisi <redacted>
Cc: Ashwin Chaugule <redacted>
Cc: Will Deacon <redacted>
Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Sudeep Holla <redacted>
Cc: Daniel Lezcano <redacted>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
---
drivers/perf/arm_pmu.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/perf/arm_pmu.h | 1 +
2 files changed, 96 insertions(+)
@@ -710,6 +711,93 @@ static int cpu_pmu_notify(struct notifier_block *b, unsigned long action,returnNOTIFY_OK;}+#ifdef CONFIG_CPU_PM+staticvoidcpu_pm_pmu_setup(structarm_pmu*armpmu,unsignedlongcmd)+{+structpmu_hw_events*hw_events=this_cpu_ptr(armpmu->hw_events);+structperf_event*event;+intidx;++for(idx=0;idx<armpmu->num_events;idx++){+/*+*Ifthecounterisnotusedskipit,thereisno+*needofstopping/restartingit.+*/+if(!test_bit(idx,hw_events->used_mask))+continue;++event=hw_events->events[idx];++switch(cmd){+caseCPU_PM_ENTER:+/*+*Stopandupdatethecounter+*/+armpmu_stop(event,PERF_EF_UPDATE);+break;+caseCPU_PM_EXIT:+caseCPU_PM_ENTER_FAILED:+/* Restore and enable the counter */+armpmu_start(event,PERF_EF_RELOAD);+break;+default:+break;+}+}+}++staticintcpu_pm_pmu_notify(structnotifier_block*b,unsignedlongcmd,+void*v)+{+structarm_pmu*armpmu=container_of(b,structarm_pmu,cpu_pm_nb);+structpmu_hw_events*hw_events=this_cpu_ptr(armpmu->hw_events);+intenabled=bitmap_weight(hw_events->used_mask,armpmu->num_events);++if(!cpumask_test_cpu(smp_processor_id(),&armpmu->supported_cpus))+returnNOTIFY_DONE;++/*+*AlwaysresetthePMUregistersonpower-upevenif+*therearenoeventsrunning.+*/+if(cmd==CPU_PM_EXIT&&armpmu->reset)+armpmu->reset(armpmu);++if(!enabled)+returnNOTIFY_OK;++switch(cmd){+caseCPU_PM_ENTER:+armpmu->stop(armpmu);+cpu_pm_pmu_setup(armpmu,cmd);+break;+caseCPU_PM_EXIT:+cpu_pm_pmu_setup(armpmu,cmd);+caseCPU_PM_ENTER_FAILED:+armpmu->start(armpmu);+break;+default:+returnNOTIFY_DONE;+}++returnNOTIFY_OK;+}++staticintcpu_pm_pmu_register(structarm_pmu*cpu_pmu)+{+cpu_pmu->cpu_pm_nb.notifier_call=cpu_pm_pmu_notify;+returncpu_pm_register_notifier(&cpu_pmu->cpu_pm_nb);+}++staticvoidcpu_pm_pmu_unregister(structarm_pmu*cpu_pmu)+{+cpu_pm_unregister_notifier(&cpu_pmu->cpu_pm_nb);+}+#else+staticinlineintcpu_pm_pmu_register(structarm_pmu*cpu_pmu){return0;}+staticinlinevoidcpu_pm_pmu_unregister(structarm_pmu*cpu_pmu){}+#endif+staticintcpu_pmu_init(structarm_pmu*cpu_pmu){interr;
@@ -725,6 +813,10 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)if(err)gotoout_hw_events;+err=cpu_pm_pmu_register(cpu_pmu);+if(err)+gotoout_unregister;+for_each_possible_cpu(cpu){structpmu_hw_events*events=per_cpu_ptr(cpu_hw_events,cpu);raw_spin_lock_init(&events->pmu_lock);
@@ -746,6 +838,8 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu)return0;+out_unregister:+unregister_cpu_notifier(&cpu_pmu->hotplug_nb);out_hw_events:free_percpu(cpu_hw_events);returnerr;
On 23 February 2016 at 11:22, Lorenzo Pieralisi
[off-list ref] wrote:
quoted hunk
When a CPU is suspended (either through suspend-to-RAM or CPUidle),
its PMU registers content can be lost, which means that counters
registers values that were initialized on power down entry have to be
reprogrammed on power-up to make sure the counters set-up is preserved
(ie on power-up registers take the reset values on Cold or Warm reset,
which can be architecturally UNKNOWN).
To guarantee seamless profiling conditions across a core power down
this patch adds a CPU PM notifier to ARM pmus, that upon CPU PM
entry/exit from low-power states saves/restores the pmu registers
set-up (by using the ARM perf API), so that the power-down/up cycle does
not affect the perf behaviour (apart from a black-out period between
power-up/down CPU PM notifications that is unavoidable).
Signed-off-by: Lorenzo Pieralisi <redacted>
Cc: Ashwin Chaugule <redacted>
Cc: Will Deacon <redacted>
Cc: Kevin Hilman <khilman@baylibre.com>
Cc: Sudeep Holla <redacted>
Cc: Daniel Lezcano <redacted>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
---
drivers/perf/arm_pmu.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/perf/arm_pmu.h | 1 +
2 files changed, 96 insertions(+)
@@ -710,6 +711,93 @@ static int cpu_pmu_notify(struct notifier_block *b, unsigned long action,returnNOTIFY_OK;}+#ifdef CONFIG_CPU_PM+staticvoidcpu_pm_pmu_setup(structarm_pmu*armpmu,unsignedlongcmd)+{+structpmu_hw_events*hw_events=this_cpu_ptr(armpmu->hw_events);+structperf_event*event;+intidx;++for(idx=0;idx<armpmu->num_events;idx++){+/*+*Ifthecounterisnotusedskipit,thereisno+*needofstopping/restartingit.+*/+if(!test_bit(idx,hw_events->used_mask))+continue;++event=hw_events->events[idx];++switch(cmd){+caseCPU_PM_ENTER:+/*+*Stopandupdatethecounter+*/+armpmu_stop(event,PERF_EF_UPDATE);+break;+caseCPU_PM_EXIT:+caseCPU_PM_ENTER_FAILED:+/* Restore and enable the counter */+armpmu_start(event,PERF_EF_RELOAD);+break;+default:+break;+}+}+}++staticintcpu_pm_pmu_notify(structnotifier_block*b,unsignedlongcmd,+void*v)+{+structarm_pmu*armpmu=container_of(b,structarm_pmu,cpu_pm_nb);+structpmu_hw_events*hw_events=this_cpu_ptr(armpmu->hw_events);+intenabled=bitmap_weight(hw_events->used_mask,armpmu->num_events);++if(!cpumask_test_cpu(smp_processor_id(),&armpmu->supported_cpus))+returnNOTIFY_DONE;++/*+*AlwaysresetthePMUregistersonpower-upevenif+*therearenoeventsrunning.+*/+if(cmd==CPU_PM_EXIT&&armpmu->reset)+armpmu->reset(armpmu);
I think this patch does the right thing but I can't get the above
reset. Wouldn't it be better to do the reset as part of the
CPU_PM_EXIT case below? At this point nothing tells us the CPU won't
go back down before the event is enabled, wasting the cycle needed to
reset the PMU.
Thanks,
Mathieu
From: Lorenzo Pieralisi <hidden> Date: 2016-02-24 17:35:11
On Wed, Feb 24, 2016 at 09:20:22AM -0700, Mathieu Poirier wrote:
On 23 February 2016 at 11:22, Lorenzo Pieralisi
[...]
quoted
+static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
+ void *v)
+{
+ struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
+ struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
+ int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+
+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
+ return NOTIFY_DONE;
+
+ /*
+ * Always reset the PMU registers on power-up even if
+ * there are no events running.
+ */
+ if (cmd == CPU_PM_EXIT && armpmu->reset)
+ armpmu->reset(armpmu);
I think this patch does the right thing but I can't get the above
reset. Wouldn't it be better to do the reset as part of the
CPU_PM_EXIT case below? At this point nothing tells us the CPU won't
go back down before the event is enabled, wasting the cycle needed to
reset the PMU.
The logic goes, if the cpu is woken up and it has no events enabled,
if we do not reset it (mind, ->reset here sets the PMU register values
to a sane default, some of them are architecturally UNKNOWN on reset, it
does NOT reset the PMU) _and_ we subsequently install an event on it we
do have a problem, that's why whenever a core gets out of low-power we
have to reset its pmu.
Does it make sense ?
Thanks,
Lorenzo
Hi Lorenzo,
On 24 February 2016 at 12:35, Lorenzo Pieralisi
[off-list ref] wrote:
On Wed, Feb 24, 2016 at 09:20:22AM -0700, Mathieu Poirier wrote:
quoted
On 23 February 2016 at 11:22, Lorenzo Pieralisi
[...]
quoted
quoted
+static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
+ void *v)
+{
+ struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
+ struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
+ int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+
+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
+ return NOTIFY_DONE;
+
+ /*
+ * Always reset the PMU registers on power-up even if
+ * there are no events running.
+ */
+ if (cmd == CPU_PM_EXIT && armpmu->reset)
+ armpmu->reset(armpmu);
I think this patch does the right thing but I can't get the above
reset. Wouldn't it be better to do the reset as part of the
CPU_PM_EXIT case below? At this point nothing tells us the CPU won't
go back down before the event is enabled, wasting the cycle needed to
reset the PMU.
The logic goes, if the cpu is woken up and it has no events enabled,
if we do not reset it (mind, ->reset here sets the PMU register values
to a sane default, some of them are architecturally UNKNOWN on reset, it
does NOT reset the PMU) _and_ we subsequently install an event on it we
do have a problem, that's why whenever a core gets out of low-power we
have to reset its pmu.
Dont we blow out the previous value in the counter when installing an
event? Or has that changed lately? IIRC, there was some initial value
we'd program into the counter to avoid missing the overflow event.
(sorry its been too long) ;)
Cheers,
Ashwin.
From: Lorenzo Pieralisi <hidden> Date: 2016-02-24 22:31:28
On Wed, Feb 24, 2016 at 02:53:02PM -0500, Ashwin Chaugule wrote:
Hi Lorenzo,
On 24 February 2016 at 12:35, Lorenzo Pieralisi
[off-list ref] wrote:
quoted
On Wed, Feb 24, 2016 at 09:20:22AM -0700, Mathieu Poirier wrote:
quoted
On 23 February 2016 at 11:22, Lorenzo Pieralisi
[...]
quoted
quoted
+static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
+ void *v)
+{
+ struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
+ struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
+ int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+
+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
+ return NOTIFY_DONE;
+
+ /*
+ * Always reset the PMU registers on power-up even if
+ * there are no events running.
+ */
+ if (cmd == CPU_PM_EXIT && armpmu->reset)
+ armpmu->reset(armpmu);
I think this patch does the right thing but I can't get the above
reset. Wouldn't it be better to do the reset as part of the
CPU_PM_EXIT case below? At this point nothing tells us the CPU won't
go back down before the event is enabled, wasting the cycle needed to
reset the PMU.
The logic goes, if the cpu is woken up and it has no events enabled,
if we do not reset it (mind, ->reset here sets the PMU register values
to a sane default, some of them are architecturally UNKNOWN on reset, it
does NOT reset the PMU) _and_ we subsequently install an event on it we
do have a problem, that's why whenever a core gets out of low-power we
have to reset its pmu.
Dont we blow out the previous value in the counter when installing an
event? Or has that changed lately? IIRC, there was some initial value
we'd program into the counter to avoid missing the overflow event.
(sorry its been too long) ;)
If you mean there is no need of resetting the value since we are
overwriting it anyway you should see ->reset from a PMU unit POW
not just an event. If you look at the ->reset method for eg v8, you
will see that the reset method operates on all counters and the PMU
unit as a whole, that's the only sane way of setting up the PMU unit
before enabling single counters (some registers are UNKNOWN at reset).
To make my reply to Mathieu clearer, the ->reset method contains
operations (eg writing PMCR counters reset bits) that do carry out
counters reset, what I wanted to say is that the ->reset method
does not by itself drive the PMU HW reset signal, that's what the
power controller does when it resets the CPU on power up.
The PMU ->reset method must be called on a cpu on power-up, to make
sure PMU HW is set-up to sane default values and ready to be used (ie
install counters), for instance on v8 all counters must be disabled
(irq inclusive) and reset, that's what armv8pmu_reset() does.
I hope this makes things clearer.
Thanks,
Lorenzo
On 24 February 2016 at 17:31, Lorenzo Pieralisi
[off-list ref] wrote:
On Wed, Feb 24, 2016 at 02:53:02PM -0500, Ashwin Chaugule wrote:
quoted
Hi Lorenzo,
On 24 February 2016 at 12:35, Lorenzo Pieralisi
[off-list ref] wrote:
quoted
On Wed, Feb 24, 2016 at 09:20:22AM -0700, Mathieu Poirier wrote:
quoted
On 23 February 2016 at 11:22, Lorenzo Pieralisi
[...]
quoted
quoted
+static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
+ void *v)
+{
+ struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
+ struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
+ int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+
+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
+ return NOTIFY_DONE;
+
+ /*
+ * Always reset the PMU registers on power-up even if
+ * there are no events running.
+ */
+ if (cmd == CPU_PM_EXIT && armpmu->reset)
+ armpmu->reset(armpmu);
I think this patch does the right thing but I can't get the above
reset. Wouldn't it be better to do the reset as part of the
CPU_PM_EXIT case below? At this point nothing tells us the CPU won't
go back down before the event is enabled, wasting the cycle needed to
reset the PMU.
The logic goes, if the cpu is woken up and it has no events enabled,
if we do not reset it (mind, ->reset here sets the PMU register values
to a sane default, some of them are architecturally UNKNOWN on reset, it
does NOT reset the PMU) _and_ we subsequently install an event on it we
do have a problem, that's why whenever a core gets out of low-power we
have to reset its pmu.
Dont we blow out the previous value in the counter when installing an
event? Or has that changed lately? IIRC, there was some initial value
we'd program into the counter to avoid missing the overflow event.
(sorry its been too long) ;)
If you mean there is no need of resetting the value since we are
overwriting it anyway you should see ->reset from a PMU unit POW
not just an event. If you look at the ->reset method for eg v8, you
will see that the reset method operates on all counters and the PMU
unit as a whole, that's the only sane way of setting up the PMU unit
before enabling single counters (some registers are UNKNOWN at reset).
To make my reply to Mathieu clearer, the ->reset method contains
operations (eg writing PMCR counters reset bits) that do carry out
counters reset, what I wanted to say is that the ->reset method
does not by itself drive the PMU HW reset signal, that's what the
power controller does when it resets the CPU on power up.
The PMU ->reset method must be called on a cpu on power-up, to make
sure PMU HW is set-up to sane default values and ready to be used (ie
install counters), for instance on v8 all counters must be disabled
(irq inclusive) and reset, that's what armv8pmu_reset() does.
I hope this makes things clearer.
Indeed. Thanks for the explanation. The patch looks good to me.
Acked-by: Ashwin Chaugule <redacted>
On 24 February 2016 at 10:35, Lorenzo Pieralisi
[off-list ref] wrote:
On Wed, Feb 24, 2016 at 09:20:22AM -0700, Mathieu Poirier wrote:
quoted
On 23 February 2016 at 11:22, Lorenzo Pieralisi
[...]
quoted
quoted
+static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
+ void *v)
+{
+ struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
+ struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
+ int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
+
+ if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
+ return NOTIFY_DONE;
+
+ /*
+ * Always reset the PMU registers on power-up even if
+ * there are no events running.
+ */
+ if (cmd == CPU_PM_EXIT && armpmu->reset)
+ armpmu->reset(armpmu);
I think this patch does the right thing but I can't get the above
reset. Wouldn't it be better to do the reset as part of the
CPU_PM_EXIT case below? At this point nothing tells us the CPU won't
go back down before the event is enabled, wasting the cycle needed to
reset the PMU.
The logic goes, if the cpu is woken up and it has no events enabled,
if we do not reset it (mind, ->reset here sets the PMU register values
to a sane default, some of them are architecturally UNKNOWN on reset, it
does NOT reset the PMU) _and_ we subsequently install an event on it we
do have a problem, that's why whenever a core gets out of low-power we
have to reset its pmu.
Does it make sense ?
Ok, I understand the context and your solution will work.
Isn't there a flag somewhere in the PMU registers that indicate the
status has been lost due a loss of power? If so I think the best
solution is to probe that flag when an event gets installed. If the
unit has gone through a power down the reset can be done before
installing the event.
Mathieu