From 85e5dc788d08ddade605a3f94a4e6cc8d2052599 Mon Sep 17 00:00:00 2001 From: Wu Zhou Date: Tue, 8 Aug 2023 16:47:21 +0800 Subject: [PATCH] dm: vRTC: fix a bug that waag can't update RTC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Through it is best to halt the RTC before changing date/time, still some OSes just write date/time while RTC is not halted. Currently the DM vRTC has already dealt the situation where openBSD writes century byte out side of vRTC halt by updating vRTC time on century byte writes. Now WaaG is found writing all date/time regs outside of vRTC halt. Because those date/time writes are not updated instantly, WaaG’s vRTC time is not actually changed. This bug has not affected anything till now when we are adding support to RTC change vm_event. To make WaaG’s vRTC work properly, this patch adds vRTC time update on all date/time writes outside of vRTC halt. Tracked-On: #8547 Signed-off-by: Wu Zhou Reviewed-by: Jian Jun Chen --- devicemodel/hw/platform/rtc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/devicemodel/hw/platform/rtc.c b/devicemodel/hw/platform/rtc.c index 80039df71..b68220be0 100644 --- a/devicemodel/hw/platform/rtc.c +++ b/devicemodel/hw/platform/rtc.c @@ -882,6 +882,12 @@ vrtc_addr_handler(struct vmctx *ctx, int vcpu, int in, int port, return 0; } +static inline bool vrtc_is_time_register(uint32_t offset) +{ + return ((offset == RTC_SEC) || (offset == RTC_MIN) || (offset == RTC_HRS) || (offset == RTC_DAY) + || (offset == RTC_MONTH) || (offset == RTC_YEAR) || (offset == RTC_CENTURY)); +} + int vrtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, uint32_t *eax, void *arg) @@ -960,10 +966,11 @@ vrtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, } /* - * XXX some guests (e.g. OpenBSD) write the century byte - * outside of RTCSB_HALT so re-calculate the RTC date/time. + * Some guests (e.g. OpenBSD) write the century byte outside of RTCSB_HALT, + * and some guests (e.g. WaaG) write all date/time outside of RTCSB_HALT, + * so re-calculate the RTC date/time. */ - if (offset == RTC_CENTURY && !rtc_halted(vrtc)) { + if (vrtc_is_time_register(offset) && !rtc_halted(vrtc)) { curtime = rtc_to_secs(vrtc); error = vrtc_time_update(vrtc, curtime, time(NULL)); if ((error != 0) || (curtime == VRTC_BROKEN_TIME && rtc_flag_broken_time))