diff options
Diffstat (limited to 'kernel/watchdog.c')
-rw-r--r-- | kernel/watchdog.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index df30ee08bdd4..4b1dfba70f7c 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/sysctl.h> | 24 | #include <linux/sysctl.h> |
25 | 25 | ||
26 | #include <asm/irq_regs.h> | 26 | #include <asm/irq_regs.h> |
27 | #include <linux/kvm_para.h> | ||
27 | #include <linux/perf_event.h> | 28 | #include <linux/perf_event.h> |
28 | 29 | ||
29 | int watchdog_enabled = 1; | 30 | int watchdog_enabled = 1; |
@@ -280,6 +281,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) | |||
280 | __this_cpu_write(softlockup_touch_sync, false); | 281 | __this_cpu_write(softlockup_touch_sync, false); |
281 | sched_clock_tick(); | 282 | sched_clock_tick(); |
282 | } | 283 | } |
284 | |||
285 | /* Clear the guest paused flag on watchdog reset */ | ||
286 | kvm_check_and_clear_guest_paused(); | ||
283 | __touch_watchdog(); | 287 | __touch_watchdog(); |
284 | return HRTIMER_RESTART; | 288 | return HRTIMER_RESTART; |
285 | } | 289 | } |
@@ -292,6 +296,14 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer) | |||
292 | */ | 296 | */ |
293 | duration = is_softlockup(touch_ts); | 297 | duration = is_softlockup(touch_ts); |
294 | if (unlikely(duration)) { | 298 | if (unlikely(duration)) { |
299 | /* | ||
300 | * If a virtual machine is stopped by the host it can look to | ||
301 | * the watchdog like a soft lockup, check to see if the host | ||
302 | * stopped the vm before we issue the warning | ||
303 | */ | ||
304 | if (kvm_check_and_clear_guest_paused()) | ||
305 | return HRTIMER_RESTART; | ||
306 | |||
295 | /* only warn once */ | 307 | /* only warn once */ |
296 | if (__this_cpu_read(soft_watchdog_warn) == true) | 308 | if (__this_cpu_read(soft_watchdog_warn) == true) |
297 | return HRTIMER_RESTART; | 309 | return HRTIMER_RESTART; |
@@ -360,6 +372,13 @@ static int watchdog(void *unused) | |||
360 | 372 | ||
361 | 373 | ||
362 | #ifdef CONFIG_HARDLOCKUP_DETECTOR | 374 | #ifdef CONFIG_HARDLOCKUP_DETECTOR |
375 | /* | ||
376 | * People like the simple clean cpu node info on boot. | ||
377 | * Reduce the watchdog noise by only printing messages | ||
378 | * that are different from what cpu0 displayed. | ||
379 | */ | ||
380 | static unsigned long cpu0_err; | ||
381 | |||
363 | static int watchdog_nmi_enable(int cpu) | 382 | static int watchdog_nmi_enable(int cpu) |
364 | { | 383 | { |
365 | struct perf_event_attr *wd_attr; | 384 | struct perf_event_attr *wd_attr; |
@@ -378,11 +397,21 @@ static int watchdog_nmi_enable(int cpu) | |||
378 | 397 | ||
379 | /* Try to register using hardware perf events */ | 398 | /* Try to register using hardware perf events */ |
380 | event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL); | 399 | event = perf_event_create_kernel_counter(wd_attr, cpu, NULL, watchdog_overflow_callback, NULL); |
400 | |||
401 | /* save cpu0 error for future comparision */ | ||
402 | if (cpu == 0 && IS_ERR(event)) | ||
403 | cpu0_err = PTR_ERR(event); | ||
404 | |||
381 | if (!IS_ERR(event)) { | 405 | if (!IS_ERR(event)) { |
382 | pr_info("enabled, takes one hw-pmu counter.\n"); | 406 | /* only print for cpu0 or different than cpu0 */ |
407 | if (cpu == 0 || cpu0_err) | ||
408 | pr_info("enabled on all CPUs, permanently consumes one hw-PMU counter.\n"); | ||
383 | goto out_save; | 409 | goto out_save; |
384 | } | 410 | } |
385 | 411 | ||
412 | /* skip displaying the same error again */ | ||
413 | if (cpu > 0 && (PTR_ERR(event) == cpu0_err)) | ||
414 | return PTR_ERR(event); | ||
386 | 415 | ||
387 | /* vary the KERN level based on the returned errno */ | 416 | /* vary the KERN level based on the returned errno */ |
388 | if (PTR_ERR(event) == -EOPNOTSUPP) | 417 | if (PTR_ERR(event) == -EOPNOTSUPP) |