[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 05/14] watchdog/diag288: avoid race condition on expi
From: |
Cornelia Huck |
Subject: |
[Qemu-devel] [PULL 05/14] watchdog/diag288: avoid race condition on expired watchdog |
Date: |
Tue, 1 Mar 2016 12:52:54 +0100 |
From: Sascha Silbe <address@hidden>
When configured to inject an NMI, watchdog_perform_action() may cause
the BQL to be temporarily relinquished (inject_nmi() → ... →
s390_nmi() → s390_cpu_restart() → run_on_cpu()). When the guest issues
diag 288 again in response to the NMI, the diag 288 operation will
race against wdt_diag288_reset(). Depending on scheduler behaviour,
wdt_diag288_reset() may be run after the guest issued a diag 288
Init. As a result, we will cancel the timer the guest just set up. The
effect observed by the guest is that a second expiry does not trigger
the watchdog action and diag 288 Change operations fail.
Fix this by resetting the timer _before_ invoking the action.
Signed-off-by: Sascha Silbe <address@hidden>
Acked-by: David Hildenbrand <address@hidden>
Signed-off-by: Cornelia Huck <address@hidden>
---
hw/watchdog/wdt_diag288.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
index 5eb5b94..1c3658e 100644
--- a/hw/watchdog/wdt_diag288.c
+++ b/hw/watchdog/wdt_diag288.c
@@ -51,15 +51,19 @@ static void diag288_reset(void *opaque)
static void diag288_timer_expired(void *dev)
{
qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
- watchdog_perform_action();
- /* Reset the watchdog only if the guest was notified about expiry. */
+ /* Reset the watchdog only if the guest gets notified about
+ * expiry. watchdog_perform_action() may temporarily relinquish
+ * the BQL; reset before triggering the action to avoid races with
+ * diag288 instructions. */
switch (get_watchdog_action()) {
case WDT_DEBUG:
case WDT_NONE:
case WDT_PAUSE:
- return;
+ break;
+ default:
+ wdt_diag288_reset(dev);
}
- wdt_diag288_reset(dev);
+ watchdog_perform_action();
}
static int wdt_diag288_handle_timer(DIAG288State *diag288,
--
2.7.2
- [Qemu-devel] [PULL 00/14] s390x patches, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 02/14] s390x/kvm: sync fprs via kvm_run, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 03/14] s390x: fix debug statement in trigger_page_fault(), Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 05/14] watchdog/diag288: avoid race condition on expired watchdog,
Cornelia Huck <=
- [Qemu-devel] [PULL 08/14] s390x/pci: fix reg/dereg irq functions, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 09/14] s390x/css: Allocate channel_subsys statically, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 11/14] s390x/pci: use PCI_MSIX_FLAGS on retrieving the MSIX entries, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 13/14] MAINTAINERS: Remove entry for hw/s390x/s390-virtio-bus.[ch], Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 04/14] s390x: remove {kvm_}s390_virtio_irq(), Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 14/14] s390x/css: only suspend when enabled by orb, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 06/14] s390x/virtio: old machine leftovers, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 01/14] linux-headers: update against kvm/next, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 12/14] MAINTAINERS: Remove the old s390-virtio machine, Cornelia Huck, 2016/03/01
- [Qemu-devel] [PULL 07/14] s390x/css: introduce indicator refcounting interfaces, Cornelia Huck, 2016/03/01