[3.13.y.z extended stable] Patch "sparc64: Fix pcr_ops initialization and usage bugs." has been added to staging queue

Kamal Mostafa kamal at canonical.com
Fri Oct 31 20:53:25 UTC 2014

This is a note to let you know that I have just added a patch titled

    sparc64: Fix pcr_ops initialization and usage bugs.

to the linux-3.13.y-queue branch of the 3.13.y.z extended stable tree 
which can be found at:


This patch is scheduled to be released in version

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.13.y.z tree, see



>From 226c864dfff12ffd2658ad87f51d0f62ef9e97a2 Mon Sep 17 00:00:00 2001
From: "David S. Miller" <davem at davemloft.net>
Date: Mon, 11 Aug 2014 15:38:46 -0700
Subject: sparc64: Fix pcr_ops initialization and usage bugs.

[ Upstream commit 8bccf5b313180faefce38e0d1140f76e0f327d28 ]

Christopher reports that perf_event_print_debug() can crash in uniprocessor
builds.  The crash is due to pcr_ops being NULL.

This happens because pcr_arch_init() is only invoked by smp_cpus_done() which
only executes in SMP builds.

init_hw_perf_events() is closely intertwined with pcr_ops being setup properly,

1) Call pcr_arch_init() early on from init_hw_perf_events(), instead of
   from smp_cpus_done().

2) Do not hook up a PMU type if pcr_ops is NULL after pcr_arch_init().

3) Move init_hw_perf_events to a later initcall so that it we will be
   sure to invoke pcr_arch_init() after all cpus are brought up.

Finally, guard the one naked sequence of pcr_ops dereferences in
__global_pmu_self() with an appropriate NULL check.

Reported-by: Christopher Alexander Tobias Schulze <cat.schulze at alice-dsl.net>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
 arch/sparc/kernel/perf_event.c | 7 +++++--
 arch/sparc/kernel/process_64.c | 3 +++
 arch/sparc/kernel/smp_64.c     | 1 -
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index b5c38fa..857baca 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -1671,9 +1671,12 @@ static bool __init supported_pmu(void)

 int __init init_hw_perf_events(void)
+	int err;
 	pr_info("Performance events: ");

-	if (!supported_pmu()) {
+	err = pcr_arch_init();
+	if (err || !supported_pmu()) {
 		pr_cont("No support for PMU type '%s'\n", sparc_pmu_type);
 		return 0;
@@ -1685,7 +1688,7 @@ int __init init_hw_perf_events(void)

 	return 0;

 void perf_callchain_kernel(struct perf_callchain_entry *entry,
 			   struct pt_regs *regs)
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c
index d7b4967..c6f7113 100644
--- a/arch/sparc/kernel/process_64.c
+++ b/arch/sparc/kernel/process_64.c
@@ -306,6 +306,9 @@ static void __global_pmu_self(int this_cpu)
 	struct global_pmu_snapshot *pp;
 	int i, num;

+	if (!pcr_ops)
+		return;
 	pp = &global_cpu_snapshot[this_cpu].pmu;

 	num = 1;
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index 8416d7f..8311f3d 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -1395,7 +1395,6 @@ void __cpu_die(unsigned int cpu)

 void __init smp_cpus_done(unsigned int max_cpus)
-	pcr_arch_init();

 void smp_send_reschedule(int cpu)

More information about the kernel-team mailing list