Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */ 2 : : /* 3 : : * linux/include/linux/nmi.h 4 : : */ 5 : : #ifndef LINUX_NMI_H 6 : : #define LINUX_NMI_H 7 : : 8 : : #include <linux/sched.h> 9 : : #include <asm/irq.h> 10 : : #if defined(CONFIG_HAVE_NMI_WATCHDOG) 11 : : #include <asm/nmi.h> 12 : : #endif 13 : : 14 : : #ifdef CONFIG_LOCKUP_DETECTOR 15 : : void lockup_detector_init(void); 16 : : void lockup_detector_soft_poweroff(void); 17 : : void lockup_detector_cleanup(void); 18 : : bool is_hardlockup(void); 19 : : 20 : : extern int watchdog_user_enabled; 21 : : extern int nmi_watchdog_user_enabled; 22 : : extern int soft_watchdog_user_enabled; 23 : : extern int watchdog_thresh; 24 : : extern unsigned long watchdog_enabled; 25 : : 26 : : extern struct cpumask watchdog_cpumask; 27 : : extern unsigned long *watchdog_cpumask_bits; 28 : : #ifdef CONFIG_SMP 29 : : extern int sysctl_softlockup_all_cpu_backtrace; 30 : : extern int sysctl_hardlockup_all_cpu_backtrace; 31 : : #else 32 : : #define sysctl_softlockup_all_cpu_backtrace 0 33 : : #define sysctl_hardlockup_all_cpu_backtrace 0 34 : : #endif /* !CONFIG_SMP */ 35 : : 36 : : #else /* CONFIG_LOCKUP_DETECTOR */ 37 : : static inline void lockup_detector_init(void) { } 38 : : static inline void lockup_detector_soft_poweroff(void) { } 39 : : static inline void lockup_detector_cleanup(void) { } 40 : : #endif /* !CONFIG_LOCKUP_DETECTOR */ 41 : : 42 : : #ifdef CONFIG_SOFTLOCKUP_DETECTOR 43 : : extern void touch_softlockup_watchdog_sched(void); 44 : : extern void touch_softlockup_watchdog(void); 45 : : extern void touch_softlockup_watchdog_sync(void); 46 : : extern void touch_all_softlockup_watchdogs(void); 47 : : extern unsigned int softlockup_panic; 48 : : 49 : : extern int lockup_detector_online_cpu(unsigned int cpu); 50 : : extern int lockup_detector_offline_cpu(unsigned int cpu); 51 : : #else /* CONFIG_SOFTLOCKUP_DETECTOR */ 52 : : static inline void touch_softlockup_watchdog_sched(void) { } 53 : : static inline void touch_softlockup_watchdog(void) { } 54 : : static inline void touch_softlockup_watchdog_sync(void) { } 55 : : static inline void touch_all_softlockup_watchdogs(void) { } 56 : : 57 : : #define lockup_detector_online_cpu NULL 58 : : #define lockup_detector_offline_cpu NULL 59 : : #endif /* CONFIG_SOFTLOCKUP_DETECTOR */ 60 : : 61 : : #ifdef CONFIG_DETECT_HUNG_TASK 62 : : void reset_hung_task_detector(void); 63 : : #else 64 : : static inline void reset_hung_task_detector(void) { } 65 : : #endif 66 : : 67 : : /* 68 : : * The run state of the lockup detectors is controlled by the content of the 69 : : * 'watchdog_enabled' variable. Each lockup detector has its dedicated bit - 70 : : * bit 0 for the hard lockup detector and bit 1 for the soft lockup detector. 71 : : * 72 : : * 'watchdog_user_enabled', 'nmi_watchdog_user_enabled' and 73 : : * 'soft_watchdog_user_enabled' are variables that are only used as an 74 : : * 'interface' between the parameters in /proc/sys/kernel and the internal 75 : : * state bits in 'watchdog_enabled'. The 'watchdog_thresh' variable is 76 : : * handled differently because its value is not boolean, and the lockup 77 : : * detectors are 'suspended' while 'watchdog_thresh' is equal zero. 78 : : */ 79 : : #define NMI_WATCHDOG_ENABLED_BIT 0 80 : : #define SOFT_WATCHDOG_ENABLED_BIT 1 81 : : #define NMI_WATCHDOG_ENABLED (1 << NMI_WATCHDOG_ENABLED_BIT) 82 : : #define SOFT_WATCHDOG_ENABLED (1 << SOFT_WATCHDOG_ENABLED_BIT) 83 : : 84 : : #if defined(CONFIG_HARDLOCKUP_DETECTOR) 85 : : extern void hardlockup_detector_disable(void); 86 : : extern unsigned int hardlockup_panic; 87 : : #else 88 : : static inline void hardlockup_detector_disable(void) {} 89 : : #endif 90 : : 91 : : #if defined(CONFIG_HAVE_NMI_WATCHDOG) || defined(CONFIG_HARDLOCKUP_DETECTOR) 92 : : # define NMI_WATCHDOG_SYSCTL_PERM 0644 93 : : #else 94 : : # define NMI_WATCHDOG_SYSCTL_PERM 0444 95 : : #endif 96 : : 97 : : #if defined(CONFIG_HARDLOCKUP_DETECTOR_PERF) 98 : : extern void arch_touch_nmi_watchdog(void); 99 : : extern void hardlockup_detector_perf_stop(void); 100 : : extern void hardlockup_detector_perf_restart(void); 101 : : extern void hardlockup_detector_perf_disable(void); 102 : : extern void hardlockup_detector_perf_enable(void); 103 : : extern void hardlockup_detector_perf_cleanup(void); 104 : : extern int hardlockup_detector_perf_init(void); 105 : : #else 106 : : static inline void hardlockup_detector_perf_stop(void) { } 107 : : static inline void hardlockup_detector_perf_restart(void) { } 108 : : static inline void hardlockup_detector_perf_disable(void) { } 109 : : static inline void hardlockup_detector_perf_enable(void) { } 110 : : static inline void hardlockup_detector_perf_cleanup(void) { } 111 : : # if !defined(CONFIG_HAVE_NMI_WATCHDOG) 112 : : static inline int hardlockup_detector_perf_init(void) { return -ENODEV; } 113 : : static inline void arch_touch_nmi_watchdog(void) {} 114 : : # else 115 : : static inline int hardlockup_detector_perf_init(void) { return 0; } 116 : : # endif 117 : : #endif 118 : : 119 : : void watchdog_nmi_stop(void); 120 : : void watchdog_nmi_start(void); 121 : : int watchdog_nmi_probe(void); 122 : : int watchdog_nmi_enable(unsigned int cpu); 123 : : void watchdog_nmi_disable(unsigned int cpu); 124 : : 125 : : /** 126 : : * touch_nmi_watchdog - restart NMI watchdog timeout. 127 : : * 128 : : * If the architecture supports the NMI watchdog, touch_nmi_watchdog() 129 : : * may be used to reset the timeout - for code which intentionally 130 : : * disables interrupts for a long time. This call is stateless. 131 : : */ 132 : : static inline void touch_nmi_watchdog(void) 133 : : { 134 : : arch_touch_nmi_watchdog(); 135 : : touch_softlockup_watchdog(); 136 : : } 137 : : 138 : : /* 139 : : * Create trigger_all_cpu_backtrace() out of the arch-provided 140 : : * base function. Return whether such support was available, 141 : : * to allow calling code to fall back to some other mechanism: 142 : : */ 143 : : #ifdef arch_trigger_cpumask_backtrace 144 : : static inline bool trigger_all_cpu_backtrace(void) 145 : : { 146 : 0 : arch_trigger_cpumask_backtrace(cpu_online_mask, false); 147 : : return true; 148 : : } 149 : : 150 : : static inline bool trigger_allbutself_cpu_backtrace(void) 151 : : { 152 : : arch_trigger_cpumask_backtrace(cpu_online_mask, true); 153 : : return true; 154 : : } 155 : : 156 : : static inline bool trigger_cpumask_backtrace(struct cpumask *mask) 157 : : { 158 : : arch_trigger_cpumask_backtrace(mask, false); 159 : : return true; 160 : : } 161 : : 162 : 0 : static inline bool trigger_single_cpu_backtrace(int cpu) 163 : : { 164 : 0 : arch_trigger_cpumask_backtrace(cpumask_of(cpu), false); 165 : 0 : return true; 166 : : } 167 : : 168 : : /* generic implementation */ 169 : : void nmi_trigger_cpumask_backtrace(const cpumask_t *mask, 170 : : bool exclude_self, 171 : : void (*raise)(cpumask_t *mask)); 172 : : bool nmi_cpu_backtrace(struct pt_regs *regs); 173 : : 174 : : #else 175 : : static inline bool trigger_all_cpu_backtrace(void) 176 : : { 177 : : return false; 178 : : } 179 : : static inline bool trigger_allbutself_cpu_backtrace(void) 180 : : { 181 : : return false; 182 : : } 183 : : static inline bool trigger_cpumask_backtrace(struct cpumask *mask) 184 : : { 185 : : return false; 186 : : } 187 : : static inline bool trigger_single_cpu_backtrace(int cpu) 188 : : { 189 : : return false; 190 : : } 191 : : #endif 192 : : 193 : : #ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF 194 : : u64 hw_nmi_get_sample_period(int watchdog_thresh); 195 : : #endif 196 : : 197 : : #if defined(CONFIG_HARDLOCKUP_CHECK_TIMESTAMP) && \ 198 : : defined(CONFIG_HARDLOCKUP_DETECTOR) 199 : : void watchdog_update_hrtimer_threshold(u64 period); 200 : : #else 201 : : static inline void watchdog_update_hrtimer_threshold(u64 period) { } 202 : : #endif 203 : : 204 : : struct ctl_table; 205 : : extern int proc_watchdog(struct ctl_table *, int , 206 : : void __user *, size_t *, loff_t *); 207 : : extern int proc_nmi_watchdog(struct ctl_table *, int , 208 : : void __user *, size_t *, loff_t *); 209 : : extern int proc_soft_watchdog(struct ctl_table *, int , 210 : : void __user *, size_t *, loff_t *); 211 : : extern int proc_watchdog_thresh(struct ctl_table *, int , 212 : : void __user *, size_t *, loff_t *); 213 : : extern int proc_watchdog_cpumask(struct ctl_table *, int, 214 : : void __user *, size_t *, loff_t *); 215 : : 216 : : #ifdef CONFIG_HAVE_ACPI_APEI_NMI 217 : : #include <asm/nmi.h> 218 : : #endif 219 : : 220 : : #endif