From 1407dd3738fe987b17b31e7f593382c8164228de Mon Sep 17 00:00:00 2001 From: Wu Zhou Date: Mon, 31 Jul 2023 00:35:55 -0700 Subject: [PATCH] dm: change timers to MONOTONIC mode Some DM's virtual timer devices use CLOCK_REALTIME as either clock counter source or period timer source. Including: - virtual RTC - virtual PIT - virtual HPET According to Linux Manual, CLOCK_REALTIME is the 'wall clock' which is affected by discontinuous jumps in the system time. The issue is that service VM system time could be changed, either by root user manually or by NTP automatically calibration. When that happens, DM's virtual timer devices which relays on CLOCK_REALTIME will experience discontinuous time jump, and become inaccurate. It would affect both time stamp read value and period timer. Especially when service VM system time is moved backwards, WaaG's system software will lost response and be stalled for quite a long time. To solve this issue, we need to switch CLOCK_REALTIME to CLOCK_MONOTONIC. As it represents: 'A nonsettable monotonically increasing clock that measures time from some unspecified point in the past that does not change after system startup' Tracked-On: #8547 Signed-off-by: Wu Zhou Reviewed-by: Jian Jun Chen --- devicemodel/hw/platform/hpet.c | 12 ++++++------ devicemodel/hw/platform/pit.c | 8 ++++---- devicemodel/hw/platform/rtc.c | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/devicemodel/hw/platform/hpet.c b/devicemodel/hw/platform/hpet.c index 72f4bac13..9d465a37c 100644 --- a/devicemodel/hw/platform/hpet.c +++ b/devicemodel/hw/platform/hpet.c @@ -202,7 +202,7 @@ vhpet_counter(struct vhpet *vhpet, struct timespec *nowptr) val = vhpet->countbase; if (vhpet_counter_enabled(vhpet)) { - if (clock_gettime(CLOCK_REALTIME, &now)) + if (clock_gettime(CLOCK_MONOTONIC, &now)) pr_dbg("clock_gettime returned: %s", strerror(errno)); /* delta = now - countbase_ts */ @@ -225,7 +225,7 @@ vhpet_counter(struct vhpet *vhpet, struct timespec *nowptr) */ if (nowptr) { pr_warn("vhpet unexpected nowptr"); - if (clock_gettime(CLOCK_REALTIME, nowptr)) + if (clock_gettime(CLOCK_MONOTONIC, nowptr)) pr_dbg("clock_gettime returned: %s", strerror(errno)); } } @@ -366,7 +366,7 @@ vhpet_timer_handler(void *a, uint64_t nexp) vhpet_timer_interrupt(vhpet, n); - if (clock_gettime(CLOCK_REALTIME, &now)) + if (clock_gettime(CLOCK_MONOTONIC, &now)) pr_dbg("clock_gettime returned: %s", strerror(errno)); if (acrn_timer_gettime(vhpet_tmr(vhpet, n), &tmrts)) @@ -548,7 +548,7 @@ vhpet_start_counting(struct vhpet *vhpet) { int i; - if (clock_gettime(CLOCK_REALTIME, &vhpet->countbase_ts)) + if (clock_gettime(CLOCK_MONOTONIC, &vhpet->countbase_ts)) pr_dbg("clock_gettime returned: %s", strerror(errno)); /* Restart the timers based on the main counter base value */ @@ -639,7 +639,7 @@ vhpet_timer_update_config(struct vhpet *vhpet, int n, uint64_t data, * - Timer remains in periodic mode */ if (!vhpet_timer_enabled(vhpet, n)) { - if (clock_gettime(CLOCK_REALTIME, &now)) + if (clock_gettime(CLOCK_MONOTONIC, &now)) pr_dbg("clock_gettime returned: %s", strerror(errno)); vhpet_stop_timer(vhpet, n, &now, true); } else if (!(oldval & (HPET_TCNF_TYPE | HPET_TCNF_INT_ENB)) || @@ -998,7 +998,7 @@ vhpet_init(struct vmctx *ctx) arg->timer_num = i; tmr = &vhpet->timer[i].tmrlst[j].t; - tmr->clockid = CLOCK_REALTIME; + tmr->clockid = CLOCK_MONOTONIC; error = acrn_timer_init(tmr, vhpet_timer_handler, arg); if (error) { diff --git a/devicemodel/hw/platform/pit.c b/devicemodel/hw/platform/pit.c index f673f4734..a3695e842 100644 --- a/devicemodel/hw/platform/pit.c +++ b/devicemodel/hw/platform/pit.c @@ -107,7 +107,7 @@ ticks_elapsed_since(const struct timespec *since) { struct timespec ts; - if (clock_gettime(CLOCK_REALTIME, &ts)) + if (clock_gettime(CLOCK_MONOTONIC, &ts)) pr_dbg("clock_gettime returned: %s", strerror(errno)); if (timespeccmp(&ts, since, <=)) @@ -192,7 +192,7 @@ pit_load_ce(struct channel *c) c->nullcnt = false; c->crbyte = 0; - if (clock_gettime(CLOCK_REALTIME, &c->start_ts)) + if (clock_gettime(CLOCK_MONOTONIC, &c->start_ts)) pr_dbg("clock_gettime returned: %s", strerror(errno)); if (c->initial == 0 || c->initial > 0x10000) { @@ -330,7 +330,7 @@ pit_timer_start_cntr0(struct vpit *vpit) sigevt.sigev_notify = SIGEV_THREAD; sigevt.sigev_notify_function = vpit_timer_handler; - if (timer_create(CLOCK_REALTIME, &sigevt, &c->timer_id)) + if (timer_create(CLOCK_MONOTONIC, &sigevt, &c->timer_id)) pr_dbg("timer_create returned: %s", strerror(errno)); vpit_timer_arg[c->timer_idx].active = true; @@ -360,7 +360,7 @@ pit_update_counter(struct vpit *vpit, struct channel *c, bool latch, c->initial = PIT_HZ_TO_TICKS(100); delta_ticks = 0; - if (clock_gettime(CLOCK_REALTIME, &c->start_ts)) + if (clock_gettime(CLOCK_MONOTONIC, &c->start_ts)) pr_dbg("clock_gettime returned: %s", strerror(errno)); } else delta_ticks = ticks_elapsed_since(&c->start_ts); diff --git a/devicemodel/hw/platform/rtc.c b/devicemodel/hw/platform/rtc.c index 82de9b7fb..3ca75a7e5 100644 --- a/devicemodel/hw/platform/rtc.c +++ b/devicemodel/hw/platform/rtc.c @@ -1148,11 +1148,11 @@ vrtc_init(struct vmctx *ctx) pthread_mutex_unlock(&vrtc->mtx); /* init periodic interrupt timer */ - vrtc->periodic_timer.clockid = CLOCK_REALTIME; + vrtc->periodic_timer.clockid = CLOCK_MONOTONIC; acrn_timer_init(&vrtc->periodic_timer, vrtc_periodic_timer, vrtc); /* init update interrupt timer(1s)*/ - vrtc->update_timer.clockid = CLOCK_REALTIME; + vrtc->update_timer.clockid = CLOCK_MONOTONIC; acrn_timer_init(&vrtc->update_timer, vrtc_update_timer, vrtc); vrtc_start_timer(&vrtc->update_timer, 1, 0);