9ae3a8
From 6fa144cedf0719b284355c9cd13ea6ec9a7c26d4 Mon Sep 17 00:00:00 2001
9ae3a8
From: Marcelo Tosatti <mtosatti@redhat.com>
9ae3a8
Date: Fri, 28 Aug 2015 01:07:55 +0200
9ae3a8
Subject: [PATCH] mc146818rtc: add rtc-reset-reinjection QMP command
9ae3a8
9ae3a8
Message-id: <20150828010755.GA11313@amt.cnet>
9ae3a8
Patchwork-id: 67629
9ae3a8
O-Subject: [RHEL-7.2 qemu-kvm PATCH] mc146818rtc: add rtc-reset-reinjection QMP command
9ae3a8
Bugzilla: 1191226
9ae3a8
RH-Acked-by: Juan Quintela <quintela@redhat.com>
9ae3a8
RH-Acked-by: Amit Shah <amit.shah@redhat.com>
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
9ae3a8
Without this command libvirt refuses to allow guest agent
9ae3a8
time synchronization to function.
9ae3a8
9ae3a8
Upstream commit f2ae8abf1fa003e7ec6ee22cc3871924422a01d0
9ae3a8
9ae3a8
It is necessary to reset RTC interrupt reinjection backlog if
9ae3a8
guest time is synchronized via a different mechanism, such as
9ae3a8
QGA's guest-set-time command.
9ae3a8
9ae3a8
Failing to do so causes both corrections to be applied (summed),
9ae3a8
resulting in an incorrect guest time.
9ae3a8
9ae3a8
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
9ae3a8
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
9ae3a8
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 hw/timer/mc146818rtc.c | 18 ++++++++++++++++++
9ae3a8
 monitor.c              |  7 +++++++
9ae3a8
 qapi-schema.json       | 13 +++++++++++++
9ae3a8
 qmp-commands.hx        | 23 +++++++++++++++++++++++
9ae3a8
 4 files changed, 61 insertions(+)
9ae3a8
9ae3a8
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
9ae3a8
index 432b16c..083f573 100644
9ae3a8
--- a/hw/timer/mc146818rtc.c
9ae3a8
+++ b/hw/timer/mc146818rtc.c
9ae3a8
@@ -26,6 +26,7 @@
9ae3a8
 #include "sysemu/sysemu.h"
9ae3a8
 #include "hw/timer/mc146818rtc.h"
9ae3a8
 #include "qapi/visitor.h"
9ae3a8
+#include "qmp-commands.h"
9ae3a8
 
9ae3a8
 #ifdef TARGET_I386
9ae3a8
 #include "hw/i386/apic.h"
9ae3a8
@@ -85,6 +86,7 @@ typedef struct RTCState {
9ae3a8
     Notifier clock_reset_notifier;
9ae3a8
     LostTickPolicy lost_tick_policy;
9ae3a8
     Notifier suspend_notifier;
9ae3a8
+    QLIST_ENTRY(RTCState) link;
9ae3a8
 } RTCState;
9ae3a8
 
9ae3a8
 static void rtc_set_time(RTCState *s);
9ae3a8
@@ -529,6 +531,20 @@ static void rtc_get_time(RTCState *s, struct tm *tm)
9ae3a8
         rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900;
9ae3a8
 }
9ae3a8
 
9ae3a8
+static QLIST_HEAD(, RTCState) rtc_devices =
9ae3a8
+    QLIST_HEAD_INITIALIZER(rtc_devices);
9ae3a8
+
9ae3a8
+#ifdef TARGET_I386
9ae3a8
+void qmp_rtc_reset_reinjection(Error **errp)
9ae3a8
+{
9ae3a8
+    RTCState *s;
9ae3a8
+
9ae3a8
+    QLIST_FOREACH(s, &rtc_devices, link) {
9ae3a8
+        s->irq_coalesced = 0;
9ae3a8
+    }
9ae3a8
+}
9ae3a8
+#endif
9ae3a8
+
9ae3a8
 static void rtc_set_time(RTCState *s)
9ae3a8
 {
9ae3a8
     struct tm tm;
9ae3a8
@@ -889,6 +905,8 @@ ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
9ae3a8
     } else {
9ae3a8
         isa_init_irq(isadev, &s->irq, RTC_ISA_IRQ);
9ae3a8
     }
9ae3a8
+    QLIST_INSERT_HEAD(&rtc_devices, s, link);
9ae3a8
+
9ae3a8
     return isadev;
9ae3a8
 }
9ae3a8
 
9ae3a8
diff --git a/monitor.c b/monitor.c
9ae3a8
index 798885d..6a1d06e 100644
9ae3a8
--- a/monitor.c
9ae3a8
+++ b/monitor.c
9ae3a8
@@ -4878,3 +4878,10 @@ QemuOptsList qemu_mon_opts = {
9ae3a8
         { /* end of list */ }
9ae3a8
     },
9ae3a8
 };
9ae3a8
+
9ae3a8
+#ifndef TARGET_I386
9ae3a8
+void qmp_rtc_reset_reinjection(Error **errp)
9ae3a8
+{
9ae3a8
+    error_set(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection");
9ae3a8
+}
9ae3a8
+#endif
9ae3a8
diff --git a/qapi-schema.json b/qapi-schema.json
9ae3a8
index 8a7cf0b..c8732c1 100644
9ae3a8
--- a/qapi-schema.json
9ae3a8
+++ b/qapi-schema.json
9ae3a8
@@ -4213,3 +4213,16 @@
9ae3a8
 ##
9ae3a8
 { 'command': 'query-rx-filter', 'data': { '*name': 'str' },
9ae3a8
   'returns': ['RxFilterInfo'] }
9ae3a8
+
9ae3a8
+##
9ae3a8
+# @rtc-reset-reinjection
9ae3a8
+#
9ae3a8
+# This command will reset the RTC interrupt reinjection backlog.
9ae3a8
+# Can be used if another mechanism to synchronize guest time
9ae3a8
+# is in effect, for example QEMU guest agent's guest-set-time
9ae3a8
+# command.
9ae3a8
+#
9ae3a8
+# Since: 2.1
9ae3a8
+##
9ae3a8
+{ 'command': 'rtc-reset-reinjection' }
9ae3a8
+
9ae3a8
diff --git a/qmp-commands.hx b/qmp-commands.hx
9ae3a8
index 44dd48e..22a09be 100644
9ae3a8
--- a/qmp-commands.hx
9ae3a8
+++ b/qmp-commands.hx
9ae3a8
@@ -3341,3 +3341,26 @@ Example:
9ae3a8
    }
9ae3a8
 
9ae3a8
 EQMP
9ae3a8
+
9ae3a8
+#if defined TARGET_I386
9ae3a8
+    {
9ae3a8
+        .name       = "rtc-reset-reinjection",
9ae3a8
+        .args_type  = "",
9ae3a8
+        .mhandler.cmd_new = qmp_marshal_input_rtc_reset_reinjection,
9ae3a8
+    },
9ae3a8
+#endif
9ae3a8
+
9ae3a8
+SQMP
9ae3a8
+rtc-reset-reinjection
9ae3a8
+---------------------
9ae3a8
+
9ae3a8
+Reset the RTC interrupt reinjection backlog.
9ae3a8
+
9ae3a8
+Arguments: None.
9ae3a8
+
9ae3a8
+Example:
9ae3a8
+
9ae3a8
+-> { "execute": "rtc-reset-reinjection" }
9ae3a8
+<- { "return": {} }
9ae3a8
+
9ae3a8
+EQMP
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8