Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d729bcf0 authored by Neil Leeder's avatar Neil Leeder
Browse files

Perf: reset pmu enables when starting perf



PMU enable registers are not cleared when coming out
of cpu idle and perf is not running. This means that
enable bits may be set when perf starts. This is not normally
a problem because perf only looks at the counters it enables.
But per-pid tracing will see the enabled counters and the
garbage count values that get put into trace records, and generally
be unable to distinguish them from good values.

Clear the counters when perf starts. Then also reset them when coming
out of cpu idle. The existing test was to do this when a perf
event was running on a cpu, but there is a window between init and
starting events where drop into cpu idle could happen and allow garbage
values to be loaded into the enable register again. So change the
criterion for reset after cpu idle to be whenever the PMU is running.

Change-Id: Ie807363de92d166994ebbb9369132176ceaa4f68
Signed-off-by: default avatarNeil Leeder <nleeder@codeaurora.org>
parent ab01e731
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -368,6 +368,7 @@ static int
armpmu_reserve_hardware(struct arm_pmu *armpmu)
{
	int err;
	int cpu;
	struct arm_pmu_platdata *plat;
	struct platform_device *pmu_device = armpmu->plat_device;

@@ -393,6 +394,9 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
		return err;
	}
	armpmu->pmu_state = ARM_PMU_STATE_RUNNING;
	if (armpmu->reset)
		for_each_cpu(cpu, cpu_online_mask)
			smp_call_function_single(cpu, armpmu->reset, armpmu, 1);

	return 0;
}
+12 −5
Original line number Diff line number Diff line
@@ -326,9 +326,13 @@ static int perf_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,
		void *v)
{
	struct pmu *pmu;

	if (!cpu_pmu)
		return NOTIFY_OK;

	switch (cmd) {
	case CPU_PM_ENTER:
		if (cpu_pmu && cpu_pmu->save_pm_registers)
		if (cpu_pmu->save_pm_registers)
			cpu_pmu->save_pm_registers((void *)smp_processor_id());
		if (cpu_has_active_perf((int)v)) {
			armpmu_update_counters();
@@ -339,12 +343,15 @@ static int perf_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd,

	case CPU_PM_ENTER_FAILED:
	case CPU_PM_EXIT:
		if (cpu_has_active_perf((int)v) && cpu_pmu->reset)
			cpu_pmu->reset(NULL);
		if (cpu_pmu && cpu_pmu->restore_pm_registers)
		/* Reset PMU to clear counters for ftrace buffer */
		if ((cpu_pmu->pmu_state == ARM_PMU_STATE_RUNNING) &&
		    cpu_pmu->reset)
			cpu_pmu->reset(cpu_pmu);

		if (cpu_pmu->restore_pm_registers)
			cpu_pmu->restore_pm_registers(
				(void *)smp_processor_id());
		if (cpu_pmu && cpu_has_active_perf((int)v)) {
		if (cpu_has_active_perf((int)v)) {
			/*
			 * Flip this bit so armpmu_enable knows it needs
			 * to re-enable active counters.
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ static char *descriptions =
	"27 Perf: stop counters when going into hotplug\n"
	"28 ARM: dts: msm: add perf-events support for msm8909\n"
	"29 msm: perf: Refine disable/enable in tracecounters\n"
	"30 Perf: reset pmu enables when starting perf\n"
;

static ssize_t desc_read(struct file *fp, char __user *buf,