234 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * linux/include/linux/nmi.h4 */5#ifndef LINUX_NMI_H6#define LINUX_NMI_H7 8#include <linux/sched.h>9#include <asm/irq.h>10 11/* Arch specific watchdogs might need to share extra watchdog-related APIs. */12#if defined(CONFIG_HARDLOCKUP_DETECTOR_ARCH) || defined(CONFIG_HARDLOCKUP_DETECTOR_SPARC64)13#include <asm/nmi.h>14#endif15 16#ifdef CONFIG_LOCKUP_DETECTOR17void lockup_detector_init(void);18void lockup_detector_retry_init(void);19void lockup_detector_soft_poweroff(void);20void lockup_detector_cleanup(void);21 22extern int watchdog_user_enabled;23extern int watchdog_thresh;24extern unsigned long watchdog_enabled;25 26extern struct cpumask watchdog_cpumask;27extern unsigned long *watchdog_cpumask_bits;28#ifdef CONFIG_SMP29extern int sysctl_softlockup_all_cpu_backtrace;30extern int sysctl_hardlockup_all_cpu_backtrace;31#else32#define sysctl_softlockup_all_cpu_backtrace 033#define sysctl_hardlockup_all_cpu_backtrace 034#endif /* !CONFIG_SMP */35 36#else /* CONFIG_LOCKUP_DETECTOR */37static inline void lockup_detector_init(void) { }38static inline void lockup_detector_retry_init(void) { }39static inline void lockup_detector_soft_poweroff(void) { }40static inline void lockup_detector_cleanup(void) { }41#endif /* !CONFIG_LOCKUP_DETECTOR */42 43#ifdef CONFIG_SOFTLOCKUP_DETECTOR44extern void touch_softlockup_watchdog_sched(void);45extern void touch_softlockup_watchdog(void);46extern void touch_softlockup_watchdog_sync(void);47extern void touch_all_softlockup_watchdogs(void);48extern unsigned int softlockup_panic;49 50extern int lockup_detector_online_cpu(unsigned int cpu);51extern int lockup_detector_offline_cpu(unsigned int cpu);52#else /* CONFIG_SOFTLOCKUP_DETECTOR */53static inline void touch_softlockup_watchdog_sched(void) { }54static inline void touch_softlockup_watchdog(void) { }55static inline void touch_softlockup_watchdog_sync(void) { }56static inline void touch_all_softlockup_watchdogs(void) { }57 58#define lockup_detector_online_cpu NULL59#define lockup_detector_offline_cpu NULL60#endif /* CONFIG_SOFTLOCKUP_DETECTOR */61 62#ifdef CONFIG_DETECT_HUNG_TASK63void reset_hung_task_detector(void);64#else65static inline void reset_hung_task_detector(void) { }66#endif67 68/*69 * The run state of the lockup detectors is controlled by the content of the70 * 'watchdog_enabled' variable. Each lockup detector has its dedicated bit -71 * bit 0 for the hard lockup detector and bit 1 for the soft lockup detector.72 *73 * 'watchdog_user_enabled', 'watchdog_hardlockup_user_enabled' and74 * 'watchdog_softlockup_user_enabled' are variables that are only used as an75 * 'interface' between the parameters in /proc/sys/kernel and the internal76 * state bits in 'watchdog_enabled'. The 'watchdog_thresh' variable is77 * handled differently because its value is not boolean, and the lockup78 * detectors are 'suspended' while 'watchdog_thresh' is equal zero.79 */80#define WATCHDOG_HARDLOCKUP_ENABLED_BIT 081#define WATCHDOG_SOFTOCKUP_ENABLED_BIT 182#define WATCHDOG_HARDLOCKUP_ENABLED (1 << WATCHDOG_HARDLOCKUP_ENABLED_BIT)83#define WATCHDOG_SOFTOCKUP_ENABLED (1 << WATCHDOG_SOFTOCKUP_ENABLED_BIT)84 85#if defined(CONFIG_HARDLOCKUP_DETECTOR)86extern void hardlockup_detector_disable(void);87extern unsigned int hardlockup_panic;88#else89static inline void hardlockup_detector_disable(void) {}90#endif91 92/* Sparc64 has special implemetantion that is always enabled. */93#if defined(CONFIG_HARDLOCKUP_DETECTOR) || defined(CONFIG_HARDLOCKUP_DETECTOR_SPARC64)94void arch_touch_nmi_watchdog(void);95#else96static inline void arch_touch_nmi_watchdog(void) { }97#endif98 99#if defined(CONFIG_HARDLOCKUP_DETECTOR_COUNTS_HRTIMER)100void watchdog_hardlockup_touch_cpu(unsigned int cpu);101void watchdog_hardlockup_check(unsigned int cpu, struct pt_regs *regs);102#endif103 104#if defined(CONFIG_HARDLOCKUP_DETECTOR_PERF)105extern void hardlockup_detector_perf_stop(void);106extern void hardlockup_detector_perf_restart(void);107extern void hardlockup_detector_perf_cleanup(void);108extern void hardlockup_config_perf_event(const char *str);109#else110static inline void hardlockup_detector_perf_stop(void) { }111static inline void hardlockup_detector_perf_restart(void) { }112static inline void hardlockup_detector_perf_cleanup(void) { }113static inline void hardlockup_config_perf_event(const char *str) { }114#endif115 116void watchdog_hardlockup_stop(void);117void watchdog_hardlockup_start(void);118int watchdog_hardlockup_probe(void);119void watchdog_hardlockup_enable(unsigned int cpu);120void watchdog_hardlockup_disable(unsigned int cpu);121 122void lockup_detector_reconfigure(void);123 124#ifdef CONFIG_HARDLOCKUP_DETECTOR_BUDDY125void watchdog_buddy_check_hardlockup(int hrtimer_interrupts);126#else127static inline void watchdog_buddy_check_hardlockup(int hrtimer_interrupts) {}128#endif129 130/**131 * touch_nmi_watchdog - manually reset the hardlockup watchdog timeout.132 *133 * If we support detecting hardlockups, touch_nmi_watchdog() may be134 * used to pet the watchdog (reset the timeout) - for code which135 * intentionally disables interrupts for a long time. This call is stateless.136 *137 * Though this function has "nmi" in the name, the hardlockup watchdog might138 * not be backed by NMIs. This function will likely be renamed to139 * touch_hardlockup_watchdog() in the future.140 */141static inline void touch_nmi_watchdog(void)142{143 /*144 * Pass on to the hardlockup detector selected via CONFIG_. Note that145 * the hardlockup detector may not be arch-specific nor using NMIs146 * and the arch_touch_nmi_watchdog() function will likely be renamed147 * in the future.148 */149 arch_touch_nmi_watchdog();150 151 touch_softlockup_watchdog();152}153 154/*155 * Create trigger_all_cpu_backtrace() out of the arch-provided156 * base function. Return whether such support was available,157 * to allow calling code to fall back to some other mechanism:158 */159#ifdef arch_trigger_cpumask_backtrace160static inline bool trigger_all_cpu_backtrace(void)161{162 arch_trigger_cpumask_backtrace(cpu_online_mask, -1);163 return true;164}165 166static inline bool trigger_allbutcpu_cpu_backtrace(int exclude_cpu)167{168 arch_trigger_cpumask_backtrace(cpu_online_mask, exclude_cpu);169 return true;170}171 172static inline bool trigger_cpumask_backtrace(struct cpumask *mask)173{174 arch_trigger_cpumask_backtrace(mask, -1);175 return true;176}177 178static inline bool trigger_single_cpu_backtrace(int cpu)179{180 arch_trigger_cpumask_backtrace(cpumask_of(cpu), -1);181 return true;182}183 184/* generic implementation */185void nmi_trigger_cpumask_backtrace(const cpumask_t *mask,186 int exclude_cpu,187 void (*raise)(cpumask_t *mask));188bool nmi_cpu_backtrace(struct pt_regs *regs);189 190#else191static inline bool trigger_all_cpu_backtrace(void)192{193 return false;194}195static inline bool trigger_allbutcpu_cpu_backtrace(int exclude_cpu)196{197 return false;198}199static inline bool trigger_cpumask_backtrace(struct cpumask *mask)200{201 return false;202}203static inline bool trigger_single_cpu_backtrace(int cpu)204{205 return false;206}207#endif208 209#ifdef CONFIG_HARDLOCKUP_DETECTOR_PERF210u64 hw_nmi_get_sample_period(int watchdog_thresh);211bool arch_perf_nmi_is_available(void);212#endif213 214#if defined(CONFIG_HARDLOCKUP_CHECK_TIMESTAMP) && \215 defined(CONFIG_HARDLOCKUP_DETECTOR_PERF)216void watchdog_update_hrtimer_threshold(u64 period);217#else218static inline void watchdog_update_hrtimer_threshold(u64 period) { }219#endif220 221#ifdef CONFIG_HAVE_ACPI_APEI_NMI222#include <asm/nmi.h>223#endif224 225#ifdef CONFIG_NMI_CHECK_CPU226void nmi_backtrace_stall_snap(const struct cpumask *btp);227void nmi_backtrace_stall_check(const struct cpumask *btp);228#else229static inline void nmi_backtrace_stall_snap(const struct cpumask *btp) {}230static inline void nmi_backtrace_stall_check(const struct cpumask *btp) {}231#endif232 233#endif234