From f528b3d2c27fd9a1e1180161b562b3d3cd9c094e Mon Sep 17 00:00:00 2001
From: Gleb Natapov <gleb@redhat.com>
Date: Tue, 13 Mar 2012 10:26:29 +0100
Subject: [PATCH 3/3] mc146818rtc: Handle host clock resets

RH-Author: Gleb Natapov <gleb@redhat.com>
Message-id: <1331634389-10990-3-git-send-email-gleb@redhat.com>
Patchwork-id: 38475
O-Subject: [PATCH RHEL6.3 qemu-kvm v2 2/2] mc146818rtc: Handle host clock resets
Bugzilla: 734426
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>

Make use of the new clock reset notifier to update the RTC whenever
rtc_clock is the host clock and that happens to jump backward. This
avoids that the RTC stalls for the period the host clock was set back.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

Upstream commit: 17604dac28b2410c021a4a52dcfa58e8803dfb24
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
 hw/mc146818rtc.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 hw/mc146818rtc.c |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index cba9ca8..119315d 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -85,6 +85,7 @@ struct RTCState {
     QEMUTimer *second_timer;
     QEMUTimer *second_timer2;
     Notifier suspend_notifier;
+    Notifier clock_reset_notifier;
 };
 
 /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE)
@@ -571,6 +572,22 @@ static const VMStateDescription vmstate_rtc = {
     }
 };
 
+static void rtc_notify_clock_reset(Notifier *notifier, void *data)
+{
+    RTCState *s = container_of(notifier, RTCState, clock_reset_notifier);
+    int64_t now = *(int64_t *)data;
+
+    rtc_set_date_from_host(s);
+    s->next_second_time = now + (get_ticks_per_sec() * 99) / 100;
+    qemu_mod_timer(s->second_timer2, s->next_second_time);
+    rtc_timer_update(s, now);
+#ifdef TARGET_I386
+    if (rtc_td_hack) {
+        rtc_coalesced_timer_update(s);
+    }
+#endif
+}
+
 static void rtc_reset(void *opaque)
 {
     RTCState *s = opaque;
@@ -612,6 +629,8 @@ static int rtc_initfn(ISADevice *dev)
 
     s->suspend_notifier.notify = rtc_notify_suspend;
     qemu_register_suspend_notifier(&s->suspend_notifier);
+    s->clock_reset_notifier.notify = rtc_notify_clock_reset;
+    qemu_register_clock_reset_notifier(rtc_clock, &s->clock_reset_notifier);
 
     s->next_second_time =
         qemu_get_clock(rtc_clock) + (get_ticks_per_sec() * 99) / 100;
-- 
1.7.7.6