Skip to content

Commit

Permalink
dm: change timers to MONOTONIC mode
Browse files Browse the repository at this point in the history
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: 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 a6611ef commit fe52619
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 12 deletions.
12 changes: 6 additions & 6 deletions devicemodel/hw/platform/hpet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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));
}
}
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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)) ||
Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 4 additions & 4 deletions devicemodel/hw/platform/pit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, <=))
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions devicemodel/hw/platform/rtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit fe52619

Please sign in to comment.