Skip to content

Commit

Permalink
dm: vRTC: fix a bug that waag can't update RTC
Browse files Browse the repository at this point in the history
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: projectacrn#8547
Signed-off-by: Wu Zhou <wu.zhou@intel.com>
Reviewed-by: Jian Jun Chen <jian.jun.chen@intel.com>
  • Loading branch information
izhouwu committed Jan 19, 2024
1 parent a0f91fc commit cf52b26
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions devicemodel/hw/platform/rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Expand Down

0 comments on commit cf52b26

Please sign in to comment.