From 6fa144cedf0719b284355c9cd13ea6ec9a7c26d4 Mon Sep 17 00:00:00 2001 From: Marcelo Tosatti Date: Fri, 28 Aug 2015 01:07:55 +0200 Subject: [PATCH] mc146818rtc: add rtc-reset-reinjection QMP command Message-id: <20150828010755.GA11313@amt.cnet> Patchwork-id: 67629 O-Subject: [RHEL-7.2 qemu-kvm PATCH] mc146818rtc: add rtc-reset-reinjection QMP command Bugzilla: 1191226 RH-Acked-by: Juan Quintela RH-Acked-by: Amit Shah RH-Acked-by: Laszlo Ersek Without this command libvirt refuses to allow guest agent time synchronization to function. Upstream commit f2ae8abf1fa003e7ec6ee22cc3871924422a01d0 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 Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Signed-off-by: Miroslav Rezanina --- hw/timer/mc146818rtc.c | 18 ++++++++++++++++++ monitor.c | 7 +++++++ qapi-schema.json | 13 +++++++++++++ qmp-commands.hx | 23 +++++++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 432b16c..083f573 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -26,6 +26,7 @@ #include "sysemu/sysemu.h" #include "hw/timer/mc146818rtc.h" #include "qapi/visitor.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); @@ -529,6 +531,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; @@ -889,6 +905,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 798885d..6a1d06e 100644 --- a/monitor.c +++ b/monitor.c @@ -4878,3 +4878,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 8a7cf0b..c8732c1 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -4213,3 +4213,16 @@ ## { 'command': 'query-rx-filter', 'data': { '*name': 'str' }, 'returns': ['RxFilterInfo'] } + +## +# @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 44dd48e..22a09be 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -3341,3 +3341,26 @@ Example: } 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 -- 1.8.3.1