devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
To: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
	will.deacon-5wv7dgnIgG8@public.gmane.org,
	rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org
Subject: [RFC PATCH 07/11] arm: perf: treat PMUs as CPU affine
Date: Thu, 11 Apr 2013 10:12:38 +0100	[thread overview]
Message-ID: <1365671562-2403-8-git-send-email-mark.rutland@arm.com> (raw)
In-Reply-To: <1365671562-2403-1-git-send-email-mark.rutland-5wv7dgnIgG8@public.gmane.org>

In multi-cluster systems, the PMUs can be different across clusters, and
so our logical PMU may not be able to schedule events on all CPUs.

This patch adds a cpumask to encode which CPUs a PMU driver supports
controlling events for, and limits the driver to scheduling events on
those CPUs. Currently the cpumask is set to match all CPUs.

Signed-off-by: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
Reviewed-by: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
---
 arch/arm/include/asm/pmu.h       |  1 +
 arch/arm/kernel/perf_event.c     | 20 ++++++++++++++++++++
 arch/arm/kernel/perf_event_cpu.c | 10 +++++++++-
 3 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 56724b2..4688692 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -65,6 +65,7 @@ struct pmu_hw_events {
 struct arm_pmu {
 	struct pmu	pmu;
 	cpumask_t	active_irqs;
+	cpumask_t	supported_cpus;
 	char		*name;
 	irqreturn_t	(*handle_irq)(int irq_num, void *dev);
 	void		(*enable)(struct perf_event *event);
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 5bcd8ac..ebcd123 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -12,6 +12,7 @@
  */
 #define pr_fmt(fmt) "hw perfevents: " fmt
 
+#include <linux/cpumask.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -21,6 +22,11 @@
 #include <asm/pmu.h>
 #include <asm/stacktrace.h>
 
+static bool cpu_supported(struct arm_pmu *armpmu, int cpu)
+{
+	return cpumask_test_cpu(cpu, &armpmu->supported_cpus);
+}
+
 static int
 armpmu_map_cache_event(const unsigned (*cache_map)
 				      [PERF_COUNT_HW_CACHE_MAX]
@@ -221,6 +227,10 @@ armpmu_add(struct perf_event *event, int flags)
 	int idx;
 	int err = 0;
 
+	/* An event following a process won't be stopped earlier */
+	if (!cpu_supported(armpmu, smp_processor_id()))
+		return -ENOENT;
+
 	perf_pmu_disable(event->pmu);
 
 	/* If we don't have a space for the counter then finish early. */
@@ -417,6 +427,16 @@ static int armpmu_event_init(struct perf_event *event)
 	int err = 0;
 	atomic_t *active_events = &armpmu->active_events;
 
+	/*
+	 * Reject CPU-affine events for CPUs that are of a different class to
+	 * that which this PMU handles. Process-following events (where
+	 * event->cpu == -1) can be migrated between CPUs, and thus we have to
+	 * reject them later (in armpmu_add) if they're scheduled on a
+	 * different class of CPU.
+	 */
+	if (event->cpu != -1 && !cpu_supported(armpmu, event->cpu))
+		return -ENOENT;
+
 	/* does not support taken branch sampling */
 	if (has_branch_stack(event))
 		return -EOPNOTSUPP;
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index ae5be75..c1a9880c 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -168,7 +168,8 @@ static void cpu_pmu_init(struct cpu_pmu *cpu_pmu)
 
 	/* Ensure the PMU has sane values out of reset. */
 	if (arm_pmu->reset)
-		on_each_cpu(arm_pmu->reset, arm_pmu, 1);
+		on_each_cpu_mask(&arm_pmu->supported_cpus, arm_pmu->reset,
+				 arm_pmu, 1);
 }
 
 /*
@@ -180,9 +181,13 @@ static void cpu_pmu_init(struct cpu_pmu *cpu_pmu)
 static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
 				    unsigned long action, void *hcpu)
 {
+	int cpu = (long)hcpu;
 	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
 		return NOTIFY_DONE;
 
+	if (!cpumask_test_cpu(cpu, &cpu_pmu->supported_cpus))
+		return NOTIFY_DONE;
+
 	if (cpu_pmu && cpu_pmu->reset)
 		cpu_pmu->reset(cpu_pmu);
 	else
@@ -296,6 +301,9 @@ static int cpu_pmu_device_probe(struct platform_device *pdev)
 		goto out_pmu;
 	}
 
+	/* Assume by default that we're on a homogeneous system */
+	cpumask_setall(&pmu->armpmu.supported_cpus);
+
 	if (node && (of_id = of_match_node(cpu_pmu_of_device_ids, pdev->dev.of_node))) {
 		init_fn = of_id->data;
 		ret = init_fn(&pmu->armpmu);
-- 
1.8.1.1

  parent reply	other threads:[~2013-04-11  9:12 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-11  9:12 [RFC PATCH 00/11] Topology bindings / Perf for big.LITTLE systems Mark Rutland
     [not found] ` <1365671562-2403-1-git-send-email-mark.rutland-5wv7dgnIgG8@public.gmane.org>
2013-04-11  9:12   ` [RFC PATCH 01/11] Documentation: DT: arm: define CPU topology bindings Mark Rutland
2013-04-11 15:00     ` Rob Herring
2013-04-11 15:50       ` Lorenzo Pieralisi
2013-04-11 17:55         ` Rob Herring
2013-04-11 18:17           ` Dave Martin
     [not found]             ` <20130411181710.GC2239-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2013-04-12 11:27               ` Lorenzo Pieralisi
     [not found]           ` <5166F908.9050503-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2013-04-12 11:16             ` Lorenzo Pieralisi
2013-04-11 18:01         ` Dave Martin
     [not found]           ` <20130411180125.GB2239-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2013-04-12 11:44             ` Lorenzo Pieralisi
     [not found]               ` <20130412114457.GC6637-7AyDDHkRsp3ZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>
2013-04-12 14:36                 ` Dave Martin
2013-04-12 16:59                   ` Lorenzo Pieralisi
2013-04-11  9:12   ` [RFC PATCH 02/11] arm: add functions to parse cpu affinity from dt Mark Rutland
2013-04-11  9:12   ` [RFC PATCH 03/11] arm: perf: clean up PMU names Mark Rutland
2013-04-11  9:12   ` [RFC PATCH 04/11] arm: perf: use IDR types for CPU PMUs Mark Rutland
2013-04-11  9:12   ` [RFC PATCH 05/11] arm: perf: make get_hw_events take arm_pmu Mark Rutland
2013-04-11  9:12   ` [RFC PATCH 06/11] arm: perf: dynamically allocate cpu hardware data Mark Rutland
2013-04-11  9:12   ` Mark Rutland [this message]
2013-04-11  9:12   ` [RFC PATCH 08/11] arm: perf: probe number of counters on affine CPUs Mark Rutland
2013-04-11  9:12   ` [RFC PATCH 09/11] arm: perf: parse cpu affinity from dt Mark Rutland
2013-04-11  9:12   ` [RFC PATCH 10/11] arm: perf: allow multiple CPU PMUs to be registered Mark Rutland
2013-04-11  9:12   ` [RFC PATCH 11/11] arm: dts: add all PMUs for A15x2 A7x3 coretile Mark Rutland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1365671562-2403-8-git-send-email-mark.rutland@arm.com \
    --to=mark.rutland-5wv7dgnigg8@public.gmane.org \
    --cc=devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=rob.herring-bsGFqQB8/DxBDgjK7y7TUQ@public.gmane.org \
    --cc=will.deacon-5wv7dgnIgG8@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).