aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2014-06-24 18:55:11 -0300
committerMichael S. Tsirkin <mst@redhat.com>2014-06-29 18:59:35 +0300
commitf2ae8abf1fa003e7ec6ee22cc3871924422a01d0 (patch)
treeb7c7f3bd2345af11289f489b939f544924070de8
parentfa118d1f8be40860469e8e23745d0202bdf229ba (diff)
mc146818rtc: add rtc-reset-reinjection QMP command
It is necessary to reset RTC interrupt reinjection backlog if guest time is synchronized via a different mechanism, such as QGA's guest-set-time command. Failing to do so causes both corrections to be applied (summed), resulting in an incorrect guest time. Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/timer/mc146818rtc.c18
-rw-r--r--monitor.c7
-rw-r--r--qapi-schema.json12
-rw-r--r--qmp-commands.hx23
4 files changed, 60 insertions, 0 deletions
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 05002bf9d6..307732c744 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -27,6 +27,7 @@
#include "hw/timer/mc146818rtc.h"
#include "qapi/visitor.h"
#include "qapi-event.h"
+#include "qmp-commands.h"
#ifdef TARGET_I386
#include "hw/i386/apic.h"
@@ -85,6 +86,7 @@ typedef struct RTCState {
Notifier clock_reset_notifier;
LostTickPolicy lost_tick_policy;
Notifier suspend_notifier;
+ QLIST_ENTRY(RTCState) link;
} RTCState;
static void rtc_set_time(RTCState *s);
@@ -523,6 +525,20 @@ static void rtc_get_time(RTCState *s, struct tm *tm)
rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900;
}
+static QLIST_HEAD(, RTCState) rtc_devices =
+ QLIST_HEAD_INITIALIZER(rtc_devices);
+
+#ifdef TARGET_I386
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+ RTCState *s;
+
+ QLIST_FOREACH(s, &rtc_devices, link) {
+ s->irq_coalesced = 0;
+ }
+}
+#endif
+
static void rtc_set_time(RTCState *s)
{
struct tm tm;
@@ -911,6 +927,8 @@ ISADevice *rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
} else {
isa_init_irq(isadev, &s->irq, RTC_ISA_IRQ);
}
+ QLIST_INSERT_HEAD(&rtc_devices, s, link);
+
return isadev;
}
diff --git a/monitor.c b/monitor.c
index 5718d0b60a..799131bd01 100644
--- a/monitor.c
+++ b/monitor.c
@@ -5441,3 +5441,10 @@ QemuOptsList qemu_mon_opts = {
{ /* end of list */ }
},
};
+
+#ifndef TARGET_I386
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+ error_set(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection");
+}
+#endif
diff --git a/qapi-schema.json b/qapi-schema.json
index a83befc05b..b11aad2068 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -3468,3 +3468,15 @@
##
{ 'enum': 'GuestPanicAction',
'data': [ 'pause' ] }
+
+##
+# @rtc-reset-reinjection
+#
+# This command will reset the RTC interrupt reinjection backlog.
+# Can be used if another mechanism to synchronize guest time
+# is in effect, for example QEMU guest agent's guest-set-time
+# command.
+#
+# Since: 2.1
+##
+{ 'command': 'rtc-reset-reinjection' }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 65218bc147..1ea18b22a3 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -3675,3 +3675,26 @@ Example:
{ "slot": "3", "slot-type": "DIMM", "source": 0, "status": 0}
]}
EQMP
+
+#if defined TARGET_I386
+ {
+ .name = "rtc-reset-reinjection",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_rtc_reset_reinjection,
+ },
+#endif
+
+SQMP
+rtc-reset-reinjection
+---------------------
+
+Reset the RTC interrupt reinjection backlog.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "rtc-reset-reinjection" }
+<- { "return": {} }
+
+EQMP