aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/perf_event.c
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2015-05-13 12:12:26 -0400
committerWill Deacon <will.deacon@arm.com>2015-05-27 11:12:36 -0400
commitc904e32a69b7c77905876fc834f474f13f62c138 (patch)
tree01c4a7dbfece988438ff5f80972b433929947c7d /arch/arm/kernel/perf_event.c
parentcc88116da0d18b8292f5437dbc0c4683c8a34ac1 (diff)
arm: perf: filter unschedulable events
Different CPU microarchitectures implement different PMU events, and thus events which can be scheduled on one microarchitecture cannot be scheduled on another, and vice-versa. Some archicted events behave differently across microarchitectures, and thus cannot be meaningfully summed. Due to this, we reject the scheduling of an event on a CPU of a different microarchitecture to that the event targets. When the core perf code is scheduling events and encounters an event which cannot be scheduled, it stops attempting to schedule events. As the perf core periodically rotates the list of events, for some proportion of the time events which are unschedulable will block events which are schedulable, resulting in low utilisation of the hardware counters. This patch implements a pmu::filter_match callback such that we can detect and skip such events while scheduling early, before they can block the schedulable events. This prevents the low HW counter utilisation issue. Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm/kernel/perf_event.c')
-rw-r--r--arch/arm/kernel/perf_event.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 9b536be74f7b..df028072aabf 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -524,6 +524,18 @@ static void armpmu_disable(struct pmu *pmu)
524 armpmu->stop(armpmu); 524 armpmu->stop(armpmu);
525} 525}
526 526
527/*
528 * In heterogeneous systems, events are specific to a particular
529 * microarchitecture, and aren't suitable for another. Thus, only match CPUs of
530 * the same microarchitecture.
531 */
532static int armpmu_filter_match(struct perf_event *event)
533{
534 struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
535 unsigned int cpu = smp_processor_id();
536 return cpumask_test_cpu(cpu, &armpmu->supported_cpus);
537}
538
527#ifdef CONFIG_PM 539#ifdef CONFIG_PM
528static int armpmu_runtime_resume(struct device *dev) 540static int armpmu_runtime_resume(struct device *dev)
529{ 541{
@@ -564,6 +576,7 @@ static void armpmu_init(struct arm_pmu *armpmu)
564 .start = armpmu_start, 576 .start = armpmu_start,
565 .stop = armpmu_stop, 577 .stop = armpmu_stop,
566 .read = armpmu_read, 578 .read = armpmu_read,
579 .filter_match = armpmu_filter_match,
567 }; 580 };
568} 581}
569 582