Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2104180a authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Linus Torvalds
Browse files

powerpc/64s: implement arch-specific hardlockup watchdog

Implement an arch-speicfic watchdog rather than use the perf-based
hardlockup detector.

The new watchdog takes the soft-NMI directly, rather than going through
perf.  Perf interrupts are to be made maskable in future, so that would
prevent the perf detector from working in those regions.

Additionally, implement a SMP based detector where all CPUs watch one
another by pinging a shared cpumask.  This is because powerpc Book3S
does not have a true periodic local NMI, but some platforms do implement
a true NMI IPI.

If a CPU is stuck with interrupts hard disabled, the soft-NMI watchdog
does not work, but the SMP watchdog will.  Even on platforms without a
true NMI IPI to get a good trace from the stuck CPU, other CPUs will
notice the lockup sufficiently to report it and panic.

[npiggin@gmail.com: honor watchdog disable at boot/hotplug]
  Link: http://lkml.kernel.org/r/20170621001346.5bb337c9@roar.ozlabs.ibm.com
[npiggin@gmail.com: fix false positive warning at CPU unplug]
  Link: http://lkml.kernel.org/r/20170630080740.20766-1-npiggin@gmail.com
[akpm@linux-foundation.org: coding-style fixes]
Link: http://lkml.kernel.org/r/20170616065715.18390-6-npiggin@gmail.com


Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Reviewed-by: default avatarDon Zickus <dzickus@redhat.com>
Tested-by: Babu Moger <babu.moger@oracle.com>	[sparc]
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a10a842f
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -82,7 +82,7 @@ config NR_IRQS

config NMI_IPI
	bool
	depends on SMP && (DEBUGGER || KEXEC_CORE)
	depends on SMP && (DEBUGGER || KEXEC_CORE || HARDLOCKUP_DETECTOR)
	default y

config STACKTRACE_SUPPORT
@@ -192,12 +192,13 @@ config PPC
	select HAVE_MEMBLOCK
	select HAVE_MEMBLOCK_NODE_MAP
	select HAVE_MOD_ARCH_SPECIFIC
	select HAVE_NMI				if PERF_EVENTS
	select HAVE_NMI				if PERF_EVENTS || (PPC64 && PPC_BOOK3S)
	select HAVE_HARDLOCKUP_DETECTOR_ARCH	if (PPC64 && PPC_BOOK3S)
	select HAVE_OPROFILE
	select HAVE_OPTPROBES			if PPC64
	select HAVE_PERF_EVENTS
	select HAVE_PERF_EVENTS_NMI		if PPC64
	select HAVE_HARDLOCKUP_DETECTOR_PERF	if HAVE_PERF_EVENTS_NMI
	select HAVE_HARDLOCKUP_DETECTOR_PERF	if HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH
	select HAVE_PERF_REGS
	select HAVE_PERF_USER_STACK_DUMP
	select HAVE_RCU_TABLE_FREE		if SMP
+11 −0
Original line number Diff line number Diff line
#ifndef _ASM_NMI_H
#define _ASM_NMI_H

#ifdef CONFIG_HARDLOCKUP_DETECTOR
extern void arch_touch_nmi_watchdog(void);

extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask,
					   bool exclude_self);
#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace

#else
static inline void arch_touch_nmi_watchdog(void) {}
#endif

#endif /* _ASM_NMI_H */
+2 −0
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ struct smp_ops_t {
	int   (*cpu_bootable)(unsigned int nr);
};

extern void smp_flush_nmi_ipi(u64 delay_us);
extern int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us);
extern void smp_send_debugger_break(void);
extern void start_secondary_resume(void);
extern void smp_generic_give_timebase(void);
+1 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \
				   signal_64.o ptrace32.o \
				   paca.o nvram_64.o firmware.o
obj-$(CONFIG_VDSO32)		+= vdso32/
obj-$(CONFIG_HARDLOCKUP_DETECTOR)	+= watchdog.o
obj-$(CONFIG_HAVE_HW_BREAKPOINT)	+= hw_breakpoint.o
obj-$(CONFIG_PPC_BOOK3S_64)	+= cpu_setup_ppc970.o cpu_setup_pa6t.o
obj-$(CONFIG_PPC_BOOK3S_64)	+= cpu_setup_power.o
+28 −2
Original line number Diff line number Diff line
@@ -1314,6 +1314,31 @@ EXC_REAL_NONE(0x1800, 0x100)
EXC_VIRT_NONE(0x5800, 0x100)
#endif

#if defined(CONFIG_HARDLOCKUP_DETECTOR) && defined(CONFIG_HAVE_HARDLOCKUP_DETECTOR_ARCH)

#define MASKED_DEC_HANDLER_LABEL 3f

#define MASKED_DEC_HANDLER(_H)				\
3: /* soft-nmi */					\
	std	r12,PACA_EXGEN+EX_R12(r13);		\
	GET_SCRATCH0(r10);				\
	std	r10,PACA_EXGEN+EX_R13(r13);		\
	EXCEPTION_PROLOG_PSERIES_1(soft_nmi_common, _H)

EXC_COMMON_BEGIN(soft_nmi_common)
	mr	r10,r1
	ld	r1,PACAEMERGSP(r13)
	ld	r1,PACA_NMI_EMERG_SP(r13)
	subi	r1,r1,INT_FRAME_SIZE
	EXCEPTION_COMMON_NORET_STACK(PACA_EXGEN, 0x900,
			system_reset, soft_nmi_interrupt,
			ADD_NVGPRS;ADD_RECONCILE)
	b	ret_from_except

#else
#define MASKED_DEC_HANDLER_LABEL 2f /* normal return */
#define MASKED_DEC_HANDLER(_H)
#endif

/*
 * An interrupt came in while soft-disabled. We set paca->irq_happened, then:
@@ -1336,7 +1361,7 @@ masked_##_H##interrupt: \
	lis	r10,0x7fff;				\
	ori	r10,r10,0xffff;				\
	mtspr	SPRN_DEC,r10;				\
	b	2f;					\
	b	MASKED_DEC_HANDLER_LABEL;		\
1:	cmpwi	r10,PACA_IRQ_DBELL;			\
	beq	2f;					\
	cmpwi	r10,PACA_IRQ_HMI;			\
@@ -1351,7 +1376,8 @@ masked_##_H##interrupt: \
	ld	r11,PACA_EXGEN+EX_R11(r13);		\
	GET_SCRATCH0(r13);				\
	##_H##rfid;					\
	b	.
	b	.;					\
	MASKED_DEC_HANDLER(_H)

/*
 * Real mode exceptions actually use this too, but alternate
Loading