Skip to content

Commit

Permalink
dm: vRTC: use monotonic time for vrtc base time
Browse files Browse the repository at this point in the history
The dm vrtc has been using time(NULL) as the vrtc base time. When
service VM system time is adjusted, the vrtc will experience time jump
which will make the vrtc time inaccurate. Change the source of base
time to monotonic time can resolve this issue, as the monotonic time is
not setable.

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 cf52b26 commit d3897c3
Showing 1 changed file with 17 additions and 6 deletions.
23 changes: 17 additions & 6 deletions devicemodel/hw/platform/rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,17 @@ update_enabled(struct vrtc *vrtc)
return true;
}

/* monotonic time is number of seconds that the system has been running
* since it was booted. It is none setable. It is more suitable to be used
* as base time.
*/
static time_t monotonic_time(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec;
}

static time_t
vrtc_curtime(struct vrtc *vrtc, time_t *basetime)
{
Expand All @@ -229,7 +240,7 @@ vrtc_curtime(struct vrtc *vrtc, time_t *basetime)
t = vrtc->base_rtctime;
*basetime = vrtc->base_uptime;
if (update_enabled(vrtc)) {
now = time(NULL);
now = monotonic_time();
delta = now - vrtc->base_uptime;
secs = delta;
t += secs;
Expand Down Expand Up @@ -736,7 +747,7 @@ vrtc_set_reg_b(struct vrtc *vrtc, uint8_t newval)
if (changed & RTCSB_HALT) {
if ((newval & RTCSB_HALT) == 0) {
rtctime = rtc_to_secs(vrtc);
basetime = time(NULL);
basetime = monotonic_time();
if (rtctime == VRTC_BROKEN_TIME) {
if (rtc_flag_broken_time)
return -1;
Expand Down Expand Up @@ -810,7 +821,7 @@ vrtc_set_reg_a(struct vrtc *vrtc, uint8_t newval)
* maintain the illusion that the RTC date/time was frozen
* while the dividers were disabled.
*/
vrtc->base_uptime = time(NULL);
vrtc->base_uptime = monotonic_time();
RTC_DEBUG("RTC divider out of reset at %#lx/%#lx\n",
vrtc->base_rtctime, vrtc->base_uptime);
} else {
Expand Down Expand Up @@ -972,7 +983,7 @@ vrtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port,
*/
if (vrtc_is_time_register(offset) && !rtc_halted(vrtc)) {
curtime = rtc_to_secs(vrtc);
error = vrtc_time_update(vrtc, curtime, time(NULL));
error = vrtc_time_update(vrtc, curtime, monotonic_time());
if ((error != 0) || (curtime == VRTC_BROKEN_TIME && rtc_flag_broken_time))
error = -1;
}
Expand All @@ -989,7 +1000,7 @@ vrtc_set_time(struct vrtc *vrtc, time_t secs)
int error;

pthread_mutex_lock(&vrtc->mtx);
error = vrtc_time_update(vrtc, secs, time(NULL));
error = vrtc_time_update(vrtc, secs, monotonic_time());
pthread_mutex_unlock(&vrtc->mtx);

if (error)
Expand Down Expand Up @@ -1102,7 +1113,7 @@ vrtc_init(struct vmctx *ctx)

pthread_mutex_lock(&vrtc->mtx);
vrtc->base_rtctime = VRTC_BROKEN_TIME;
vrtc_time_update(vrtc, curtime, time(NULL));
vrtc_time_update(vrtc, curtime, monotonic_time());
secs_to_rtc(curtime, vrtc, 0);
pthread_mutex_unlock(&vrtc->mtx);

Expand Down

0 comments on commit d3897c3

Please sign in to comment.