diff options
Diffstat (limited to 'include/linux/kernel.h')
| -rw-r--r-- | include/linux/kernel.h | 28 | 
1 files changed, 28 insertions, 0 deletions
| diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 350dfb08aee3..7311c3294e25 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -255,6 +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 *);  extern void oops_enter(void);  extern void oops_exit(void);  void print_oops_end_marker(void); @@ -446,6 +447,33 @@ extern int sysctl_panic_on_stackoverflow;  extern bool crash_kexec_post_notifiers;  /* + * panic_cpu is used for synchronizing panic() and crash_kexec() execution. It + * holds a CPU number which is executing panic() currently. A value of + * PANIC_CPU_INVALID means no CPU has entered panic() or crash_kexec(). + */ +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.   */ | 
