From patchwork Mon Aug 8 16:03:35 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Metcalf X-Patchwork-Id: 9268651 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A4DD9607D6 for ; Mon, 8 Aug 2016 16:06:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9645D2094F for ; Mon, 8 Aug 2016 16:06:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8A70B283FE; Mon, 8 Aug 2016 16:06:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E19422094F for ; Mon, 8 Aug 2016 16:06:26 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bWn37-0002Y9-Pc; Mon, 08 Aug 2016 16:05:09 +0000 Received: from mail-il-dmz.mellanox.com ([193.47.165.129] helo=mellanox.co.il) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bWn2H-0001v4-JK for linux-arm-kernel@lists.infradead.org; Mon, 08 Aug 2016 16:04:22 +0000 Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmetcalf@mellanox.com) with ESMTPS (AES256-SHA encrypted); 8 Aug 2016 19:03:50 +0300 Received: from ld-1.internal.tilera.com (ld-1.internal.tilera.com [10.15.7.41]) by mtbu-labmail01.internal.tilera.com (8.14.4/8.14.4) with ESMTP id u78G3nGA022229; Mon, 8 Aug 2016 12:03:49 -0400 Received: (from cmetcalf@localhost) by ld-1.internal.tilera.com (8.14.4/8.14.4/Submit) id u78G3nLU016108; Mon, 8 Aug 2016 12:03:49 -0400 From: Chris Metcalf To: Peter Zijlstra , "Rafael J. Wysocki" , Petr Mladek , Russell King , Thomas Gleixner , Aaron Tomlin , Ingo Molnar , Andrew Morton , Daniel Thompson , x86@kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v7 1/4] nmi_backtrace: add more trigger_*_cpu_backtrace() methods Date: Mon, 8 Aug 2016 12:03:35 -0400 Message-Id: <1470672218-16059-2-git-send-email-cmetcalf@mellanox.com> X-Mailer: git-send-email 2.7.2 In-Reply-To: <1470672218-16059-1-git-send-email-cmetcalf@mellanox.com> References: <1470672218-16059-1-git-send-email-cmetcalf@mellanox.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160808_090418_235228_B1B2ABF6 X-CRM114-Status: GOOD ( 15.10 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Chris Metcalf MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Currently you can only request a backtrace of either all cpus, or all cpus but yourself. It can also be helpful to request a remote backtrace of a single cpu, and since we want that, the logical extension is to support a cpumask as the underlying primitive. This change modifies the existing lib/nmi_backtrace.c code to take a cpumask as its basic primitive, and modifies the linux/nmi.h code to use either the old "all/all_but_self" arch methods, or the new "cpumask" method, depending on which is available. The existing clients of nmi_backtrace (arm and x86) are converted to using the new cpumask approach in this change. Signed-off-by: Chris Metcalf Reviewed-by: Aaron Tomlin --- arch/arm/include/asm/irq.h | 5 +++-- arch/arm/kernel/smp.c | 4 ++-- arch/x86/include/asm/irq.h | 5 +++-- arch/x86/kernel/apic/hw_nmi.c | 7 ++++--- include/linux/nmi.h | 49 +++++++++++++++++++++++++++++++------------ lib/nmi_backtrace.c | 13 ++++++------ 6 files changed, 55 insertions(+), 28 deletions(-) diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h index 1bd9510de1b9..edbbb0e78f9c 100644 --- a/arch/arm/include/asm/irq.h +++ b/arch/arm/include/asm/irq.h @@ -36,8 +36,9 @@ 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) +extern void arch_trigger_cpumask_backtrace(bool include_self, + const cpumask_t *mask); +#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace #endif static inline int nr_legacy_irqs(void) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 861521606c6d..732583dcb8f8 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -760,7 +760,7 @@ static void raise_nmi(cpumask_t *mask) smp_cross_call(mask, IPI_CPU_BACKTRACE); } -void arch_trigger_all_cpu_backtrace(bool include_self) +void arch_trigger_cpumask_backtrace(bool include_self, const cpumask_t *mask) { - nmi_trigger_all_cpu_backtrace(include_self, raise_nmi); + nmi_trigger_cpumask_backtrace(include_self, mask, raise_nmi); } diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index e7de5c9a4fbd..5e7e826308b6 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -50,8 +50,9 @@ extern int vector_used_by_percpu_irq(unsigned int vector); extern void init_ISA_irqs(void); #ifdef CONFIG_X86_LOCAL_APIC -void arch_trigger_all_cpu_backtrace(bool); -#define arch_trigger_all_cpu_backtrace arch_trigger_all_cpu_backtrace +void arch_trigger_cpumask_backtrace(bool include_self, + const struct cpumask *mask); +#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace #endif #endif /* _ASM_X86_IRQ_H */ diff --git a/arch/x86/kernel/apic/hw_nmi.c b/arch/x86/kernel/apic/hw_nmi.c index f29501e1a5c1..6da698d54256 100644 --- a/arch/x86/kernel/apic/hw_nmi.c +++ b/arch/x86/kernel/apic/hw_nmi.c @@ -26,15 +26,16 @@ u64 hw_nmi_get_sample_period(int watchdog_thresh) } #endif -#ifdef arch_trigger_all_cpu_backtrace +#ifdef arch_trigger_cpumask_backtrace static void nmi_raise_cpu_backtrace(cpumask_t *mask) { apic->send_IPI_mask(mask, NMI_VECTOR); } -void arch_trigger_all_cpu_backtrace(bool include_self) +void arch_trigger_cpumask_backtrace(bool include_self, const cpumask_t *mask) { - nmi_trigger_all_cpu_backtrace(include_self, nmi_raise_cpu_backtrace); + nmi_trigger_cpumask_backtrace(include_self, mask, + nmi_raise_cpu_backtrace); } static int diff --git a/include/linux/nmi.h b/include/linux/nmi.h index 4630eeae18e0..8e9ad95df219 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h @@ -31,38 +31,61 @@ static inline void hardlockup_detector_disable(void) {} #endif /* - * Create trigger_all_cpu_backtrace() out of the arch-provided - * base function. Return whether such support was available, + * Create trigger_all_cpu_backtrace() etc out of the arch-provided + * base function(s). Return whether such support was available, * to allow calling code to fall back to some other mechanism: */ -#ifdef arch_trigger_all_cpu_backtrace static inline bool trigger_all_cpu_backtrace(void) { +#if defined(arch_trigger_all_cpu_backtrace) arch_trigger_all_cpu_backtrace(true); - return true; +#elif defined(arch_trigger_cpumask_backtrace) + arch_trigger_cpumask_backtrace(true, cpu_online_mask); + return true; +#else + return false; +#endif } + static inline bool trigger_allbutself_cpu_backtrace(void) { +#if defined(arch_trigger_all_cpu_backtrace) arch_trigger_all_cpu_backtrace(false); return true; +#elif defined(arch_trigger_cpumask_backtrace) + arch_trigger_cpumask_backtrace(false, cpu_online_mask); + return true; +#else + return false; +#endif } -/* generic implementation */ -void nmi_trigger_all_cpu_backtrace(bool include_self, - void (*raise)(cpumask_t *mask)); -bool nmi_cpu_backtrace(struct pt_regs *regs); - -#else -static inline bool trigger_all_cpu_backtrace(void) +static inline bool trigger_cpumask_backtrace(struct cpumask *mask) { +#if defined(arch_trigger_cpumask_backtrace) + arch_trigger_cpumask_backtrace(true, mask); + return true; +#else return false; +#endif } -static inline bool trigger_allbutself_cpu_backtrace(void) + +static inline bool trigger_single_cpu_backtrace(int cpu) { +#if defined(arch_trigger_cpumask_backtrace) + arch_trigger_cpumask_backtrace(true, cpumask_of(cpu)); + return true; +#else return false; -} #endif +} + +/* generic implementation */ +void nmi_trigger_cpumask_backtrace(bool include_self, + const cpumask_t *mask, + void (*raise)(cpumask_t *mask)); +bool nmi_cpu_backtrace(struct pt_regs *regs); #ifdef CONFIG_LOCKUP_DETECTOR u64 hw_nmi_get_sample_period(int watchdog_thresh); diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c index 26caf51cc238..5448d6621102 100644 --- a/lib/nmi_backtrace.c +++ b/lib/nmi_backtrace.c @@ -17,7 +17,7 @@ #include #include -#ifdef arch_trigger_all_cpu_backtrace +#ifdef arch_trigger_cpumask_backtrace /* For reliability, we're prepared to waste bits here. */ static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly; @@ -25,12 +25,13 @@ static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly; static unsigned long backtrace_flag; /* - * When raise() is called it will be is passed a pointer to the + * When raise() is called it will be passed a pointer to the * backtrace_mask. Architectures that call nmi_cpu_backtrace() * directly from their raise() functions may rely on the mask * they are passed being updated as a side effect of this call. */ -void nmi_trigger_all_cpu_backtrace(bool include_self, +void nmi_trigger_cpumask_backtrace(bool include_self, + const cpumask_t *mask, void (*raise)(cpumask_t *mask)) { int i, this_cpu = get_cpu(); @@ -44,13 +45,13 @@ void nmi_trigger_all_cpu_backtrace(bool include_self, return; } - cpumask_copy(to_cpumask(backtrace_mask), cpu_online_mask); + cpumask_copy(to_cpumask(backtrace_mask), mask); if (!include_self) cpumask_clear_cpu(this_cpu, to_cpumask(backtrace_mask)); if (!cpumask_empty(to_cpumask(backtrace_mask))) { - pr_info("Sending NMI to %s CPUs:\n", - (include_self ? "all" : "other")); + pr_info("Sending NMI from CPU %d to CPUs %*pbl:\n", + this_cpu, nr_cpumask_bits, to_cpumask(backtrace_mask)); raise(to_cpumask(backtrace_mask)); }