@@ -58,6 +58,8 @@ static struct hrtimer softdog_preticktock;
static enum hrtimer_restart softdog_fire(struct hrtimer *timer)
{
+ watchdog_softlockup(NULL, true);
+
module_put(THIS_MODULE);
if (soft_noboot) {
pr_crit("Triggered - Reboot ignored\n");
@@ -215,4 +215,13 @@ extern void watchdog_unregister_device(struct watchdog_device *);
/* devres register variant */
int devm_watchdog_register_device(struct device *dev, struct watchdog_device *);
+#if IS_ENABLED(CONFIG_LOCKUP_DETECTOR)
+extern void watchdog_softlockup(struct pt_regs *regs, bool show_backtrace);
+#else
+static inline void watchdog_softlockup(struct pt_regs *regs,
+ bool show_backtrace)
+{
+}
+#endif
+
#endif /* ifndef _LINUX_WATCHDOG_H */
@@ -24,6 +24,7 @@
#include <linux/workqueue.h>
#include <linux/sched/clock.h>
#include <linux/sched/debug.h>
+#include <linux/watchdog.h>
#include <asm/irq_regs.h>
#include <linux/kvm_para.h>
@@ -415,30 +416,21 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
}
pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
- smp_processor_id(), duration,
- current->comm, task_pid_nr(current));
- __this_cpu_write(softlockup_task_ptr_saved, current);
- print_modules();
- print_irqtrace_events(current);
- if (regs)
- show_regs(regs);
- else
- dump_stack();
+ smp_processor_id(), duration,
+ current->comm, task_pid_nr(current));
+
+ watchdog_softlockup(regs, softlockup_all_cpu_backtrace);
+ if (softlockup_panic)
+ panic("softlockup: hung tasks");
if (softlockup_all_cpu_backtrace) {
/* Avoid generating two back traces for current
* given that one is already made above
*/
- trigger_allbutself_cpu_backtrace();
-
clear_bit(0, &soft_lockup_nmi_warn);
/* Barrier to sync with other cpus */
smp_mb__after_atomic();
}
-
- add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
- if (softlockup_panic)
- panic("softlockup: hung tasks");
__this_cpu_write(soft_watchdog_warn, true);
} else
__this_cpu_write(soft_watchdog_warn, false);
@@ -787,3 +779,20 @@ void __init lockup_detector_init(void)
nmi_watchdog_available = true;
lockup_detector_setup();
}
+
+void watchdog_softlockup(struct pt_regs *regs, bool show_backtrace)
+{
+ __this_cpu_write(softlockup_task_ptr_saved, current);
+ print_modules();
+ print_irqtrace_events(current);
+ if (regs)
+ show_regs(regs);
+ else
+ dump_stack();
+
+ if (show_backtrace)
+ trigger_allbutself_cpu_backtrace();
+
+ add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK);
+}
+EXPORT_SYMBOL(watchdog_softlockup);