From patchwork Tue Jan 13 10:26:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 5619241 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 732629F3A0 for ; Tue, 13 Jan 2015 10:31:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6423820558 for ; Tue, 13 Jan 2015 10:31:39 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 2B195202AE for ; Tue, 13 Jan 2015 10:31:38 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1YAyie-0000Y0-Nb; Tue, 13 Jan 2015 10:29:04 +0000 Received: from mail-wg0-f47.google.com ([74.125.82.47]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YAyhU-0007qP-Im for linux-arm-kernel@lists.infradead.org; Tue, 13 Jan 2015 10:27:54 +0000 Received: by mail-wg0-f47.google.com with SMTP id n12so2018558wgh.6 for ; Tue, 13 Jan 2015 02:27:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=5/VDXUMjkaTmjxPcTGQmWz79HeNf07PR/3NjBIFJ7Aw=; b=iMf8m+5/xyMWS6mTO+dR7Zkv0mAFAkuiQfbMSNj1FSWZvuNvgu36PR2cgeeZVYOdby 3FE7f8vEefmvVIPfqkbBdKctbYT0JQyeidKcR6sVjuIBj6VqzGat9uQJKr7JB/e9zBLN fTNAqjmdspczfFH2G9l7X0eofKE1xUiMoY5zV6nJh2ysJEj38ZtIswwPp5oOiSKV94WJ NrjTUEx/bgbR9amEcRVjr/ZdQ/T1NuqUtzuOXMQLZ+33452mTAJN+9Z83HjCVSa/mSF2 OSBIS7rlHmjGYISiFozv3HKnNzzWgwg0UI/Pd9XUnK1hE0L/SfUoRNMGKtC9+94oWewe kPog== X-Gm-Message-State: ALoCoQmkaHXsXz5O0PRmEgUH8yTRgO3h6xuBeJz//kwJYlxoe27QUawbcujJNrIBJ+GwhlaL8bUx X-Received: by 10.180.101.98 with SMTP id ff2mr38814238wib.83.1421144855742; Tue, 13 Jan 2015 02:27:35 -0800 (PST) Received: from sundance.lan (cpc4-aztw19-0-0-cust157.18-1.cable.virginm.net. [82.33.25.158]) by mx.google.com with ESMTPSA id u18sm25111297wjq.42.2015.01.13.02.27.33 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 13 Jan 2015 02:27:34 -0800 (PST) From: Daniel Thompson To: Thomas Gleixner , Jason Cooper Subject: [PATCH 3.19-rc2 v14 6/7] ARM: Add support for on-demand backtrace of other CPUs Date: Tue, 13 Jan 2015 10:26:57 +0000 Message-Id: <1421144818-14036-7-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1421144818-14036-1-git-send-email-daniel.thompson@linaro.org> References: <1415968543-29469-1-git-send-email-daniel.thompson@linaro.org> <1421144818-14036-1-git-send-email-daniel.thompson@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150113_022752_969015_FA59F5CD X-CRM114-Status: GOOD ( 21.59 ) X-Spam-Score: -0.7 (/) Cc: Daniel Thompson , linaro-kernel@lists.linaro.org, Russell King , patches@linaro.org, Stephen Boyd , linux-kernel@vger.kernel.org, Steven Rostedt , Daniel Drake , Dmitry Pervushin , Dirk Behme , John Stultz , Tim Sander , Sumit Semwal , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Duplicate the x86 code to trigger a backtrace using an NMI and hook it up to IPI on ARM. Where it is possible for the hardware to do so the IPI will be delivered at FIQ level. Also provide are a few small items of plumbing to hook up the new code. Signed-off-by: Daniel Thompson 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 | 71 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/kernel/traps.c | 3 ++ 6 files changed, 84 insertions(+), 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 97d07ed60a0b..91d62731b52d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -11,6 +11,7 @@ config ARM select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_CMPXCHG_LOCKREF select ARCH_WANT_IPC_PARSE_VERSION + select ARCH_WANT_NMI_PRINTK select BUILDTIME_EXTABLE_SORT if MMU select CLONE_BACKWARDS select CPU_PM if (SUSPEND || CPU_IDLE) 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 5e6052e18850..afb094a1e6d4 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); @@ -444,6 +446,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) @@ -558,6 +561,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]); @@ -611,6 +616,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); @@ -705,3 +716,63 @@ 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; +static cpumask_t printtrace_mask; + +void arch_trigger_all_cpu_backtrace(bool include_self) +{ + struct nmi_seq_buf *s; + int len; + int cpu; + int i; + int this_cpu = get_cpu(); + + if (0 != prepare_nmi_printk(to_cpumask(backtrace_mask))) { + /* + * If there is already an nmi printk sequence in + * progress then just give up... + */ + put_cpu(); + return; + } + + if (!include_self) + cpumask_clear_cpu(this_cpu, to_cpumask(backtrace_mask)); + cpumask_copy(&printtrace_mask, 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(); + } + + complete_nmi_printk(&printtrace_mask); + put_cpu(); +} + +void ipi_cpu_backtrace(struct pt_regs *regs) +{ + int cpu; + printk_func_t orig; + + cpu = smp_processor_id(); + + if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { + orig = this_cpu_begin_nmi_printk(); + pr_warn("FIQ backtrace for cpu %d\n", cpu); + show_regs(regs); + this_cpu_end_nmi_printk(orig); + + 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();