summaryrefslogtreecommitdiff
path: root/kernel/watchdog_hld.c (plain)
blob: 9a42b8bc0cc6010947e6c0491761953a543b0bb0
1/*
2 * Detect hard lockups on a system
3 *
4 * started by Don Zickus, Copyright (C) 2010 Red Hat, Inc.
5 *
6 * Note: Most of this code is borrowed heavily from the original softlockup
7 * detector, so thanks to Ingo for the initial implementation.
8 * Some chunks also taken from the old x86-specific nmi watchdog code, thanks
9 * to those contributors as well.
10 */
11
12#define pr_fmt(fmt) "NMI watchdog: " fmt
13
14#include <linux/nmi.h>
15#include <linux/module.h>
16#include <asm/irq_regs.h>
17#include <linux/perf_event.h>
18
19static DEFINE_PER_CPU(bool, hard_watchdog_warn);
20static DEFINE_PER_CPU(bool, watchdog_nmi_touch);
21#ifdef CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU
22static cpumask_t __read_mostly watchdog_cpus;
23#endif
24#ifdef CONFIG_HARDLOCKUP_DETECTOR_NMI
25static DEFINE_PER_CPU(struct perf_event *, watchdog_ev);
26#endif
27DECLARE_PER_CPU(unsigned long, hrtimer_interrupts);
28DECLARE_PER_CPU(unsigned long, hrtimer_interrupts_saved);
29
30/* boot commands */
31/*
32 * Should we panic when a soft-lockup or hard-lockup occurs:
33 */
34unsigned int __read_mostly hardlockup_panic =
35 CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE;
36static unsigned long __maybe_unused hardlockup_allcpu_dumped;
37/*
38 * We may not want to enable hard lockup detection by default in all cases,
39 * for example when running the kernel as a guest on a hypervisor. In these
40 * cases this function can be called to disable hard lockup detection. This
41 * function should only be executed once by the boot processor before the
42 * kernel command line parameters are parsed, because otherwise it is not
43 * possible to override this in hardlockup_panic_setup().
44 */
45void hardlockup_detector_disable(void)
46{
47 watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
48}
49
50static int __init hardlockup_panic_setup(char *str)
51{
52 if (!strncmp(str, "panic", 5))
53 hardlockup_panic = 1;
54 else if (!strncmp(str, "nopanic", 7))
55 hardlockup_panic = 0;
56 else if (!strncmp(str, "0", 1))
57 watchdog_enabled &= ~NMI_WATCHDOG_ENABLED;
58 else if (!strncmp(str, "1", 1))
59 watchdog_enabled |= NMI_WATCHDOG_ENABLED;
60 return 1;
61}
62__setup("nmi_watchdog=", hardlockup_panic_setup);
63
64void touch_nmi_watchdog(void)
65{
66 /*
67 * Using __raw here because some code paths have
68 * preemption enabled. If preemption is enabled
69 * then interrupts should be enabled too, in which
70 * case we shouldn't have to worry about the watchdog
71 * going off.
72 */
73 raw_cpu_write(watchdog_nmi_touch, true);
74 touch_softlockup_watchdog();
75}
76EXPORT_SYMBOL(touch_nmi_watchdog);
77
78#ifdef CONFIG_HARDLOCKUP_DETECTOR_NMI
79static struct perf_event_attr wd_hw_attr = {
80 .type = PERF_TYPE_HARDWARE,
81 .config = PERF_COUNT_HW_CPU_CYCLES,
82 .size = sizeof(struct perf_event_attr),
83 .pinned = 1,
84 .disabled = 1,
85};
86
87/* Callback function for perf event subsystem */
88static void watchdog_overflow_callback(struct perf_event *event,
89 struct perf_sample_data *data,
90 struct pt_regs *regs)
91{
92 /* Ensure the watchdog never gets throttled */
93 event->hw.interrupts = 0;
94
95 if (atomic_read(&watchdog_park_in_progress) != 0)
96 return;
97
98 if (__this_cpu_read(watchdog_nmi_touch) == true) {
99 __this_cpu_write(watchdog_nmi_touch, false);
100 return;
101 }
102
103 /* check for a hardlockup
104 * This is done by making sure our timer interrupt
105 * is incrementing. The timer interrupt should have
106 * fired multiple times before we overflow'd. If it hasn't
107 * then this is a good indication the cpu is stuck
108 */
109 if (is_hardlockup()) {
110 int this_cpu = smp_processor_id();
111
112 /* only print hardlockups once */
113 if (__this_cpu_read(hard_watchdog_warn) == true)
114 return;
115
116 pr_emerg("Watchdog detected hard LOCKUP on cpu %d", this_cpu);
117 print_modules();
118 print_irqtrace_events(current);
119 if (regs)
120 show_regs(regs);
121 else
122 dump_stack();
123
124 /*
125 * Perform all-CPU dump only once to avoid multiple hardlockups
126 * generating interleaving traces
127 */
128 if (sysctl_hardlockup_all_cpu_backtrace &&
129 !test_and_set_bit(0, &hardlockup_allcpu_dumped))
130 trigger_allbutself_cpu_backtrace();
131
132#ifdef CONFIG_AMLOGIC_DEBUG_LOCKUP
133 pr_lockup_info(next_cpu);
134#endif
135 if (hardlockup_panic)
136 nmi_panic(regs, "Hard LOCKUP");
137
138 __this_cpu_write(hard_watchdog_warn, true);
139 return;
140 }
141
142 __this_cpu_write(hard_watchdog_warn, false);
143 return;
144}
145#endif
146
147#ifdef CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU
148static unsigned int watchdog_next_cpu(unsigned int cpu)
149{
150 cpumask_t cpus = watchdog_cpus;
151 unsigned int next_cpu;
152
153 next_cpu = cpumask_next(cpu, &cpus);
154 if (next_cpu >= nr_cpu_ids)
155 next_cpu = cpumask_first(&cpus);
156
157 if (next_cpu == cpu)
158 return nr_cpu_ids;
159
160 return next_cpu;
161}
162
163static int is_hardlockup_other_cpu(unsigned int cpu)
164{
165 unsigned long hrint = per_cpu(hrtimer_interrupts, cpu);
166
167 if (per_cpu(hrtimer_interrupts_saved, cpu) == hrint)
168 return 1;
169
170 per_cpu(hrtimer_interrupts_saved, cpu) = hrint;
171 return 0;
172}
173
174void watchdog_check_hardlockup_other_cpu(void)
175{
176 unsigned int next_cpu;
177
178 /*
179 * Test for hardlockups every 3 samples. The sample period is
180 * watchdog_thresh * 2 / 5, so 3 samples gets us back to slightly over
181 * watchdog_thresh (over by 20%).
182 */
183 if (__this_cpu_read(hrtimer_interrupts) % 3 != 0)
184 return;
185
186 /* check for a hardlockup on the next cpu */
187 next_cpu = watchdog_next_cpu(smp_processor_id());
188 if (next_cpu >= nr_cpu_ids)
189 return;
190
191 /*mem barrier*/
192 smp_rmb();
193
194 if (per_cpu(watchdog_nmi_touch, next_cpu) == true) {
195 per_cpu(watchdog_nmi_touch, next_cpu) = false;
196 return;
197 }
198
199 if (is_hardlockup_other_cpu(next_cpu)) {
200 /* only warn once */
201 if (per_cpu(hard_watchdog_warn, next_cpu) == true)
202 return;
203
204#ifdef CONFIG_AMLOGIC_DEBUG_LOCKUP
205 pr_lockup_info(next_cpu);
206#endif
207 if (hardlockup_panic)
208 panic("Watchdog detected hard LOCKUP on cpu %u",
209 next_cpu);
210 else
211 WARN(1, "Watchdog detected hard LOCKUP on cpu %u",
212 next_cpu);
213
214 per_cpu(hard_watchdog_warn, next_cpu) = true;
215 } else {
216 per_cpu(hard_watchdog_warn, next_cpu) = false;
217 }
218}
219#else
220static inline void watchdog_check_hardlockup_other_cpu(void) { return; }
221#endif
222
223
224
225#ifdef CONFIG_HARDLOCKUP_DETECTOR_NMI
226/*
227 * People like the simple clean cpu node info on boot.
228 * Reduce the watchdog noise by only printing messages
229 * that are different from what cpu0 displayed.
230 */
231static unsigned long cpu0_err;
232
233int watchdog_nmi_enable(unsigned int cpu)
234{
235 struct perf_event_attr *wd_attr;
236 struct perf_event *event = per_cpu(watchdog_ev, cpu);
237
238 /* nothing to do if the hard lockup detector is disabled */
239 if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
240 goto out;
241
242 /* is it already setup and enabled? */
243 if (event && event->state > PERF_EVENT_STATE_OFF)
244 goto out;
245
246 /* it is setup but not enabled */
247 if (event != NULL)
248 goto out_enable;
249
250 wd_attr = &wd_hw_attr;
251 wd_attr->sample_period = hw_nmi_get_sample_period(watchdog_thresh);
252
253 /* Try to register using hardware perf events */
254 event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL);
255
256 /* save cpu0 error for future comparision */
257 if (cpu == 0 && IS_ERR(event))
258 cpu0_err = PTR_ERR(event);
259
260 if (!IS_ERR(event)) {
261 /* only print for cpu0 or different than cpu0 */
262 if (cpu == 0 || cpu0_err)
263 pr_info("enabled on all CPUs, permanently consumes one hw-PMU counter.\n");
264 goto out_save;
265 }
266
267 /*
268 * Disable the hard lockup detector if _any_ CPU fails to set up
269 * set up the hardware perf event. The watchdog() function checks
270 * the NMI_WATCHDOG_ENABLED bit periodically.
271 *
272 * The barriers are for syncing up watchdog_enabled across all the
273 * cpus, as clear_bit() does not use barriers.
274 */
275 smp_mb__before_atomic();
276 clear_bit(NMI_WATCHDOG_ENABLED_BIT, &watchdog_enabled);
277 smp_mb__after_atomic();
278
279 /* skip displaying the same error again */
280 if (cpu > 0 && (PTR_ERR(event) == cpu0_err))
281 return PTR_ERR(event);
282
283 /* vary the KERN level based on the returned errno */
284 if (PTR_ERR(event) == -EOPNOTSUPP)
285 pr_info("disabled (cpu%i): not supported (no LAPIC?)\n", cpu);
286 else if (PTR_ERR(event) == -ENOENT)
287 pr_warn("disabled (cpu%i): hardware events not enabled\n",
288 cpu);
289 else
290 pr_err("disabled (cpu%i): unable to create perf event: %ld\n",
291 cpu, PTR_ERR(event));
292
293 pr_info("Shutting down hard lockup detector on all cpus\n");
294
295 return PTR_ERR(event);
296
297 /* success path */
298out_save:
299 per_cpu(watchdog_ev, cpu) = event;
300out_enable:
301 perf_event_enable(per_cpu(watchdog_ev, cpu));
302out:
303 return 0;
304}
305
306void watchdog_nmi_disable(unsigned int cpu)
307{
308 struct perf_event *event = per_cpu(watchdog_ev, cpu);
309
310 if (event) {
311 perf_event_disable(event);
312 per_cpu(watchdog_ev, cpu) = NULL;
313
314 /* should be in cleanup, but blocks oprofile */
315 perf_event_release_kernel(event);
316 }
317 if (cpu == 0) {
318 /* watchdog_nmi_enable() expects this to be zero initially. */
319 cpu0_err = 0;
320 }
321}
322#else
323#ifdef CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU
324int watchdog_nmi_enable(unsigned int cpu)
325{
326 /*
327 * The new cpu will be marked online before the first hrtimer interrupt
328 * runs on it. If another cpu tests for a hardlockup on the new cpu
329 * before it has run its first hrtimer, it will get a false positive.
330 * Touch the watchdog on the new cpu to delay the first check for at
331 * least 3 sampling periods to guarantee one hrtimer has run on the new
332 * cpu.
333 */
334 per_cpu(watchdog_nmi_touch, cpu) = true;
335 /*mem barrier*/
336 smp_wmb();
337 cpumask_set_cpu(cpu, &watchdog_cpus);
338 return 0;
339}
340
341void watchdog_nmi_disable(unsigned int cpu)
342{
343 unsigned int next_cpu = watchdog_next_cpu(cpu);
344
345 /*
346 * Offlining this cpu will cause the cpu before this one to start
347 * checking the one after this one. If this cpu just finished checking
348 * the next cpu and updating hrtimer_interrupts_saved, and then the
349 * previous cpu checks it within one sample period, it will trigger a
350 * false positive. Touch the watchdog on the next cpu to prevent it.
351 */
352 if (next_cpu < nr_cpu_ids)
353 per_cpu(watchdog_nmi_touch, next_cpu) = true;
354 /*mem barrier*/
355 smp_wmb();
356 cpumask_clear_cpu(cpu, &watchdog_cpus);
357}
358#else
359int watchdog_nmi_enable(unsigned int cpu) { return 0; }
360void watchdog_nmi_disable(unsigned int cpu) { return; }
361#endif /* CONFIG_HARDLOCKUP_DETECTOR_OTHER_CPU */
362#endif /* CONFIG_HARDLOCKUP_DETECTOR_NMI */
363