aboutsummaryrefslogtreecommitdiff
path: root/hw/timer/mc146818rtc.c
diff options
context:
space:
mode:
authorPaul Donohue <qemu-devel@PaulSD.com>2015-06-12 10:10:14 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2015-06-19 12:27:14 +0200
commitae46e23964ad45d5bc72374040e87d8f52ac2178 (patch)
treef33f22a3d54807a496cdc552736cb31f59c50b40 /hw/timer/mc146818rtc.c
parentfb1a3a051d89975f26296163066bb0745ecca49d (diff)
mc146818rtc: Reset the periodic timer on load
When loading a VM from a snapshot or migration, clock changes can cause the periodic timer to stall or loop rapidly. qemu-timer has a reset notifier mechanism that is used to avoid timer stalls or loops if the host clock changes while the VM is running when using QEMU_CLOCK_HOST. However, when loading a snapshot or migration, qemu-timer is initialized and fires the reset notifier before mc146818rtc is initialized and has registered its reset handler. In addition, this mechanism isn't used when using QEMU_CLOCK_REALTIME, which might also change when loading a snapshot or migration. To correct that problem, this commit resets the periodic timer after loading from a snapshot or migration if the clock has either jumped backward or has jumped forward by more than the clock jump limit that is used by the reset notifier code in qemu-timer. Signed-off-by: Paul Donohue <qemu-git@PaulSD.com> Message-Id: <20150612141013.GE2749@TopQuark.net> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/timer/mc146818rtc.c')
-rw-r--r--hw/timer/mc146818rtc.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 32048258c9..2e3ffc8c07 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -723,6 +723,12 @@ static int rtc_post_load(void *opaque, int version_id)
check_update_timer(s);
}
+ uint64_t now = qemu_clock_get_ns(rtc_clock);
+ if (now < s->next_periodic_time ||
+ now > (s->next_periodic_time + get_max_clock_jump())) {
+ periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
+ }
+
#ifdef TARGET_I386
if (version_id >= 2) {
if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) {