From: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
To: Jonathan Corbet <corbet@lwn.net>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>,
"Eric W. Biederman" <ebiederm@xmission.com>,
"H. Peter Anvin" <hpa@zytor.com>,
Andrew Morton <akpm@linux-foundation.org>,
Thomas Gleixner <tglx@linutronix.de>,
Vivek Goyal <vgoyal@redhat.com>
Cc: linux-doc@vger.kernel.org, x86@kernel.org,
kexec@lists.infradead.org, linux-kernel@vger.kernel.org,
Ingo Molnar <mingo@redhat.com>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Subject: [PATCH 1/3] x86/panic: Fix re-entrance problem due to panic on NMI
Date: Wed, 22 Jul 2015 11:14:21 +0900 [thread overview]
Message-ID: <20150722021421.5155.9710.stgit@softrs> (raw)
In-Reply-To: <20150722021421.5155.74460.stgit@softrs>
If panic on NMI happens just after panic() on the same CPU, panic()
is recursively called. As the result, it stalls on panic_lock.
To avoid this problem, don't call panic() in NMI context if
we've already entered panic() (i.e. we hold panic_lock).
Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
arch/x86/kernel/nmi.c | 18 ++++++++++++------
include/linux/kernel.h | 4 ++++
kernel/panic.c | 33 +++++++++++++++++++++++++--------
3 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index d05bd2e..c14b23f 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -230,8 +230,8 @@ void unregister_nmi_handler(unsigned int type, const char *name)
}
#endif
- if (panic_on_unrecovered_nmi)
- panic("NMI: Not continuing");
+ if (panic_on_unrecovered_nmi && spin_trylock(&panic_lock))
+ __panic("NMI: Not continuing");
pr_emerg("Dazed and confused, but trying to continue\n");
@@ -255,8 +255,12 @@ void unregister_nmi_handler(unsigned int type, const char *name)
reason, smp_processor_id());
show_regs(regs);
- if (panic_on_io_nmi)
- panic("NMI IOCK error: Not continuing");
+ if (panic_on_io_nmi) {
+ if (spin_trylock(&panic_lock))
+ __panic("NMI IOCK error: Not continuing");
+ else
+ return; /* We don't want to wait and re-enable NMI */
+ }
/* Re-enable the IOCK line, wait for a few seconds */
reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
@@ -296,8 +300,10 @@ void unregister_nmi_handler(unsigned int type, const char *name)
reason, smp_processor_id());
pr_emerg("Do you have a strange power saving mode enabled?\n");
- if (unknown_nmi_panic || panic_on_unrecovered_nmi)
- panic("NMI: Not continuing");
+ if (unknown_nmi_panic || panic_on_unrecovered_nmi) {
+ if (spin_trylock(&panic_lock))
+ __panic("NMI: Not continuing");
+ }
pr_emerg("Dazed and confused, but trying to continue\n");
}
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 5582410..be430dc 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -250,11 +250,15 @@ static inline u32 reciprocal_scale(u32 val, u32 ep_ro)
static inline void might_fault(void) { }
#endif
+typedef struct spinlock spinlock_t;
+extern spinlock_t panic_lock;
extern struct atomic_notifier_head panic_notifier_list;
extern long (*panic_blink)(int state);
__printf(1, 2)
void panic(const char *fmt, ...)
__noreturn __cold;
+void __panic(char *msg)
+ __noreturn __cold;
extern void oops_enter(void);
extern void oops_exit(void);
void print_oops_end_marker(void);
diff --git a/kernel/panic.c b/kernel/panic.c
index 04e91ff..3c8338b 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -60,6 +60,8 @@ void __weak panic_smp_self_stop(void)
cpu_relax();
}
+DEFINE_SPINLOCK(panic_lock);
+
/**
* panic - halt the system
* @fmt: The text string to print
@@ -70,11 +72,8 @@ void __weak panic_smp_self_stop(void)
*/
void panic(const char *fmt, ...)
{
- static DEFINE_SPINLOCK(panic_lock);
static char buf[1024];
va_list args;
- long i, i_next = 0;
- int state = 0;
/*
* Disable local interrupts. This will prevent panic_smp_self_stop
@@ -97,12 +96,30 @@ void panic(const char *fmt, ...)
if (!spin_trylock(&panic_lock))
panic_smp_self_stop();
- console_verbose();
- bust_spinlocks(1);
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- pr_emerg("Kernel panic - not syncing: %s\n", buf);
+
+ __panic(buf);
+}
+
+/**
+ * __panic - no lock version of panic
+ * @msg: The text string to print
+ *
+ * Normally, please use panic(). This function can be used
+ * only if panic_lock has already been held.
+ *
+ * This function never returns.
+ */
+void __panic(char *msg)
+{
+ long i, i_next = 0;
+ int state = 0;
+
+ console_verbose();
+ bust_spinlocks(1);
+ pr_emerg("Kernel panic - not syncing: %s\n", msg);
#ifdef CONFIG_DEBUG_BUGVERBOSE
/*
* Avoid nested stack-dumping if a panic occurs during oops processing
@@ -131,7 +148,7 @@ void panic(const char *fmt, ...)
* Run any panic handlers, including those that might need to
* add information to the kmsg dump output.
*/
- atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
+ atomic_notifier_call_chain(&panic_notifier_list, 0, msg);
kmsg_dump(KMSG_DUMP_PANIC);
@@ -190,7 +207,7 @@ void panic(const char *fmt, ...)
disabled_wait(caller);
}
#endif
- pr_emerg("---[ end Kernel panic - not syncing: %s\n", buf);
+ pr_emerg("---[ end Kernel panic - not syncing: %s\n", msg);
local_irq_enable();
for (i = 0; ; i += PANIC_TIMER_STEP) {
touch_softlockup_watchdog();
_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec
WARNING: multiple messages have this Message-ID (diff)
From: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
To: Jonathan Corbet <corbet@lwn.net>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>,
"Eric W. Biederman" <ebiederm@xmission.com>,
"H. Peter Anvin" <hpa@zytor.com>,
Andrew Morton <akpm@linux-foundation.org>,
Thomas Gleixner <tglx@linutronix.de>,
Vivek Goyal <vgoyal@redhat.com>
Cc: linux-doc@vger.kernel.org, x86@kernel.org,
kexec@lists.infradead.org, linux-kernel@vger.kernel.org,
Ingo Molnar <mingo@redhat.com>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Subject: [PATCH 1/3] x86/panic: Fix re-entrance problem due to panic on NMI
Date: Wed, 22 Jul 2015 11:14:21 +0900 [thread overview]
Message-ID: <20150722021421.5155.9710.stgit@softrs> (raw)
In-Reply-To: <20150722021421.5155.74460.stgit@softrs>
If panic on NMI happens just after panic() on the same CPU, panic()
is recursively called. As the result, it stalls on panic_lock.
To avoid this problem, don't call panic() in NMI context if
we've already entered panic() (i.e. we hold panic_lock).
Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Peter Zijlstra <peterz@infradead.org>
---
arch/x86/kernel/nmi.c | 18 ++++++++++++------
include/linux/kernel.h | 4 ++++
kernel/panic.c | 33 +++++++++++++++++++++++++--------
3 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
index d05bd2e..c14b23f 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/nmi.c
@@ -230,8 +230,8 @@ void unregister_nmi_handler(unsigned int type, const char *name)
}
#endif
- if (panic_on_unrecovered_nmi)
- panic("NMI: Not continuing");
+ if (panic_on_unrecovered_nmi && spin_trylock(&panic_lock))
+ __panic("NMI: Not continuing");
pr_emerg("Dazed and confused, but trying to continue\n");
@@ -255,8 +255,12 @@ void unregister_nmi_handler(unsigned int type, const char *name)
reason, smp_processor_id());
show_regs(regs);
- if (panic_on_io_nmi)
- panic("NMI IOCK error: Not continuing");
+ if (panic_on_io_nmi) {
+ if (spin_trylock(&panic_lock))
+ __panic("NMI IOCK error: Not continuing");
+ else
+ return; /* We don't want to wait and re-enable NMI */
+ }
/* Re-enable the IOCK line, wait for a few seconds */
reason = (reason & NMI_REASON_CLEAR_MASK) | NMI_REASON_CLEAR_IOCHK;
@@ -296,8 +300,10 @@ void unregister_nmi_handler(unsigned int type, const char *name)
reason, smp_processor_id());
pr_emerg("Do you have a strange power saving mode enabled?\n");
- if (unknown_nmi_panic || panic_on_unrecovered_nmi)
- panic("NMI: Not continuing");
+ if (unknown_nmi_panic || panic_on_unrecovered_nmi) {
+ if (spin_trylock(&panic_lock))
+ __panic("NMI: Not continuing");
+ }
pr_emerg("Dazed and confused, but trying to continue\n");
}
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 5582410..be430dc 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -250,11 +250,15 @@ static inline u32 reciprocal_scale(u32 val, u32 ep_ro)
static inline void might_fault(void) { }
#endif
+typedef struct spinlock spinlock_t;
+extern spinlock_t panic_lock;
extern struct atomic_notifier_head panic_notifier_list;
extern long (*panic_blink)(int state);
__printf(1, 2)
void panic(const char *fmt, ...)
__noreturn __cold;
+void __panic(char *msg)
+ __noreturn __cold;
extern void oops_enter(void);
extern void oops_exit(void);
void print_oops_end_marker(void);
diff --git a/kernel/panic.c b/kernel/panic.c
index 04e91ff..3c8338b 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -60,6 +60,8 @@ void __weak panic_smp_self_stop(void)
cpu_relax();
}
+DEFINE_SPINLOCK(panic_lock);
+
/**
* panic - halt the system
* @fmt: The text string to print
@@ -70,11 +72,8 @@ void __weak panic_smp_self_stop(void)
*/
void panic(const char *fmt, ...)
{
- static DEFINE_SPINLOCK(panic_lock);
static char buf[1024];
va_list args;
- long i, i_next = 0;
- int state = 0;
/*
* Disable local interrupts. This will prevent panic_smp_self_stop
@@ -97,12 +96,30 @@ void panic(const char *fmt, ...)
if (!spin_trylock(&panic_lock))
panic_smp_self_stop();
- console_verbose();
- bust_spinlocks(1);
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- pr_emerg("Kernel panic - not syncing: %s\n", buf);
+
+ __panic(buf);
+}
+
+/**
+ * __panic - no lock version of panic
+ * @msg: The text string to print
+ *
+ * Normally, please use panic(). This function can be used
+ * only if panic_lock has already been held.
+ *
+ * This function never returns.
+ */
+void __panic(char *msg)
+{
+ long i, i_next = 0;
+ int state = 0;
+
+ console_verbose();
+ bust_spinlocks(1);
+ pr_emerg("Kernel panic - not syncing: %s\n", msg);
#ifdef CONFIG_DEBUG_BUGVERBOSE
/*
* Avoid nested stack-dumping if a panic occurs during oops processing
@@ -131,7 +148,7 @@ void panic(const char *fmt, ...)
* Run any panic handlers, including those that might need to
* add information to the kmsg dump output.
*/
- atomic_notifier_call_chain(&panic_notifier_list, 0, buf);
+ atomic_notifier_call_chain(&panic_notifier_list, 0, msg);
kmsg_dump(KMSG_DUMP_PANIC);
@@ -190,7 +207,7 @@ void panic(const char *fmt, ...)
disabled_wait(caller);
}
#endif
- pr_emerg("---[ end Kernel panic - not syncing: %s\n", buf);
+ pr_emerg("---[ end Kernel panic - not syncing: %s\n", msg);
local_irq_enable();
for (i = 0; ; i += PANIC_TIMER_STEP) {
touch_softlockup_watchdog();
next prev parent reply other threads:[~2015-07-22 7:38 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-22 2:14 [PATCH 0/3] x86: Fix panic vs. NMI issues Hidehiro Kawai
2015-07-22 2:14 ` Hidehiro Kawai
2015-07-22 2:14 ` [PATCH 3/3] x86/apic: Introduce noextnmi boot option Hidehiro Kawai
2015-07-22 2:14 ` Hidehiro Kawai
2015-07-22 2:14 ` [PATCH 2/3] kexec: Fix race between panic() and crash_kexec() directly called Hidehiro Kawai
2015-07-22 2:14 ` Hidehiro Kawai
2015-07-22 2:14 ` Hidehiro Kawai [this message]
2015-07-22 2:14 ` [PATCH 1/3] x86/panic: Fix re-entrance problem due to panic on NMI Hidehiro Kawai
2015-07-23 8:15 ` Peter Zijlstra
2015-07-23 8:15 ` Peter Zijlstra
2015-07-23 9:43 ` Hidehiro Kawai
2015-07-23 9:43 ` Hidehiro Kawai
2015-07-23 8:25 ` [PATCH 0/3] x86: Fix panic vs. NMI issues Michal Hocko
2015-07-23 8:25 ` Michal Hocko
2015-07-23 10:11 ` Hidehiro Kawai
2015-07-23 10:11 ` Hidehiro Kawai
2015-07-23 11:25 ` Michal Hocko
2015-07-23 11:25 ` Michal Hocko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150722021421.5155.9710.stgit@softrs \
--to=hidehiro.kawai.ez@hitachi.com \
--cc=akpm@linux-foundation.org \
--cc=corbet@lwn.net \
--cc=ebiederm@xmission.com \
--cc=hpa@zytor.com \
--cc=kexec@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=mingo@kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=vgoyal@redhat.com \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.