From ebc41f20d77f6ad91f1f2d2af5147dc9bb6b5eea Mon Sep 17 00:00:00 2001 From: Hidehiro Kawai Date: Tue, 22 Mar 2016 14:27:17 -0700 Subject: [PATCH] panic: change nmi_panic from macro to function Commit 1717f2096b54 ("panic, x86: Fix re-entrance problem due to panic on NMI") and commit 58c5661f2144 ("panic, x86: Allow CPUs to save registers even if looping in NMI context") introduced nmi_panic() which prevents concurrent/recursive execution of panic(). It also saves registers for the crash dump on x86. However, there are some cases where NMI handlers still use panic(). This patch set partially replaces them with nmi_panic() in those cases. Even this patchset is applied, some NMI or similar handlers (e.g. MCE handler) continue to use panic(). This is because I can't test them well and actual problems won't happen. For example, the possibility that normal panic and panic on MCE happen simultaneously is very low. This patch (of 3): Convert nmi_panic() to a proper function and export it instead of exporting internal implementation details to modules, for obvious reasons. Signed-off-by: Hidehiro Kawai Acked-by: Borislav Petkov Acked-by: Michal Nazarewicz Cc: Michal Hocko Cc: Rasmus Villemoes Cc: Nicolas Iooss Cc: Javi Merino Cc: Gobinda Charan Maji Cc: "Steven Rostedt (Red Hat)" Cc: Thomas Gleixner Cc: Vitaly Kuznetsov Cc: HATAYAMA Daisuke Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kernel.h | 21 +-------------------- kernel/panic.c | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b82646ee70eb..a13c52ccd8ac 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -255,7 +255,7 @@ extern long (*panic_blink)(int state); __printf(1, 2) void panic(const char *fmt, ...) __noreturn __cold; -void nmi_panic_self_stop(struct pt_regs *); +void nmi_panic(struct pt_regs *regs, const char *msg); extern void oops_enter(void); extern void oops_exit(void); void print_oops_end_marker(void); @@ -456,25 +456,6 @@ extern bool crash_kexec_post_notifiers; extern atomic_t panic_cpu; #define PANIC_CPU_INVALID -1 -/* - * A variant of panic() called from NMI context. We return if we've already - * panicked on this CPU. If another CPU already panicked, loop in - * nmi_panic_self_stop() which can provide architecture dependent code such - * as saving register state for crash dump. - */ -#define nmi_panic(regs, fmt, ...) \ -do { \ - int old_cpu, cpu; \ - \ - cpu = raw_smp_processor_id(); \ - old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, cpu); \ - \ - if (old_cpu == PANIC_CPU_INVALID) \ - panic(fmt, ##__VA_ARGS__); \ - else if (old_cpu != cpu) \ - nmi_panic_self_stop(regs); \ -} while (0) - /* * Only to be used by arch init code. If the user over-wrote the default * CONFIG_PANIC_TIMEOUT, honor it. diff --git a/kernel/panic.c b/kernel/panic.c index fa400852bf6c..535c96510a44 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -73,6 +73,26 @@ void __weak nmi_panic_self_stop(struct pt_regs *regs) atomic_t panic_cpu = ATOMIC_INIT(PANIC_CPU_INVALID); +/* + * A variant of panic() called from NMI context. We return if we've already + * panicked on this CPU. If another CPU already panicked, loop in + * nmi_panic_self_stop() which can provide architecture dependent code such + * as saving register state for crash dump. + */ +void nmi_panic(struct pt_regs *regs, const char *msg) +{ + int old_cpu, cpu; + + cpu = raw_smp_processor_id(); + old_cpu = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, cpu); + + if (old_cpu == PANIC_CPU_INVALID) + panic("%s", msg); + else if (old_cpu != cpu) + nmi_panic_self_stop(regs); +} +EXPORT_SYMBOL(nmi_panic); + /** * panic - halt the system * @fmt: The text string to print -- GitLab