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

Commit 58687acb authored by Don Zickus's avatar Don Zickus Committed by Frederic Weisbecker
Browse files

lockup_detector: Combine nmi_watchdog and softlockup detector



The new nmi_watchdog (which uses the perf event subsystem) is very
similar in structure to the softlockup detector.  Using Ingo's
suggestion, I combined the two functionalities into one file:
kernel/watchdog.c.

Now both the nmi_watchdog (or hardlockup detector) and softlockup
detector sit on top of the perf event subsystem, which is run every
60 seconds or so to see if there are any lockups.

To detect hardlockups, cpus not responding to interrupts, I
implemented an hrtimer that runs 5 times for every perf event
overflow event.  If that stops counting on a cpu, then the cpu is
most likely in trouble.

To detect softlockups, tasks not yielding to the scheduler, I used the
previous kthread idea that now gets kicked every time the hrtimer fires.
If the kthread isn't being scheduled neither is anyone else and the
warning is printed to the console.

I tested this on x86_64 and both the softlockup and hardlockup paths
work.

V2:
- cleaned up the Kconfig and softlockup combination
- surrounded hardlockup cases with #ifdef CONFIG_PERF_EVENTS_NMI
- seperated out the softlockup case from perf event subsystem
- re-arranged the enabling/disabling nmi watchdog from proc space
- added cpumasks for hardlockup failure cases
- removed fallback to soft events if no PMU exists for hard events

V3:
- comment cleanups
- drop support for older softlockup code
- per_cpu cleanups
- completely remove software clock base hardlockup detector
- use per_cpu masking on hard/soft lockup detection
- #ifdef cleanups
- rename config option NMI_WATCHDOG to LOCKUP_DETECTOR
- documentation additions

V4:
- documentation fixes
- convert per_cpu to __get_cpu_var
- powerpc compile fixes

V5:
- split apart warn flags for hard and soft lockups

TODO:
- figure out how to make an arch-agnostic clock2cycles call
  (if possible) to feed into perf events as a sample period

[fweisbec: merged conflict patch]

Signed-off-by: default avatarDon Zickus <dzickus@redhat.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Eric Paris <eparis@redhat.com>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
LKML-Reference: <1273266711-18706-2-git-send-email-dzickus@redhat.com>
Signed-off-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
parent a9aa1d02
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1777,6 +1777,8 @@ and is between 256 and 4096 characters. It is defined in the file

	nousb		[USB] Disable the USB subsystem

	nowatchdog	[KNL] Disable the lockup detector.

	nowb		[ARM]

	nox2apic	[X86-64,APIC] Do not enable x2APIC mode.
+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ int do_nmi_callback(struct pt_regs *regs, int cpu);

extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
extern int check_nmi_watchdog(void);
#if !defined(CONFIG_NMI_WATCHDOG)
#if !defined(CONFIG_LOCKUP_DETECTOR)
extern int nmi_watchdog_enabled;
#endif
extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
+2 −2
Original line number Diff line number Diff line
@@ -3,10 +3,10 @@
#

obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o apic_noop.o probe_$(BITS).o ipi.o
ifneq ($(CONFIG_NMI_WATCHDOG),y)
ifneq ($(CONFIG_LOCKUP_DETECTOR),y)
obj-$(CONFIG_X86_LOCAL_APIC)	+= nmi.o
endif
obj-$(CONFIG_NMI_WATCHDOG)	+= hw_nmi.o
obj-$(CONFIG_LOCKUP_DETECTOR)	+= hw_nmi.o

obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
obj-$(CONFIG_SMP)		+= ipi.o
+1 −1
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ int hw_nmi_is_cpu_stuck(struct pt_regs *regs)

u64 hw_nmi_get_sample_period(void)
{
	return cpu_khz * 1000;
	return (u64)(cpu_khz) * 1000 * 60;
}

#ifdef ARCH_HAS_NMI_WATCHDOG
+2 −2
Original line number Diff line number Diff line
@@ -406,7 +406,7 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
							== NOTIFY_STOP)
			return;

#ifndef CONFIG_NMI_WATCHDOG
#ifndef CONFIG_LOCKUP_DETECTOR
		/*
		 * Ok, so this is none of the documented NMI sources,
		 * so it must be the NMI watchdog.
@@ -414,7 +414,7 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
		if (nmi_watchdog_tick(regs, reason))
			return;
		if (!do_nmi_callback(regs, cpu))
#endif /* !CONFIG_NMI_WATCHDOG */
#endif /* !CONFIG_LOCKUP_DETECTOR */
			unknown_nmi_error(reason, regs);
#else
		unknown_nmi_error(reason, regs);
Loading