5d360b
From 5918245d224a7a527052ed30af2627187777a282 Mon Sep 17 00:00:00 2001
5d360b
From: Richard Jones <rjones@redhat.com>
5d360b
Date: Wed, 1 Nov 2017 11:33:01 +0100
5d360b
Subject: [PATCH 6/7] i6300esb: fix timer overflow
5d360b
5d360b
RH-Author: Richard Jones <rjones@redhat.com>
5d360b
Message-id: <1509535982-27927-3-git-send-email-rjones@redhat.com>
5d360b
Patchwork-id: 77460
5d360b
O-Subject: [RHEL-7.5 qemu-kvm PATCH v3 2/3] i6300esb: fix timer overflow
5d360b
Bugzilla: 1470244
5d360b
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
5d360b
RH-Acked-by: Thomas Huth <thuth@redhat.com>
5d360b
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
5d360b
5d360b
From: Laurent Vivier <lvivier@redhat.com>
5d360b
5d360b
We use muldiv64() to compute the time to wait:
5d360b
5d360b
    timeout = muldiv64(get_ticks_per_sec(), timeout, 33000000);
5d360b
5d360b
but get_ticks_per_sec() is 10^9 (30 bit value) and timeout
5d360b
is a 35 bit value.
5d360b
5d360b
Whereas muldiv64 is:
5d360b
5d360b
    uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
5d360b
5d360b
So we loose 3 bits of timeout.
5d360b
5d360b
Swapping get_ticks_per_sec() and timeout fixes it.
5d360b
5d360b
We can also replace it by a multiplication by 30 ns,
5d360b
but this changes PCI clock frequency from 33MHz to 33.333333MHz
5d360b
and we need to do this on all the QEMU PCI devices (later...)
5d360b
5d360b
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
5d360b
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
5d360b
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
5d360b
(cherry picked from commit fee562e9e41290a22623de83b673a8929ec5280d)
5d360b
5d360b
BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1470244
5d360b
Upstream-status: fee562e9e41290a22623de83b673a8929ec5280d
5d360b
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
5d360b
---
5d360b
 hw/watchdog/wdt_i6300esb.c | 2 +-
5d360b
 1 file changed, 1 insertion(+), 1 deletion(-)
5d360b
5d360b
diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c
5d360b
index be35034..fa8e3b9 100644
5d360b
--- a/hw/watchdog/wdt_i6300esb.c
5d360b
+++ b/hw/watchdog/wdt_i6300esb.c
5d360b
@@ -132,7 +132,7 @@ static void i6300esb_restart_timer(I6300State *d, int stage)
5d360b
      * multiply here can exceed 64-bits, before we divide by 33MHz, so
5d360b
      * we use a higher-precision intermediate result.
5d360b
      */
5d360b
-    timeout = muldiv64(get_ticks_per_sec(), timeout, 33000000);
5d360b
+    timeout = muldiv64(timeout, get_ticks_per_sec(), 33000000);
5d360b
 
5d360b
     i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout);
5d360b
 
5d360b
-- 
5d360b
1.8.3.1
5d360b