158687acbSDon Zickus /* 258687acbSDon Zickus * Detect hard and soft lockups on a system 358687acbSDon Zickus * 458687acbSDon Zickus * started by Don Zickus, Copyright (C) 2010 Red Hat, Inc. 558687acbSDon Zickus * 686f5e6a7SFernando Luis Vázquez Cao * Note: Most of this code is borrowed heavily from the original softlockup 786f5e6a7SFernando Luis Vázquez Cao * detector, so thanks to Ingo for the initial implementation. 886f5e6a7SFernando Luis Vázquez Cao * Some chunks also taken from the old x86-specific nmi watchdog code, thanks 958687acbSDon Zickus * to those contributors as well. 1058687acbSDon Zickus */ 1158687acbSDon Zickus 125f92a7b0SKefeng Wang #define pr_fmt(fmt) "watchdog: " fmt 134501980aSAndrew Morton 1458687acbSDon Zickus #include <linux/mm.h> 1558687acbSDon Zickus #include <linux/cpu.h> 1658687acbSDon Zickus #include <linux/nmi.h> 1758687acbSDon Zickus #include <linux/init.h> 1858687acbSDon Zickus #include <linux/module.h> 1958687acbSDon Zickus #include <linux/sysctl.h> 20bcd951cfSThomas Gleixner #include <linux/smpboot.h> 218bd75c77SClark Williams #include <linux/sched/rt.h> 22ae7e81c0SIngo Molnar #include <uapi/linux/sched/types.h> 23fe4ba3c3SChris Metcalf #include <linux/tick.h> 2482607adcSTejun Heo #include <linux/workqueue.h> 25e6017571SIngo Molnar #include <linux/sched/clock.h> 26b17b0153SIngo Molnar #include <linux/sched/debug.h> 2758687acbSDon Zickus 2858687acbSDon Zickus #include <asm/irq_regs.h> 295d1c0f4aSEric B Munson #include <linux/kvm_para.h> 3081a4beefSUlrich Obergfell #include <linux/kthread.h> 3158687acbSDon Zickus 32946d1977SThomas Gleixner static DEFINE_MUTEX(watchdog_mutex); 33ab992dc3SPeter Zijlstra 3405a4a952SNicholas Piggin #if defined(CONFIG_HARDLOCKUP_DETECTOR) || defined(CONFIG_HAVE_NMI_WATCHDOG) 3505a4a952SNicholas Piggin unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED | 3605a4a952SNicholas Piggin NMI_WATCHDOG_ENABLED; 3784d56e66SUlrich Obergfell #else 38249e52e3SBabu Moger unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED; 3984d56e66SUlrich Obergfell #endif 4005a4a952SNicholas Piggin 417feeb9cdSThomas Gleixner int __read_mostly nmi_watchdog_user_enabled; 427feeb9cdSThomas Gleixner int __read_mostly soft_watchdog_user_enabled; 437feeb9cdSThomas Gleixner int __read_mostly watchdog_user_enabled; 447feeb9cdSThomas Gleixner int __read_mostly watchdog_thresh = 10; 457feeb9cdSThomas Gleixner 467feeb9cdSThomas Gleixner struct cpumask watchdog_allowed_mask __read_mostly; 477feeb9cdSThomas Gleixner static bool softlockup_threads_initialized __read_mostly; 487feeb9cdSThomas Gleixner 497feeb9cdSThomas Gleixner struct cpumask watchdog_cpumask __read_mostly; 507feeb9cdSThomas Gleixner unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask); 517feeb9cdSThomas Gleixner 5205a4a952SNicholas Piggin #ifdef CONFIG_HARDLOCKUP_DETECTOR 5305a4a952SNicholas Piggin /* 5405a4a952SNicholas Piggin * Should we panic when a soft-lockup or hard-lockup occurs: 5505a4a952SNicholas Piggin */ 5605a4a952SNicholas Piggin unsigned int __read_mostly hardlockup_panic = 5705a4a952SNicholas Piggin CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE; 5805a4a952SNicholas Piggin /* 5905a4a952SNicholas Piggin * We may not want to enable hard lockup detection by default in all cases, 6005a4a952SNicholas Piggin * for example when running the kernel as a guest on a hypervisor. In these 6105a4a952SNicholas Piggin * cases this function can be called to disable hard lockup detection. This 6205a4a952SNicholas Piggin * function should only be executed once by the boot processor before the 6305a4a952SNicholas Piggin * kernel command line parameters are parsed, because otherwise it is not 6405a4a952SNicholas Piggin * possible to override this in hardlockup_panic_setup(). 6505a4a952SNicholas Piggin */ 667a355820SThomas Gleixner void __init hardlockup_detector_disable(void) 6705a4a952SNicholas Piggin { 6805a4a952SNicholas Piggin watchdog_enabled &= ~NMI_WATCHDOG_ENABLED; 6905a4a952SNicholas Piggin } 7005a4a952SNicholas Piggin 7105a4a952SNicholas Piggin static int __init hardlockup_panic_setup(char *str) 7205a4a952SNicholas Piggin { 7305a4a952SNicholas Piggin if (!strncmp(str, "panic", 5)) 7405a4a952SNicholas Piggin hardlockup_panic = 1; 7505a4a952SNicholas Piggin else if (!strncmp(str, "nopanic", 7)) 7605a4a952SNicholas Piggin hardlockup_panic = 0; 7705a4a952SNicholas Piggin else if (!strncmp(str, "0", 1)) 7805a4a952SNicholas Piggin watchdog_enabled &= ~NMI_WATCHDOG_ENABLED; 7905a4a952SNicholas Piggin else if (!strncmp(str, "1", 1)) 8005a4a952SNicholas Piggin watchdog_enabled |= NMI_WATCHDOG_ENABLED; 8105a4a952SNicholas Piggin return 1; 8205a4a952SNicholas Piggin } 8305a4a952SNicholas Piggin __setup("nmi_watchdog=", hardlockup_panic_setup); 8405a4a952SNicholas Piggin 85368a7e2cSThomas Gleixner # ifdef CONFIG_SMP 86368a7e2cSThomas Gleixner int __read_mostly sysctl_hardlockup_all_cpu_backtrace; 8705a4a952SNicholas Piggin 88368a7e2cSThomas Gleixner static int __init hardlockup_all_cpu_backtrace_setup(char *str) 89368a7e2cSThomas Gleixner { 90368a7e2cSThomas Gleixner sysctl_hardlockup_all_cpu_backtrace = !!simple_strtol(str, NULL, 0); 91368a7e2cSThomas Gleixner return 1; 92368a7e2cSThomas Gleixner } 93368a7e2cSThomas Gleixner __setup("hardlockup_all_cpu_backtrace=", hardlockup_all_cpu_backtrace_setup); 94368a7e2cSThomas Gleixner # endif /* CONFIG_SMP */ 95368a7e2cSThomas Gleixner #endif /* CONFIG_HARDLOCKUP_DETECTOR */ 9605a4a952SNicholas Piggin 97ec6a9066SUlrich Obergfell /* 9805a4a952SNicholas Piggin * These functions can be overridden if an architecture implements its 9905a4a952SNicholas Piggin * own hardlockup detector. 100a10a842fSNicholas Piggin * 101a10a842fSNicholas Piggin * watchdog_nmi_enable/disable can be implemented to start and stop when 102a10a842fSNicholas Piggin * softlockup watchdog threads start and stop. The arch must select the 103a10a842fSNicholas Piggin * SOFTLOCKUP_DETECTOR Kconfig. 10405a4a952SNicholas Piggin */ 10505a4a952SNicholas Piggin int __weak watchdog_nmi_enable(unsigned int cpu) 10605a4a952SNicholas Piggin { 10705a4a952SNicholas Piggin return 0; 10805a4a952SNicholas Piggin } 109941154bdSThomas Gleixner 11005a4a952SNicholas Piggin void __weak watchdog_nmi_disable(unsigned int cpu) 11105a4a952SNicholas Piggin { 112941154bdSThomas Gleixner hardlockup_detector_perf_disable(); 11305a4a952SNicholas Piggin } 11405a4a952SNicholas Piggin 1156592ad2fSThomas Gleixner /** 1166592ad2fSThomas Gleixner * watchdog_nmi_reconfigure - Optional function to reconfigure NMI watchdogs 1176592ad2fSThomas Gleixner * @run: If false stop the watchdogs on all enabled CPUs 1186592ad2fSThomas Gleixner * If true start the watchdogs on all enabled CPUs 1196592ad2fSThomas Gleixner * 1206592ad2fSThomas Gleixner * The core call order is: 1216592ad2fSThomas Gleixner * watchdog_nmi_reconfigure(false); 1226592ad2fSThomas Gleixner * update_variables(); 1236592ad2fSThomas Gleixner * watchdog_nmi_reconfigure(true); 1246592ad2fSThomas Gleixner * 1256592ad2fSThomas Gleixner * The second call which starts the watchdogs again guarantees that the 1266592ad2fSThomas Gleixner * following variables are stable across the call. 1277feeb9cdSThomas Gleixner * - watchdog_enabled 128a10a842fSNicholas Piggin * - watchdog_thresh 129a10a842fSNicholas Piggin * - watchdog_cpumask 1306592ad2fSThomas Gleixner * 1316592ad2fSThomas Gleixner * After the call the variables can be changed again. 132a10a842fSNicholas Piggin */ 1336592ad2fSThomas Gleixner void __weak watchdog_nmi_reconfigure(bool run) { } 134a10a842fSNicholas Piggin 13505a4a952SNicholas Piggin #ifdef CONFIG_SOFTLOCKUP_DETECTOR 13605a4a952SNicholas Piggin 1372b9d7f23SThomas Gleixner /* Global variables, exported for sysctl */ 1382b9d7f23SThomas Gleixner unsigned int __read_mostly softlockup_panic = 1392b9d7f23SThomas Gleixner CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE; 1402eb2527fSThomas Gleixner 1410f34c400SChuansheng Liu static u64 __read_mostly sample_period; 14258687acbSDon Zickus 14358687acbSDon Zickus static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts); 14458687acbSDon Zickus static DEFINE_PER_CPU(struct task_struct *, softlockup_watchdog); 14558687acbSDon Zickus static DEFINE_PER_CPU(struct hrtimer, watchdog_hrtimer); 14658687acbSDon Zickus static DEFINE_PER_CPU(bool, softlockup_touch_sync); 14758687acbSDon Zickus static DEFINE_PER_CPU(bool, soft_watchdog_warn); 148bcd951cfSThomas Gleixner static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts); 149bcd951cfSThomas Gleixner static DEFINE_PER_CPU(unsigned long, soft_lockup_hrtimer_cnt); 150b1a8de1fSchai wen static DEFINE_PER_CPU(struct task_struct *, softlockup_task_ptr_saved); 15158687acbSDon Zickus static DEFINE_PER_CPU(unsigned long, hrtimer_interrupts_saved); 152ed235875SAaron Tomlin static unsigned long soft_lockup_nmi_warn; 15358687acbSDon Zickus 15458687acbSDon Zickus static int __init softlockup_panic_setup(char *str) 15558687acbSDon Zickus { 15658687acbSDon Zickus softlockup_panic = simple_strtoul(str, NULL, 0); 15758687acbSDon Zickus return 1; 15858687acbSDon Zickus } 15958687acbSDon Zickus __setup("softlockup_panic=", softlockup_panic_setup); 16058687acbSDon Zickus 16158687acbSDon Zickus static int __init nowatchdog_setup(char *str) 16258687acbSDon Zickus { 163195daf66SUlrich Obergfell watchdog_enabled = 0; 16458687acbSDon Zickus return 1; 16558687acbSDon Zickus } 16658687acbSDon Zickus __setup("nowatchdog", nowatchdog_setup); 16758687acbSDon Zickus 16858687acbSDon Zickus static int __init nosoftlockup_setup(char *str) 16958687acbSDon Zickus { 170195daf66SUlrich Obergfell watchdog_enabled &= ~SOFT_WATCHDOG_ENABLED; 17158687acbSDon Zickus return 1; 17258687acbSDon Zickus } 17358687acbSDon Zickus __setup("nosoftlockup", nosoftlockup_setup); 174195daf66SUlrich Obergfell 175ed235875SAaron Tomlin #ifdef CONFIG_SMP 176368a7e2cSThomas Gleixner int __read_mostly sysctl_softlockup_all_cpu_backtrace; 177368a7e2cSThomas Gleixner 178ed235875SAaron Tomlin static int __init softlockup_all_cpu_backtrace_setup(char *str) 179ed235875SAaron Tomlin { 180368a7e2cSThomas Gleixner sysctl_softlockup_all_cpu_backtrace = !!simple_strtol(str, NULL, 0); 181ed235875SAaron Tomlin return 1; 182ed235875SAaron Tomlin } 183ed235875SAaron Tomlin __setup("softlockup_all_cpu_backtrace=", softlockup_all_cpu_backtrace_setup); 18405a4a952SNicholas Piggin #endif 18558687acbSDon Zickus 186941154bdSThomas Gleixner static void __lockup_detector_cleanup(void); 187941154bdSThomas Gleixner 1884eec42f3SMandeep Singh Baines /* 1894eec42f3SMandeep Singh Baines * Hard-lockup warnings should be triggered after just a few seconds. Soft- 1904eec42f3SMandeep Singh Baines * lockups can have false positives under extreme conditions. So we generally 1914eec42f3SMandeep Singh Baines * want a higher threshold for soft lockups than for hard lockups. So we couple 1924eec42f3SMandeep Singh Baines * the thresholds with a factor: we make the soft threshold twice the amount of 1934eec42f3SMandeep Singh Baines * time the hard threshold is. 1944eec42f3SMandeep Singh Baines */ 1956e9101aeSIngo Molnar static int get_softlockup_thresh(void) 1964eec42f3SMandeep Singh Baines { 1974eec42f3SMandeep Singh Baines return watchdog_thresh * 2; 1984eec42f3SMandeep Singh Baines } 19958687acbSDon Zickus 20058687acbSDon Zickus /* 20158687acbSDon Zickus * Returns seconds, approximately. We don't need nanosecond 20258687acbSDon Zickus * resolution, and we don't need to waste time with a big divide when 20358687acbSDon Zickus * 2^30ns == 1.074s. 20458687acbSDon Zickus */ 205c06b4f19SNamhyung Kim static unsigned long get_timestamp(void) 20658687acbSDon Zickus { 207545a2bf7SCyril Bur return running_clock() >> 30LL; /* 2^30 ~= 10^9 */ 20858687acbSDon Zickus } 20958687acbSDon Zickus 2100f34c400SChuansheng Liu static void set_sample_period(void) 21158687acbSDon Zickus { 21258687acbSDon Zickus /* 213586692a5SMandeep Singh Baines * convert watchdog_thresh from seconds to ns 21486f5e6a7SFernando Luis Vázquez Cao * the divide by 5 is to give hrtimer several chances (two 21586f5e6a7SFernando Luis Vázquez Cao * or three with the current relation between the soft 21686f5e6a7SFernando Luis Vázquez Cao * and hard thresholds) to increment before the 21786f5e6a7SFernando Luis Vázquez Cao * hardlockup detector generates a warning 21858687acbSDon Zickus */ 2190f34c400SChuansheng Liu sample_period = get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5); 2207edaeb68SThomas Gleixner watchdog_update_hrtimer_threshold(sample_period); 22158687acbSDon Zickus } 22258687acbSDon Zickus 22358687acbSDon Zickus /* Commands for resetting the watchdog */ 22458687acbSDon Zickus static void __touch_watchdog(void) 22558687acbSDon Zickus { 226c06b4f19SNamhyung Kim __this_cpu_write(watchdog_touch_ts, get_timestamp()); 22758687acbSDon Zickus } 22858687acbSDon Zickus 22903e0d461STejun Heo /** 23003e0d461STejun Heo * touch_softlockup_watchdog_sched - touch watchdog on scheduler stalls 23103e0d461STejun Heo * 23203e0d461STejun Heo * Call when the scheduler may have stalled for legitimate reasons 23303e0d461STejun Heo * preventing the watchdog task from executing - e.g. the scheduler 23403e0d461STejun Heo * entering idle state. This should only be used for scheduler events. 23503e0d461STejun Heo * Use touch_softlockup_watchdog() for everything else. 23603e0d461STejun Heo */ 23703e0d461STejun Heo void touch_softlockup_watchdog_sched(void) 23858687acbSDon Zickus { 2397861144bSAndrew Morton /* 2407861144bSAndrew Morton * Preemption can be enabled. It doesn't matter which CPU's timestamp 2417861144bSAndrew Morton * gets zeroed here, so use the raw_ operation. 2427861144bSAndrew Morton */ 2437861144bSAndrew Morton raw_cpu_write(watchdog_touch_ts, 0); 24458687acbSDon Zickus } 24503e0d461STejun Heo 24603e0d461STejun Heo void touch_softlockup_watchdog(void) 24703e0d461STejun Heo { 24803e0d461STejun Heo touch_softlockup_watchdog_sched(); 24982607adcSTejun Heo wq_watchdog_touch(raw_smp_processor_id()); 25003e0d461STejun Heo } 2510167c781SIngo Molnar EXPORT_SYMBOL(touch_softlockup_watchdog); 25258687acbSDon Zickus 253332fbdbcSDon Zickus void touch_all_softlockup_watchdogs(void) 25458687acbSDon Zickus { 25558687acbSDon Zickus int cpu; 25658687acbSDon Zickus 25758687acbSDon Zickus /* 258d57108d4SThomas Gleixner * watchdog_mutex cannpt be taken here, as this might be called 259d57108d4SThomas Gleixner * from (soft)interrupt context, so the access to 260d57108d4SThomas Gleixner * watchdog_allowed_cpumask might race with a concurrent update. 261d57108d4SThomas Gleixner * 262d57108d4SThomas Gleixner * The watchdog time stamp can race against a concurrent real 263d57108d4SThomas Gleixner * update as well, the only side effect might be a cycle delay for 264d57108d4SThomas Gleixner * the softlockup check. 26558687acbSDon Zickus */ 266d57108d4SThomas Gleixner for_each_cpu(cpu, &watchdog_allowed_mask) 26758687acbSDon Zickus per_cpu(watchdog_touch_ts, cpu) = 0; 26882607adcSTejun Heo wq_watchdog_touch(-1); 26958687acbSDon Zickus } 27058687acbSDon Zickus 27158687acbSDon Zickus void touch_softlockup_watchdog_sync(void) 27258687acbSDon Zickus { 273f7f66b05SChristoph Lameter __this_cpu_write(softlockup_touch_sync, true); 274f7f66b05SChristoph Lameter __this_cpu_write(watchdog_touch_ts, 0); 27558687acbSDon Zickus } 27658687acbSDon Zickus 27726e09c6eSDon Zickus static int is_softlockup(unsigned long touch_ts) 27858687acbSDon Zickus { 279c06b4f19SNamhyung Kim unsigned long now = get_timestamp(); 28058687acbSDon Zickus 28139d2da21SUlrich Obergfell if ((watchdog_enabled & SOFT_WATCHDOG_ENABLED) && watchdog_thresh){ 282195daf66SUlrich Obergfell /* Warn about unreasonable delays. */ 2834eec42f3SMandeep Singh Baines if (time_after(now, touch_ts + get_softlockup_thresh())) 28458687acbSDon Zickus return now - touch_ts; 285195daf66SUlrich Obergfell } 28658687acbSDon Zickus return 0; 28758687acbSDon Zickus } 28858687acbSDon Zickus 28905a4a952SNicholas Piggin /* watchdog detector functions */ 29005a4a952SNicholas Piggin bool is_hardlockup(void) 29105a4a952SNicholas Piggin { 29205a4a952SNicholas Piggin unsigned long hrint = __this_cpu_read(hrtimer_interrupts); 29305a4a952SNicholas Piggin 29405a4a952SNicholas Piggin if (__this_cpu_read(hrtimer_interrupts_saved) == hrint) 29505a4a952SNicholas Piggin return true; 29605a4a952SNicholas Piggin 29705a4a952SNicholas Piggin __this_cpu_write(hrtimer_interrupts_saved, hrint); 29805a4a952SNicholas Piggin return false; 29905a4a952SNicholas Piggin } 30005a4a952SNicholas Piggin 30158687acbSDon Zickus static void watchdog_interrupt_count(void) 30258687acbSDon Zickus { 303909ea964SChristoph Lameter __this_cpu_inc(hrtimer_interrupts); 30458687acbSDon Zickus } 305bcd951cfSThomas Gleixner 30658687acbSDon Zickus /* watchdog kicker functions */ 30758687acbSDon Zickus static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) 30858687acbSDon Zickus { 309909ea964SChristoph Lameter unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts); 31058687acbSDon Zickus struct pt_regs *regs = get_irq_regs(); 31158687acbSDon Zickus int duration; 312ed235875SAaron Tomlin int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace; 31358687acbSDon Zickus 31401f0a027SThomas Gleixner if (!watchdog_enabled) 315b94f5118SDon Zickus return HRTIMER_NORESTART; 316b94f5118SDon Zickus 31758687acbSDon Zickus /* kick the hardlockup detector */ 31858687acbSDon Zickus watchdog_interrupt_count(); 31958687acbSDon Zickus 32058687acbSDon Zickus /* kick the softlockup detector */ 321909ea964SChristoph Lameter wake_up_process(__this_cpu_read(softlockup_watchdog)); 32258687acbSDon Zickus 32358687acbSDon Zickus /* .. and repeat */ 3240f34c400SChuansheng Liu hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period)); 32558687acbSDon Zickus 32658687acbSDon Zickus if (touch_ts == 0) { 327909ea964SChristoph Lameter if (unlikely(__this_cpu_read(softlockup_touch_sync))) { 32858687acbSDon Zickus /* 32958687acbSDon Zickus * If the time stamp was touched atomically 33058687acbSDon Zickus * make sure the scheduler tick is up to date. 33158687acbSDon Zickus */ 332909ea964SChristoph Lameter __this_cpu_write(softlockup_touch_sync, false); 33358687acbSDon Zickus sched_clock_tick(); 33458687acbSDon Zickus } 3355d1c0f4aSEric B Munson 3365d1c0f4aSEric B Munson /* Clear the guest paused flag on watchdog reset */ 3375d1c0f4aSEric B Munson kvm_check_and_clear_guest_paused(); 33858687acbSDon Zickus __touch_watchdog(); 33958687acbSDon Zickus return HRTIMER_RESTART; 34058687acbSDon Zickus } 34158687acbSDon Zickus 34258687acbSDon Zickus /* check for a softlockup 34358687acbSDon Zickus * This is done by making sure a high priority task is 34458687acbSDon Zickus * being scheduled. The task touches the watchdog to 34558687acbSDon Zickus * indicate it is getting cpu time. If it hasn't then 34658687acbSDon Zickus * this is a good indication some task is hogging the cpu 34758687acbSDon Zickus */ 34826e09c6eSDon Zickus duration = is_softlockup(touch_ts); 34958687acbSDon Zickus if (unlikely(duration)) { 3505d1c0f4aSEric B Munson /* 3515d1c0f4aSEric B Munson * If a virtual machine is stopped by the host it can look to 3525d1c0f4aSEric B Munson * the watchdog like a soft lockup, check to see if the host 3535d1c0f4aSEric B Munson * stopped the vm before we issue the warning 3545d1c0f4aSEric B Munson */ 3555d1c0f4aSEric B Munson if (kvm_check_and_clear_guest_paused()) 3565d1c0f4aSEric B Munson return HRTIMER_RESTART; 3575d1c0f4aSEric B Munson 35858687acbSDon Zickus /* only warn once */ 359b1a8de1fSchai wen if (__this_cpu_read(soft_watchdog_warn) == true) { 360b1a8de1fSchai wen /* 361b1a8de1fSchai wen * When multiple processes are causing softlockups the 362b1a8de1fSchai wen * softlockup detector only warns on the first one 363b1a8de1fSchai wen * because the code relies on a full quiet cycle to 364b1a8de1fSchai wen * re-arm. The second process prevents the quiet cycle 365b1a8de1fSchai wen * and never gets reported. Use task pointers to detect 366b1a8de1fSchai wen * this. 367b1a8de1fSchai wen */ 368b1a8de1fSchai wen if (__this_cpu_read(softlockup_task_ptr_saved) != 369b1a8de1fSchai wen current) { 370b1a8de1fSchai wen __this_cpu_write(soft_watchdog_warn, false); 371b1a8de1fSchai wen __touch_watchdog(); 372b1a8de1fSchai wen } 37358687acbSDon Zickus return HRTIMER_RESTART; 374b1a8de1fSchai wen } 37558687acbSDon Zickus 376ed235875SAaron Tomlin if (softlockup_all_cpu_backtrace) { 377ed235875SAaron Tomlin /* Prevent multiple soft-lockup reports if one cpu is already 378ed235875SAaron Tomlin * engaged in dumping cpu back traces 379ed235875SAaron Tomlin */ 380ed235875SAaron Tomlin if (test_and_set_bit(0, &soft_lockup_nmi_warn)) { 381ed235875SAaron Tomlin /* Someone else will report us. Let's give up */ 382ed235875SAaron Tomlin __this_cpu_write(soft_watchdog_warn, true); 383ed235875SAaron Tomlin return HRTIMER_RESTART; 384ed235875SAaron Tomlin } 385ed235875SAaron Tomlin } 386ed235875SAaron Tomlin 387656c3b79SFabian Frederick pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n", 38826e09c6eSDon Zickus smp_processor_id(), duration, 38958687acbSDon Zickus current->comm, task_pid_nr(current)); 390b1a8de1fSchai wen __this_cpu_write(softlockup_task_ptr_saved, current); 39158687acbSDon Zickus print_modules(); 39258687acbSDon Zickus print_irqtrace_events(current); 39358687acbSDon Zickus if (regs) 39458687acbSDon Zickus show_regs(regs); 39558687acbSDon Zickus else 39658687acbSDon Zickus dump_stack(); 39758687acbSDon Zickus 398ed235875SAaron Tomlin if (softlockup_all_cpu_backtrace) { 399ed235875SAaron Tomlin /* Avoid generating two back traces for current 400ed235875SAaron Tomlin * given that one is already made above 401ed235875SAaron Tomlin */ 402ed235875SAaron Tomlin trigger_allbutself_cpu_backtrace(); 403ed235875SAaron Tomlin 404ed235875SAaron Tomlin clear_bit(0, &soft_lockup_nmi_warn); 405ed235875SAaron Tomlin /* Barrier to sync with other cpus */ 406ed235875SAaron Tomlin smp_mb__after_atomic(); 407ed235875SAaron Tomlin } 408ed235875SAaron Tomlin 40969361eefSJosh Hunt add_taint(TAINT_SOFTLOCKUP, LOCKDEP_STILL_OK); 41058687acbSDon Zickus if (softlockup_panic) 41158687acbSDon Zickus panic("softlockup: hung tasks"); 412909ea964SChristoph Lameter __this_cpu_write(soft_watchdog_warn, true); 41358687acbSDon Zickus } else 414909ea964SChristoph Lameter __this_cpu_write(soft_watchdog_warn, false); 41558687acbSDon Zickus 41658687acbSDon Zickus return HRTIMER_RESTART; 41758687acbSDon Zickus } 41858687acbSDon Zickus 419bcd951cfSThomas Gleixner static void watchdog_set_prio(unsigned int policy, unsigned int prio) 42058687acbSDon Zickus { 421bcd951cfSThomas Gleixner struct sched_param param = { .sched_priority = prio }; 422bcd951cfSThomas Gleixner 423bcd951cfSThomas Gleixner sched_setscheduler(current, policy, ¶m); 424bcd951cfSThomas Gleixner } 425bcd951cfSThomas Gleixner 426bcd951cfSThomas Gleixner static void watchdog_enable(unsigned int cpu) 427bcd951cfSThomas Gleixner { 42801f0a027SThomas Gleixner struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer); 42958687acbSDon Zickus 43001f0a027SThomas Gleixner /* 43101f0a027SThomas Gleixner * Start the timer first to prevent the NMI watchdog triggering 43201f0a027SThomas Gleixner * before the timer has a chance to fire. 43301f0a027SThomas Gleixner */ 4343935e895SBjørn Mork hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 4353935e895SBjørn Mork hrtimer->function = watchdog_timer_fn; 4360f34c400SChuansheng Liu hrtimer_start(hrtimer, ns_to_ktime(sample_period), 43758687acbSDon Zickus HRTIMER_MODE_REL_PINNED); 43858687acbSDon Zickus 43901f0a027SThomas Gleixner /* Initialize timestamp */ 44058687acbSDon Zickus __touch_watchdog(); 44101f0a027SThomas Gleixner /* Enable the perf event */ 44201f0a027SThomas Gleixner watchdog_nmi_enable(cpu); 44301f0a027SThomas Gleixner 44401f0a027SThomas Gleixner watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1); 44558687acbSDon Zickus } 446bcd951cfSThomas Gleixner 447bcd951cfSThomas Gleixner static void watchdog_disable(unsigned int cpu) 448bcd951cfSThomas Gleixner { 44901f0a027SThomas Gleixner struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer); 450bcd951cfSThomas Gleixner 451bcd951cfSThomas Gleixner watchdog_set_prio(SCHED_NORMAL, 0); 45201f0a027SThomas Gleixner /* 45301f0a027SThomas Gleixner * Disable the perf event first. That prevents that a large delay 45401f0a027SThomas Gleixner * between disabling the timer and disabling the perf event causes 45501f0a027SThomas Gleixner * the perf NMI to detect a false positive. 45601f0a027SThomas Gleixner */ 457bcd951cfSThomas Gleixner watchdog_nmi_disable(cpu); 45801f0a027SThomas Gleixner hrtimer_cancel(hrtimer); 459bcd951cfSThomas Gleixner } 460bcd951cfSThomas Gleixner 461b8900bc0SFrederic Weisbecker static void watchdog_cleanup(unsigned int cpu, bool online) 462b8900bc0SFrederic Weisbecker { 463b8900bc0SFrederic Weisbecker watchdog_disable(cpu); 464b8900bc0SFrederic Weisbecker } 465b8900bc0SFrederic Weisbecker 466bcd951cfSThomas Gleixner static int watchdog_should_run(unsigned int cpu) 467bcd951cfSThomas Gleixner { 468bcd951cfSThomas Gleixner return __this_cpu_read(hrtimer_interrupts) != 469bcd951cfSThomas Gleixner __this_cpu_read(soft_lockup_hrtimer_cnt); 470bcd951cfSThomas Gleixner } 471bcd951cfSThomas Gleixner 472b60f796cSAndrew Morton /* 473bcd951cfSThomas Gleixner * The watchdog thread function - touches the timestamp. 474bcd951cfSThomas Gleixner * 4750f34c400SChuansheng Liu * It only runs once every sample_period seconds (4 seconds by 476bcd951cfSThomas Gleixner * default) to reset the softlockup timestamp. If this gets delayed 477bcd951cfSThomas Gleixner * for more than 2*watchdog_thresh seconds then the debug-printout 478bcd951cfSThomas Gleixner * triggers in watchdog_timer_fn(). 479b60f796cSAndrew Morton */ 480bcd951cfSThomas Gleixner static void watchdog(unsigned int cpu) 481bcd951cfSThomas Gleixner { 482bcd951cfSThomas Gleixner __this_cpu_write(soft_lockup_hrtimer_cnt, 483bcd951cfSThomas Gleixner __this_cpu_read(hrtimer_interrupts)); 484bcd951cfSThomas Gleixner __touch_watchdog(); 48558687acbSDon Zickus } 48658687acbSDon Zickus 487b8900bc0SFrederic Weisbecker static struct smp_hotplug_thread watchdog_threads = { 488b8900bc0SFrederic Weisbecker .store = &softlockup_watchdog, 489b8900bc0SFrederic Weisbecker .thread_should_run = watchdog_should_run, 490b8900bc0SFrederic Weisbecker .thread_fn = watchdog, 491b8900bc0SFrederic Weisbecker .thread_comm = "watchdog/%u", 492b8900bc0SFrederic Weisbecker .setup = watchdog_enable, 493b8900bc0SFrederic Weisbecker .cleanup = watchdog_cleanup, 494b8900bc0SFrederic Weisbecker .park = watchdog_disable, 495b8900bc0SFrederic Weisbecker .unpark = watchdog_enable, 496b8900bc0SFrederic Weisbecker }; 497b8900bc0SFrederic Weisbecker 4982eb2527fSThomas Gleixner static void softlockup_update_smpboot_threads(void) 4992eb2527fSThomas Gleixner { 5002eb2527fSThomas Gleixner lockdep_assert_held(&watchdog_mutex); 5012eb2527fSThomas Gleixner 5022eb2527fSThomas Gleixner if (!softlockup_threads_initialized) 5032eb2527fSThomas Gleixner return; 5042eb2527fSThomas Gleixner 5052eb2527fSThomas Gleixner smpboot_update_cpumask_percpu_thread(&watchdog_threads, 5062eb2527fSThomas Gleixner &watchdog_allowed_mask); 5072eb2527fSThomas Gleixner __lockup_detector_cleanup(); 5082eb2527fSThomas Gleixner } 5092eb2527fSThomas Gleixner 5102eb2527fSThomas Gleixner /* Temporarily park all watchdog threads */ 5112eb2527fSThomas Gleixner static void softlockup_park_all_threads(void) 5122eb2527fSThomas Gleixner { 5132eb2527fSThomas Gleixner cpumask_clear(&watchdog_allowed_mask); 5142eb2527fSThomas Gleixner softlockup_update_smpboot_threads(); 5152eb2527fSThomas Gleixner } 5162eb2527fSThomas Gleixner 517e8b62b2dSThomas Gleixner /* Unpark enabled threads */ 518e8b62b2dSThomas Gleixner static void softlockup_unpark_threads(void) 5192eb2527fSThomas Gleixner { 5202eb2527fSThomas Gleixner cpumask_copy(&watchdog_allowed_mask, &watchdog_cpumask); 5212eb2527fSThomas Gleixner softlockup_update_smpboot_threads(); 5222eb2527fSThomas Gleixner } 5232eb2527fSThomas Gleixner 5242eb2527fSThomas Gleixner static void softlockup_reconfigure_threads(bool enabled) 5252eb2527fSThomas Gleixner { 5266592ad2fSThomas Gleixner watchdog_nmi_reconfigure(false); 5272eb2527fSThomas Gleixner softlockup_park_all_threads(); 5282eb2527fSThomas Gleixner set_sample_period(); 5292eb2527fSThomas Gleixner if (enabled) 530e8b62b2dSThomas Gleixner softlockup_unpark_threads(); 5316592ad2fSThomas Gleixner watchdog_nmi_reconfigure(true); 5322eb2527fSThomas Gleixner } 5332eb2527fSThomas Gleixner 5342eb2527fSThomas Gleixner /* 5352eb2527fSThomas Gleixner * Create the watchdog thread infrastructure. 5362eb2527fSThomas Gleixner * 5372eb2527fSThomas Gleixner * The threads are not unparked as watchdog_allowed_mask is empty. When 5382eb2527fSThomas Gleixner * the threads are sucessfully initialized, take the proper locks and 5392eb2527fSThomas Gleixner * unpark the threads in the watchdog_cpumask if the watchdog is enabled. 5402eb2527fSThomas Gleixner */ 5412eb2527fSThomas Gleixner static __init void softlockup_init_threads(void) 5422eb2527fSThomas Gleixner { 5432eb2527fSThomas Gleixner int ret; 5442eb2527fSThomas Gleixner 5452eb2527fSThomas Gleixner /* 5462eb2527fSThomas Gleixner * If sysctl is off and watchdog got disabled on the command line, 5472eb2527fSThomas Gleixner * nothing to do here. 5482eb2527fSThomas Gleixner */ 5492eb2527fSThomas Gleixner if (!IS_ENABLED(CONFIG_SYSCTL) && 5502eb2527fSThomas Gleixner !(watchdog_enabled && watchdog_thresh)) 5512eb2527fSThomas Gleixner return; 5522eb2527fSThomas Gleixner 5532eb2527fSThomas Gleixner ret = smpboot_register_percpu_thread_cpumask(&watchdog_threads, 5542eb2527fSThomas Gleixner &watchdog_allowed_mask); 5552eb2527fSThomas Gleixner if (ret) { 5562eb2527fSThomas Gleixner pr_err("Failed to initialize soft lockup detector threads\n"); 5572eb2527fSThomas Gleixner return; 5582eb2527fSThomas Gleixner } 5592eb2527fSThomas Gleixner 5602eb2527fSThomas Gleixner mutex_lock(&watchdog_mutex); 5612eb2527fSThomas Gleixner softlockup_threads_initialized = true; 5622eb2527fSThomas Gleixner softlockup_reconfigure_threads(watchdog_enabled && watchdog_thresh); 5632eb2527fSThomas Gleixner mutex_unlock(&watchdog_mutex); 5642eb2527fSThomas Gleixner } 5652eb2527fSThomas Gleixner 5662b9d7f23SThomas Gleixner #else /* CONFIG_SOFTLOCKUP_DETECTOR */ 5672b9d7f23SThomas Gleixner static inline int watchdog_park_threads(void) { return 0; } 5682b9d7f23SThomas Gleixner static inline void watchdog_unpark_threads(void) { } 5692b9d7f23SThomas Gleixner static inline int watchdog_enable_all_cpus(void) { return 0; } 5702b9d7f23SThomas Gleixner static inline void watchdog_disable_all_cpus(void) { } 5712eb2527fSThomas Gleixner static inline void softlockup_init_threads(void) { } 5726592ad2fSThomas Gleixner static void softlockup_reconfigure_threads(bool enabled) 5736592ad2fSThomas Gleixner { 5746592ad2fSThomas Gleixner watchdog_nmi_reconfigure(false); 5756592ad2fSThomas Gleixner watchdog_nmi_reconfigure(true); 5766592ad2fSThomas Gleixner } 5772b9d7f23SThomas Gleixner #endif /* !CONFIG_SOFTLOCKUP_DETECTOR */ 57805a4a952SNicholas Piggin 579941154bdSThomas Gleixner static void __lockup_detector_cleanup(void) 580941154bdSThomas Gleixner { 581941154bdSThomas Gleixner lockdep_assert_held(&watchdog_mutex); 582941154bdSThomas Gleixner hardlockup_detector_perf_cleanup(); 583941154bdSThomas Gleixner } 584941154bdSThomas Gleixner 585941154bdSThomas Gleixner /** 586941154bdSThomas Gleixner * lockup_detector_cleanup - Cleanup after cpu hotplug or sysctl changes 587941154bdSThomas Gleixner * 588941154bdSThomas Gleixner * Caller must not hold the cpu hotplug rwsem. 589941154bdSThomas Gleixner */ 590941154bdSThomas Gleixner void lockup_detector_cleanup(void) 591941154bdSThomas Gleixner { 592941154bdSThomas Gleixner mutex_lock(&watchdog_mutex); 593941154bdSThomas Gleixner __lockup_detector_cleanup(); 594941154bdSThomas Gleixner mutex_unlock(&watchdog_mutex); 595941154bdSThomas Gleixner } 596941154bdSThomas Gleixner 5976554fd8cSThomas Gleixner /** 5986554fd8cSThomas Gleixner * lockup_detector_soft_poweroff - Interface to stop lockup detector(s) 5996554fd8cSThomas Gleixner * 6006554fd8cSThomas Gleixner * Special interface for parisc. It prevents lockup detector warnings from 6016554fd8cSThomas Gleixner * the default pm_poweroff() function which busy loops forever. 6026554fd8cSThomas Gleixner */ 6036554fd8cSThomas Gleixner void lockup_detector_soft_poweroff(void) 6046554fd8cSThomas Gleixner { 6056554fd8cSThomas Gleixner watchdog_enabled = 0; 6066554fd8cSThomas Gleixner } 6076554fd8cSThomas Gleixner 60858cf690aSUlrich Obergfell #ifdef CONFIG_SYSCTL 60958cf690aSUlrich Obergfell 610e8b62b2dSThomas Gleixner /* Propagate any changes to the watchdog threads */ 611d57108d4SThomas Gleixner static void proc_watchdog_update(void) 61258687acbSDon Zickus { 613e8b62b2dSThomas Gleixner /* Remove impossible cpus to keep sysctl output clean. */ 614e8b62b2dSThomas Gleixner cpumask_and(&watchdog_cpumask, &watchdog_cpumask, cpu_possible_mask); 615d57108d4SThomas Gleixner softlockup_reconfigure_threads(watchdog_enabled && watchdog_thresh); 616a0c9cbb9SUlrich Obergfell } 617a0c9cbb9SUlrich Obergfell 618a0c9cbb9SUlrich Obergfell /* 619ef246a21SUlrich Obergfell * common function for watchdog, nmi_watchdog and soft_watchdog parameter 620ef246a21SUlrich Obergfell * 6217feeb9cdSThomas Gleixner * caller | table->data points to | 'which' 6227feeb9cdSThomas Gleixner * -------------------|----------------------------|-------------------------- 6237feeb9cdSThomas Gleixner * proc_watchdog | watchdog_user_enabled | NMI_WATCHDOG_ENABLED | 6247feeb9cdSThomas Gleixner * | | SOFT_WATCHDOG_ENABLED 6257feeb9cdSThomas Gleixner * -------------------|----------------------------|-------------------------- 6267feeb9cdSThomas Gleixner * proc_nmi_watchdog | nmi_watchdog_user_enabled | NMI_WATCHDOG_ENABLED 6277feeb9cdSThomas Gleixner * -------------------|----------------------------|-------------------------- 6287feeb9cdSThomas Gleixner * proc_soft_watchdog | soft_watchdog_user_enabled | SOFT_WATCHDOG_ENABLED 629ef246a21SUlrich Obergfell */ 630ef246a21SUlrich Obergfell static int proc_watchdog_common(int which, struct ctl_table *table, int write, 631ef246a21SUlrich Obergfell void __user *buffer, size_t *lenp, loff_t *ppos) 632ef246a21SUlrich Obergfell { 633ef246a21SUlrich Obergfell int err, old, new; 634ef246a21SUlrich Obergfell int *watchdog_param = (int *)table->data; 635bcd951cfSThomas Gleixner 636b7a34981SThomas Gleixner cpu_hotplug_disable(); 637946d1977SThomas Gleixner mutex_lock(&watchdog_mutex); 638ef246a21SUlrich Obergfell 639ef246a21SUlrich Obergfell /* 640ef246a21SUlrich Obergfell * If the parameter is being read return the state of the corresponding 641ef246a21SUlrich Obergfell * bit(s) in 'watchdog_enabled', else update 'watchdog_enabled' and the 642ef246a21SUlrich Obergfell * run state of the lockup detectors. 643ef246a21SUlrich Obergfell */ 644ef246a21SUlrich Obergfell if (!write) { 645ef246a21SUlrich Obergfell *watchdog_param = (watchdog_enabled & which) != 0; 646b8900bc0SFrederic Weisbecker err = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 647ef246a21SUlrich Obergfell } else { 648ef246a21SUlrich Obergfell err = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 649ef246a21SUlrich Obergfell if (err) 650ef246a21SUlrich Obergfell goto out; 651ef246a21SUlrich Obergfell 652ef246a21SUlrich Obergfell /* 653ef246a21SUlrich Obergfell * There is a race window between fetching the current value 654ef246a21SUlrich Obergfell * from 'watchdog_enabled' and storing the new value. During 655ef246a21SUlrich Obergfell * this race window, watchdog_nmi_enable() can sneak in and 656ef246a21SUlrich Obergfell * clear the NMI_WATCHDOG_ENABLED bit in 'watchdog_enabled'. 657ef246a21SUlrich Obergfell * The 'cmpxchg' detects this race and the loop retries. 658ef246a21SUlrich Obergfell */ 659ef246a21SUlrich Obergfell do { 660ef246a21SUlrich Obergfell old = watchdog_enabled; 661ef246a21SUlrich Obergfell /* 662ef246a21SUlrich Obergfell * If the parameter value is not zero set the 663ef246a21SUlrich Obergfell * corresponding bit(s), else clear it(them). 664ef246a21SUlrich Obergfell */ 665ef246a21SUlrich Obergfell if (*watchdog_param) 666ef246a21SUlrich Obergfell new = old | which; 667ef246a21SUlrich Obergfell else 668ef246a21SUlrich Obergfell new = old & ~which; 669ef246a21SUlrich Obergfell } while (cmpxchg(&watchdog_enabled, old, new) != old); 670ef246a21SUlrich Obergfell 671d57108d4SThomas Gleixner if (old != new) 672d57108d4SThomas Gleixner proc_watchdog_update(); 673ef246a21SUlrich Obergfell } 674ef246a21SUlrich Obergfell out: 675946d1977SThomas Gleixner mutex_unlock(&watchdog_mutex); 676b7a34981SThomas Gleixner cpu_hotplug_enable(); 677ef246a21SUlrich Obergfell return err; 678ef246a21SUlrich Obergfell } 679ef246a21SUlrich Obergfell 680ef246a21SUlrich Obergfell /* 68183a80a39SUlrich Obergfell * /proc/sys/kernel/watchdog 68283a80a39SUlrich Obergfell */ 68383a80a39SUlrich Obergfell int proc_watchdog(struct ctl_table *table, int write, 68483a80a39SUlrich Obergfell void __user *buffer, size_t *lenp, loff_t *ppos) 68583a80a39SUlrich Obergfell { 68683a80a39SUlrich Obergfell return proc_watchdog_common(NMI_WATCHDOG_ENABLED|SOFT_WATCHDOG_ENABLED, 68783a80a39SUlrich Obergfell table, write, buffer, lenp, ppos); 68883a80a39SUlrich Obergfell } 68983a80a39SUlrich Obergfell 69083a80a39SUlrich Obergfell /* 69183a80a39SUlrich Obergfell * /proc/sys/kernel/nmi_watchdog 69283a80a39SUlrich Obergfell */ 69383a80a39SUlrich Obergfell int proc_nmi_watchdog(struct ctl_table *table, int write, 69483a80a39SUlrich Obergfell void __user *buffer, size_t *lenp, loff_t *ppos) 69583a80a39SUlrich Obergfell { 69683a80a39SUlrich Obergfell return proc_watchdog_common(NMI_WATCHDOG_ENABLED, 69783a80a39SUlrich Obergfell table, write, buffer, lenp, ppos); 69883a80a39SUlrich Obergfell } 69983a80a39SUlrich Obergfell 70083a80a39SUlrich Obergfell /* 70183a80a39SUlrich Obergfell * /proc/sys/kernel/soft_watchdog 70283a80a39SUlrich Obergfell */ 70383a80a39SUlrich Obergfell int proc_soft_watchdog(struct ctl_table *table, int write, 70483a80a39SUlrich Obergfell void __user *buffer, size_t *lenp, loff_t *ppos) 70583a80a39SUlrich Obergfell { 70683a80a39SUlrich Obergfell return proc_watchdog_common(SOFT_WATCHDOG_ENABLED, 70783a80a39SUlrich Obergfell table, write, buffer, lenp, ppos); 70883a80a39SUlrich Obergfell } 70983a80a39SUlrich Obergfell 71083a80a39SUlrich Obergfell /* 71183a80a39SUlrich Obergfell * /proc/sys/kernel/watchdog_thresh 71283a80a39SUlrich Obergfell */ 71383a80a39SUlrich Obergfell int proc_watchdog_thresh(struct ctl_table *table, int write, 71483a80a39SUlrich Obergfell void __user *buffer, size_t *lenp, loff_t *ppos) 71583a80a39SUlrich Obergfell { 716d57108d4SThomas Gleixner int err, old; 71783a80a39SUlrich Obergfell 718b7a34981SThomas Gleixner cpu_hotplug_disable(); 719946d1977SThomas Gleixner mutex_lock(&watchdog_mutex); 72083a80a39SUlrich Obergfell 721d57108d4SThomas Gleixner old = READ_ONCE(watchdog_thresh); 72283a80a39SUlrich Obergfell err = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 72383a80a39SUlrich Obergfell 724d57108d4SThomas Gleixner if (!err && write && old != READ_ONCE(watchdog_thresh)) 725d57108d4SThomas Gleixner proc_watchdog_update(); 726e04ab2bcSMandeep Singh Baines 727946d1977SThomas Gleixner mutex_unlock(&watchdog_mutex); 728b7a34981SThomas Gleixner cpu_hotplug_enable(); 729b8900bc0SFrederic Weisbecker return err; 73058687acbSDon Zickus } 731fe4ba3c3SChris Metcalf 732fe4ba3c3SChris Metcalf /* 733fe4ba3c3SChris Metcalf * The cpumask is the mask of possible cpus that the watchdog can run 734fe4ba3c3SChris Metcalf * on, not the mask of cpus it is actually running on. This allows the 735fe4ba3c3SChris Metcalf * user to specify a mask that will include cpus that have not yet 736fe4ba3c3SChris Metcalf * been brought online, if desired. 737fe4ba3c3SChris Metcalf */ 738fe4ba3c3SChris Metcalf int proc_watchdog_cpumask(struct ctl_table *table, int write, 739fe4ba3c3SChris Metcalf void __user *buffer, size_t *lenp, loff_t *ppos) 740fe4ba3c3SChris Metcalf { 741fe4ba3c3SChris Metcalf int err; 742fe4ba3c3SChris Metcalf 743b7a34981SThomas Gleixner cpu_hotplug_disable(); 744946d1977SThomas Gleixner mutex_lock(&watchdog_mutex); 7458c073d27SUlrich Obergfell 746fe4ba3c3SChris Metcalf err = proc_do_large_bitmap(table, write, buffer, lenp, ppos); 74705ba3de7SThomas Gleixner if (!err && write) 748e8b62b2dSThomas Gleixner proc_watchdog_update(); 7495490125dSThomas Gleixner 750946d1977SThomas Gleixner mutex_unlock(&watchdog_mutex); 751b7a34981SThomas Gleixner cpu_hotplug_enable(); 752fe4ba3c3SChris Metcalf return err; 753fe4ba3c3SChris Metcalf } 75458687acbSDon Zickus #endif /* CONFIG_SYSCTL */ 75558687acbSDon Zickus 756004417a6SPeter Zijlstra void __init lockup_detector_init(void) 75758687acbSDon Zickus { 758fe4ba3c3SChris Metcalf #ifdef CONFIG_NO_HZ_FULL 759fe4ba3c3SChris Metcalf if (tick_nohz_full_enabled()) { 760fe4ba3c3SChris Metcalf pr_info("Disabling watchdog on nohz_full cores by default\n"); 761314b08ffSFrederic Weisbecker cpumask_copy(&watchdog_cpumask, housekeeping_mask); 762fe4ba3c3SChris Metcalf } else 763fe4ba3c3SChris Metcalf cpumask_copy(&watchdog_cpumask, cpu_possible_mask); 764fe4ba3c3SChris Metcalf #else 765fe4ba3c3SChris Metcalf cpumask_copy(&watchdog_cpumask, cpu_possible_mask); 766fe4ba3c3SChris Metcalf #endif 767fe4ba3c3SChris Metcalf 768d57108d4SThomas Gleixner softlockup_init_threads(); 76958687acbSDon Zickus } 770