|
|
8b1478 |
From ae11a1ea30f43abebd96a22988619eb9f52e6a4e Mon Sep 17 00:00:00 2001
|
|
|
8b1478 |
From: Marcelo Tosatti <mtosatti@redhat.com>
|
|
|
8b1478 |
Date: Wed, 4 Dec 2019 15:21:07 +0100
|
|
|
8b1478 |
Subject: [PATCH 1/3] mc146818rtc: fix timer interrupt reinjection
|
|
|
8b1478 |
|
|
|
8b1478 |
RH-Author: Marcelo Tosatti <mtosatti@redhat.com>
|
|
|
8b1478 |
Message-id: <20191204152436.680299856@amt.cnet>
|
|
|
8b1478 |
Patchwork-id: 92889
|
|
|
8b1478 |
O-Subject: [RHEL-7.8 qemu-kvm-rhev PATCH 1/3] mc146818rtc: fix timer interrupt reinjection
|
|
|
8b1478 |
Bugzilla: 1639098
|
|
|
8b1478 |
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
|
|
8b1478 |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
8b1478 |
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
|
|
8b1478 |
|
|
|
8b1478 |
BZ: 1639098
|
|
|
8b1478 |
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=24854309
|
|
|
8b1478 |
BRANCH: rhv7/master-2.12.0
|
|
|
8b1478 |
Upstream: b429de730174b388ea5760e3debb0d542ea3c261
|
|
|
8b1478 |
of pbonzini's for-upstream tree.
|
|
|
8b1478 |
|
|
|
8b1478 |
commit 369b41359af46bded5799c9ef8be2b641d92e043 broke timer interrupt
|
|
|
8b1478 |
reinjection when there is no period change by the guest.
|
|
|
8b1478 |
|
|
|
8b1478 |
In that case, old_period is 0, which ends up zeroing irq_coalesced
|
|
|
8b1478 |
(counter of reinjected interrupts).
|
|
|
8b1478 |
|
|
|
8b1478 |
The consequence is Windows 7 is unable to synchronize time via NTP.
|
|
|
8b1478 |
Easily reproducible by playing a fullscreen video with cirrus and VNC.
|
|
|
8b1478 |
|
|
|
8b1478 |
Fix by not updating s->irq_coalesced when old_period is 0.
|
|
|
8b1478 |
|
|
|
8b1478 |
V2: reorganize code (Paolo Bonzini)
|
|
|
8b1478 |
|
|
|
8b1478 |
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
|
|
|
8b1478 |
Message-Id: <20191010123008.GA19158@amt.cnet>
|
|
|
8b1478 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
8b1478 |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
8b1478 |
---
|
|
|
8b1478 |
hw/timer/mc146818rtc.c | 53 +++++++++++++++++++++++++-------------------------
|
|
|
8b1478 |
1 file changed, 27 insertions(+), 26 deletions(-)
|
|
|
8b1478 |
|
|
|
8b1478 |
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
|
|
|
8b1478 |
index 68c353f..296d974 100644
|
|
|
8b1478 |
--- a/hw/timer/mc146818rtc.c
|
|
|
8b1478 |
+++ b/hw/timer/mc146818rtc.c
|
|
|
8b1478 |
@@ -197,24 +197,28 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
|
|
|
8b1478 |
|
|
|
8b1478 |
period = rtc_periodic_clock_ticks(s);
|
|
|
8b1478 |
|
|
|
8b1478 |
- if (period) {
|
|
|
8b1478 |
- /* compute 32 khz clock */
|
|
|
8b1478 |
- cur_clock =
|
|
|
8b1478 |
- muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
|
|
|
8b1478 |
+ if (!period) {
|
|
|
8b1478 |
+ s->irq_coalesced = 0;
|
|
|
8b1478 |
+ timer_del(s->periodic_timer);
|
|
|
8b1478 |
+ return;
|
|
|
8b1478 |
+ }
|
|
|
8b1478 |
|
|
|
8b1478 |
- /*
|
|
|
8b1478 |
- * if the periodic timer's update is due to period re-configuration,
|
|
|
8b1478 |
- * we should count the clock since last interrupt.
|
|
|
8b1478 |
- */
|
|
|
8b1478 |
- if (old_period) {
|
|
|
8b1478 |
- int64_t last_periodic_clock, next_periodic_clock;
|
|
|
8b1478 |
-
|
|
|
8b1478 |
- next_periodic_clock = muldiv64(s->next_periodic_time,
|
|
|
8b1478 |
- RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
|
|
|
8b1478 |
- last_periodic_clock = next_periodic_clock - old_period;
|
|
|
8b1478 |
- lost_clock = cur_clock - last_periodic_clock;
|
|
|
8b1478 |
- assert(lost_clock >= 0);
|
|
|
8b1478 |
- }
|
|
|
8b1478 |
+ /* compute 32 khz clock */
|
|
|
8b1478 |
+ cur_clock =
|
|
|
8b1478 |
+ muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
|
|
|
8b1478 |
+
|
|
|
8b1478 |
+ /*
|
|
|
8b1478 |
+ * if the periodic timer's update is due to period re-configuration,
|
|
|
8b1478 |
+ * we should count the clock since last interrupt.
|
|
|
8b1478 |
+ */
|
|
|
8b1478 |
+ if (old_period) {
|
|
|
8b1478 |
+ int64_t last_periodic_clock, next_periodic_clock;
|
|
|
8b1478 |
+
|
|
|
8b1478 |
+ next_periodic_clock = muldiv64(s->next_periodic_time,
|
|
|
8b1478 |
+ RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND);
|
|
|
8b1478 |
+ last_periodic_clock = next_periodic_clock - old_period;
|
|
|
8b1478 |
+ lost_clock = cur_clock - last_periodic_clock;
|
|
|
8b1478 |
+ assert(lost_clock >= 0);
|
|
|
8b1478 |
|
|
|
8b1478 |
/*
|
|
|
8b1478 |
* s->irq_coalesced can change for two reasons:
|
|
|
8b1478 |
@@ -245,22 +249,19 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period)
|
|
|
8b1478 |
rtc_coalesced_timer_update(s);
|
|
|
8b1478 |
}
|
|
|
8b1478 |
} else {
|
|
|
8b1478 |
- /*
|
|
|
8b1478 |
+ /*
|
|
|
8b1478 |
* no way to compensate the interrupt if LOST_TICK_POLICY_SLEW
|
|
|
8b1478 |
* is not used, we should make the time progress anyway.
|
|
|
8b1478 |
*/
|
|
|
8b1478 |
lost_clock = MIN(lost_clock, period);
|
|
|
8b1478 |
}
|
|
|
8b1478 |
+ }
|
|
|
8b1478 |
|
|
|
8b1478 |
- assert(lost_clock >= 0 && lost_clock <= period);
|
|
|
8b1478 |
+ assert(lost_clock >= 0 && lost_clock <= period);
|
|
|
8b1478 |
|
|
|
8b1478 |
- next_irq_clock = cur_clock + period - lost_clock;
|
|
|
8b1478 |
- s->next_periodic_time = periodic_clock_to_ns(next_irq_clock) + 1;
|
|
|
8b1478 |
- timer_mod(s->periodic_timer, s->next_periodic_time);
|
|
|
8b1478 |
- } else {
|
|
|
8b1478 |
- s->irq_coalesced = 0;
|
|
|
8b1478 |
- timer_del(s->periodic_timer);
|
|
|
8b1478 |
- }
|
|
|
8b1478 |
+ next_irq_clock = cur_clock + period - lost_clock;
|
|
|
8b1478 |
+ s->next_periodic_time = periodic_clock_to_ns(next_irq_clock) + 1;
|
|
|
8b1478 |
+ timer_mod(s->periodic_timer, s->next_periodic_time);
|
|
|
8b1478 |
}
|
|
|
8b1478 |
|
|
|
8b1478 |
static void rtc_periodic_timer(void *opaque)
|
|
|
8b1478 |
--
|
|
|
8b1478 |
1.8.3.1
|
|
|
8b1478 |
|