From patchwork Wed Mar 4 10:12:54 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 45393 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f71.google.com (mail-la0-f71.google.com [209.85.215.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 27E8821486 for ; Wed, 4 Mar 2015 10:14:18 +0000 (UTC) Received: by labge10 with SMTP id ge10sf33517436lab.3 for ; Wed, 04 Mar 2015 02:14:17 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=xJ9aX2/7tFXziMzQdbWx/Y8sX5dgWtCcsWWGtB/3SJY=; b=JRbohOU8LjkhF8Hk4fpdOi320q5/1q5X9XNOymmhP7WgAJ6RsLUAR0xBTgzwbkaSJ8 Hh2bycooeLt6rD6DEF1yGJjzxKpJZpLFjTQWCmrkRcWnQM2++nOJRWiyfcXZl+R99CS1 t+kvJPiWzY2Vpw4suxxaubbqkGfHE3r1KgEBmv7Mis7CUun6YY8hhaZqn+hysnfsB+D2 FWRNXsQK/itqh1XIezlCsgwt5V+U1gJ2rOBCG4iqOvR1E5rAnc0RQOB5impIARdWY9oo JyCndKP8VwpfvMYsYAqyy05+Jr/qfz8vyniusn8X1q8yKsTE+Hm56LRzS7FPbgtGTqKL iQeA== X-Gm-Message-State: ALoCoQn2D+bOR1l4oZcvKl5SAVanN9RFRrUrseevrHh8MKijuu0kk0hF+qn2ccumDMpnEBgrVSKo X-Received: by 10.180.11.34 with SMTP id n2mr979413wib.2.1425464057117; Wed, 04 Mar 2015 02:14:17 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.87.14 with SMTP id t14ls161740laz.61.gmail; Wed, 04 Mar 2015 02:14:16 -0800 (PST) X-Received: by 10.112.140.74 with SMTP id re10mr2773953lbb.80.1425464056957; Wed, 04 Mar 2015 02:14:16 -0800 (PST) Received: from mail-la0-f49.google.com (mail-la0-f49.google.com. [209.85.215.49]) by mx.google.com with ESMTPS id ax6si2218122lbc.65.2015.03.04.02.14.16 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 04 Mar 2015 02:14:16 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.49 as permitted sender) client-ip=209.85.215.49; Received: by labgq15 with SMTP id gq15so43551012lab.3 for ; Wed, 04 Mar 2015 02:14:16 -0800 (PST) X-Received: by 10.152.115.136 with SMTP id jo8mr2872177lab.32.1425464056858; Wed, 04 Mar 2015 02:14:16 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.112.35.133 with SMTP id h5csp1121525lbj; Wed, 4 Mar 2015 02:14:16 -0800 (PST) X-Received: by 10.181.13.14 with SMTP id eu14mr53923256wid.2.1425464052054; Wed, 04 Mar 2015 02:14:12 -0800 (PST) Received: from mail-wi0-f178.google.com (mail-wi0-f178.google.com. [209.85.212.178]) by mx.google.com with ESMTPS id az2si6022457wjb.129.2015.03.04.02.14.11 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 04 Mar 2015 02:14:12 -0800 (PST) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.212.178 as permitted sender) client-ip=209.85.212.178; Received: by widex7 with SMTP id ex7so29384050wid.4 for ; Wed, 04 Mar 2015 02:14:11 -0800 (PST) X-Received: by 10.194.133.196 with SMTP id pe4mr6632751wjb.76.1425464051384; Wed, 04 Mar 2015 02:14:11 -0800 (PST) Received: from wychelm.lan (cpc4-aztw19-0-0-cust71.18-1.cable.virginm.net. [82.33.25.72]) by mx.google.com with ESMTPSA id n1sm24488228wib.11.2015.03.04.02.14.10 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 04 Mar 2015 02:14:10 -0800 (PST) From: Daniel Thompson To: Thomas Gleixner Cc: Daniel Thompson , Jason Cooper , Russell King , Will Deacon , Catalin Marinas , Marc Zyngier , Stephen Boyd , John Stultz , Steven Rostedt , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, patches@linaro.org, linaro-kernel@lists.linaro.org, Sumit Semwal , Dirk Behme , Daniel Drake , Dmitry Pervushin , Tim Sander Subject: [PATCH 4.0-rc1 v17 6/6] ARM: Add support for on-demand backtrace of other CPUs Date: Wed, 4 Mar 2015 10:12:54 +0000 Message-Id: <1425463974-23568-7-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1425463974-23568-1-git-send-email-daniel.thompson@linaro.org> References: <1422022952-31552-1-git-send-email-daniel.thompson@linaro.org> <1425463974-23568-1-git-send-email-daniel.thompson@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: daniel.thompson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.49 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Replicate the x86 code to trigger a backtrace using an NMI and hook it up to IPI on ARM. The code differs slightly from the code on x86 because, on ARM, we do now know at compile time whether a platform is capable of supporting FIQ. We must avoid using an IPI to request a backtrace from the CPU on which the backtrace was requested if interrupts are disabled and fall back to generating it directly. In addition the implementation of arch_trigger_all_cpu_backtrace() the patch also includes a few small items of plumbing that must be hooked up for the new code to work. Credit: Russell King provided the initial prototype implementing this feature for ARM. Today the patch has been reworked and, mostly, rewriten to keep it aligned with x86. However this patch does still include some code from Russell's original prototype. Signed-off-by: Daniel Thompson Cc: Russell King Cc: Steven Rostedt --- arch/arm/Kconfig | 1 + arch/arm/include/asm/hardirq.h | 2 +- arch/arm/include/asm/irq.h | 5 +++ arch/arm/include/asm/smp.h | 3 ++ arch/arm/kernel/smp.c | 80 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/traps.c | 3 ++ 6 files changed, 93 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9f1f09a2bc9b..2bb2e3cc660d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -76,6 +76,7 @@ config ARM select OLD_SIGACTION select OLD_SIGSUSPEND3 select PERF_USE_VMALLOC + select PRINTK_NMI select RTC_LIB select SYS_SUPPORTS_APM_EMULATION # Above selects are sorted alphabetically; please add new ones diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h index fe3ea776dc34..5df33e30ae1b 100644 --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h @@ -5,7 +5,7 @@ #include #include -#define NR_IPI 8 +#define NR_IPI 9 typedef struct { unsigned int __softirq_pending; diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h index 53c15dec7af6..be1d07d59ee9 100644 --- a/arch/arm/include/asm/irq.h +++ b/arch/arm/include/asm/irq.h @@ -35,6 +35,11 @@ extern void (*handle_arch_irq)(struct pt_regs *); extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); #endif +#ifdef CONFIG_SMP +extern void arch_trigger_all_cpu_backtrace(bool); +#define arch_trigger_all_cpu_backtrace(x) arch_trigger_all_cpu_backtrace(x) +#endif + #endif #endif diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h index 18f5a554134f..b076584ac0fa 100644 --- a/arch/arm/include/asm/smp.h +++ b/arch/arm/include/asm/smp.h @@ -18,6 +18,8 @@ # error " included in non-SMP build" #endif +#define SMP_IPI_FIQ_MASK 0x0100 + #define raw_smp_processor_id() (current_thread_info()->cpu) struct seq_file; @@ -79,6 +81,7 @@ extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask); +extern void ipi_cpu_backtrace(struct pt_regs *regs); extern int register_ipi_completion(struct completion *completion, int cpu); struct smp_operations { diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 86ef244c5a24..828277c4c248 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -72,6 +73,7 @@ enum ipi_msg_type { IPI_CPU_STOP, IPI_IRQ_WORK, IPI_COMPLETION, + IPI_CPU_BACKTRACE, }; static DECLARE_COMPLETION(cpu_running); @@ -456,6 +458,7 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = { S(IPI_CPU_STOP, "CPU stop interrupts"), S(IPI_IRQ_WORK, "IRQ work interrupts"), S(IPI_COMPLETION, "completion interrupts"), + S(IPI_CPU_BACKTRACE, "backtrace interrupts"), }; static void smp_cross_call(const struct cpumask *target, unsigned int ipinr) @@ -570,6 +573,8 @@ void handle_IPI(int ipinr, struct pt_regs *regs) unsigned int cpu = smp_processor_id(); struct pt_regs *old_regs = set_irq_regs(regs); + BUILD_BUG_ON(SMP_IPI_FIQ_MASK != BIT(IPI_CPU_BACKTRACE)); + if ((unsigned)ipinr < NR_IPI) { trace_ipi_entry(ipi_types[ipinr]); __inc_irq_stat(cpu, ipi_irqs[ipinr]); @@ -623,6 +628,12 @@ void handle_IPI(int ipinr, struct pt_regs *regs) irq_exit(); break; + case IPI_CPU_BACKTRACE: + irq_enter(); + ipi_cpu_backtrace(regs); + irq_exit(); + break; + default: pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); @@ -717,3 +728,72 @@ static int __init register_cpufreq_notifier(void) core_initcall(register_cpufreq_notifier); #endif + +/* For reliability, we're prepared to waste bits here. */ +static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly; + +void arch_trigger_all_cpu_backtrace(bool include_self) +{ + int i; + int this_cpu = get_cpu(); + + if (0 != printk_nmi_prepare()) { + /* + * If there is already an nmi printk sequence in + * progress then just give up... + */ + put_cpu(); + return; + } + + cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask); + + /* + * If irqs are disabled on the current processor then, if + * IPI_CPU_BACKTRACE is delivered using IRQ, we will won't be able to + * react to IPI_CPU_BACKTRACE until we leave this function. We avoid + * the potential timeout (not to mention the failure to print useful + * information) by calling the backtrace directly. + */ + if (irqs_disabled()) { + ipi_cpu_backtrace(in_interrupt() ? get_irq_regs() : NULL); + include_self = false; + } + + if (!include_self) + cpumask_clear_cpu(this_cpu, to_cpumask(backtrace_mask)); + + if (!cpumask_empty(to_cpumask(backtrace_mask))) { + pr_info("Sending FIQ to %s CPUs:\n", + (include_self ? "all" : "other")); + smp_cross_call(to_cpumask(backtrace_mask), IPI_CPU_BACKTRACE); + } + + /* Wait for up to 10 seconds for all CPUs to do the backtrace */ + for (i = 0; i < 10 * 1000; i++) { + if (cpumask_empty(to_cpumask(backtrace_mask))) + break; + mdelay(1); + touch_softlockup_watchdog(); + } + + printk_nmi_complete(); + put_cpu(); +} + +void ipi_cpu_backtrace(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { + printk_nmi_this_cpu_begin(); + pr_warn("FIQ backtrace for cpu %d\n", cpu); + if (regs != NULL) + show_regs(regs); + else + dump_stack(); + printk_nmi_this_cpu_end(); + + cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask)); + } +} diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index b35e220ae1b1..1836415b8a5c 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -483,6 +483,9 @@ asmlinkage void __exception_irq_entry handle_fiq_as_nmi(struct pt_regs *regs) #ifdef CONFIG_ARM_GIC gic_handle_fiq_ipi(); #endif +#ifdef CONFIG_SMP + ipi_cpu_backtrace(regs); +#endif nmi_exit();