From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933193AbbLSKPa (ORCPT ); Sat, 19 Dec 2015 05:15:30 -0500 Received: from terminus.zytor.com ([198.137.202.10]:36609 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932840AbbLSKPF (ORCPT ); Sat, 19 Dec 2015 05:15:05 -0500 Date: Sat, 19 Dec 2015 02:14:04 -0800 From: tip-bot for Hidehiro Kawai Message-ID: Cc: mhocko@suse.com, dyoung@redhat.com, ebiederm@xmission.com, bhe@redhat.com, hidehiro.kawai.ez@hitachi.com, mingo@kernel.org, rostedt@goodmis.org, hpa@zytor.com, vgoyal@redhat.com, peterz@infradead.org, x86@kernel.org, akpm@linux-foundation.org, corbet@lwn.net, masami.hiramatsu.pt@hitachi.com, linux-kernel@vger.kernel.org, s.l-h@gmx.de, luto@kernel.org, jiang.liu@linux.intel.com, tglx@linutronix.de, bp@suse.de Reply-To: hidehiro.kawai.ez@hitachi.com, dyoung@redhat.com, ebiederm@xmission.com, bhe@redhat.com, mhocko@suse.com, rostedt@goodmis.org, hpa@zytor.com, mingo@kernel.org, linux-kernel@vger.kernel.org, s.l-h@gmx.de, luto@kernel.org, akpm@linux-foundation.org, masami.hiramatsu.pt@hitachi.com, corbet@lwn.net, vgoyal@redhat.com, x86@kernel.org, peterz@infradead.org, tglx@linutronix.de, bp@suse.de, jiang.liu@linux.intel.com In-Reply-To: <20151210065245.4587.39316.stgit@softrs> References: <20151210065245.4587.39316.stgit@softrs> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/apic] x86/nmi: Save regs in crash dump on external NMI Git-Commit-ID: b279d67df88a49c6ca32b3eebd195660254be394 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: b279d67df88a49c6ca32b3eebd195660254be394 Gitweb: http://git.kernel.org/tip/b279d67df88a49c6ca32b3eebd195660254be394 Author: Hidehiro Kawai AuthorDate: Mon, 14 Dec 2015 11:19:13 +0100 Committer: Thomas Gleixner CommitDate: Sat, 19 Dec 2015 11:07:01 +0100 x86/nmi: Save regs in crash dump on external NMI Now, multiple CPUs can receive an external NMI simultaneously by specifying the "apic_extnmi=all" command line parameter. When we take a crash dump by using external NMI with this option, we fail to save registers into the crash dump. This happens as follows: CPU 0 CPU 1 ================================ ============================= receive an external NMI default_do_nmi() receive an external NMI spin_lock(&nmi_reason_lock) default_do_nmi() io_check_error() spin_lock(&nmi_reason_lock) panic() busy loop ... kdump_nmi_shootdown_cpus() issue NMI IPI -----------> blocked until IRET busy loop... Here, since CPU 1 is in NMI context, an additional NMI from CPU 0 remains unhandled until CPU 1 IRETs. However, CPU 1 will never execute IRET so the NMI is not handled and the callback function to save registers is never called. To solve this issue, we check if the IPI for crash dumping was issued while waiting for nmi_reason_lock to be released, and if so, call its callback function directly. If the IPI is not issued (e.g. kdump is disabled), the actual behavior doesn't change. Signed-off-by: Hidehiro Kawai Acked-by: Michal Hocko Cc: Andrew Morton Cc: Andy Lutomirski Cc: Baoquan He Cc: Dave Young Cc: "Eric W. Biederman" Cc: "H. Peter Anvin" Cc: Ingo Molnar Cc: Jiang Liu Cc: Jonathan Corbet Cc: kexec@lists.infradead.org Cc: linux-doc@vger.kernel.org Cc: Masami Hiramatsu Cc: Peter Zijlstra Cc: Stefan Lippers-Hollmann Cc: Steven Rostedt Cc: Thomas Gleixner Cc: Vivek Goyal Cc: x86-ml Link: http://lkml.kernel.org/r/20151210065245.4587.39316.stgit@softrs Signed-off-by: Borislav Petkov Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/reboot.h | 1 + arch/x86/kernel/nmi.c | 16 ++++++++++++++-- arch/x86/kernel/reboot.c | 24 +++++++++++++++++------- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/reboot.h b/arch/x86/include/asm/reboot.h index a82c4f1..2cb1cc2 100644 --- a/arch/x86/include/asm/reboot.h +++ b/arch/x86/include/asm/reboot.h @@ -25,5 +25,6 @@ void __noreturn machine_real_restart(unsigned int type); typedef void (*nmi_shootdown_cb)(int, struct pt_regs*); void nmi_shootdown_cpus(nmi_shootdown_cb callback); +void run_crash_ipi_callback(struct pt_regs *regs); #endif /* _ASM_X86_REBOOT_H */ diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 424aec4..8a2cdd7 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -29,6 +29,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -356,8 +357,19 @@ static void default_do_nmi(struct pt_regs *regs) return; } - /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */ - raw_spin_lock(&nmi_reason_lock); + /* + * Non-CPU-specific NMI: NMI sources can be processed on any CPU. + * + * Another CPU may be processing panic routines while holding + * nmi_reason_lock. Check if the CPU issued the IPI for crash dumping, + * and if so, call its callback directly. If there is no CPU preparing + * crash dump, we simply loop here. + */ + while (!raw_spin_trylock(&nmi_reason_lock)) { + run_crash_ipi_callback(regs); + cpu_relax(); + } + reason = x86_platform.get_nmi_reason(); if (reason & NMI_REASON_MASK) { diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 1da1302..d64889a 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -793,17 +793,23 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) /* Leave the nmi callback set */ } +/* + * Check if the crash dumping IPI got issued and if so, call its callback + * directly. This function is used when we have already been in NMI handler. + * It doesn't return. + */ +void run_crash_ipi_callback(struct pt_regs *regs) +{ + if (crash_ipi_issued) + crash_nmi_callback(0, regs); +} + /* Override the weak function in kernel/panic.c */ void nmi_panic_self_stop(struct pt_regs *regs) { while (1) { - /* - * Wait for the crash dumping IPI to be issued, and then - * call its callback directly. - */ - if (READ_ONCE(crash_ipi_issued)) - crash_nmi_callback(0, regs); /* Don't return */ - + /* If no CPU is preparing crash dump, we simply loop here. */ + run_crash_ipi_callback(regs); cpu_relax(); } } @@ -813,4 +819,8 @@ void nmi_shootdown_cpus(nmi_shootdown_cb callback) { /* No other CPUs to shoot down */ } + +void run_crash_ipi_callback(struct pt_regs *regs) +{ +} #endif