From: kfraser@localhost.localdomain Date: Thu, 18 Jan 2007 18:54:28 +0000 (+0000) Subject: [HVM] Fix slow wallclock in x64 Vista. This is due to confusing a X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15371^2~133^2~6 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=f545359b1c54f59be9d7c27112a68c51c45b06b5;p=xen.git [HVM] Fix slow wallclock in x64 Vista. This is due to confusing a timeout in the past vs. a timeout in the future when looking at a 32-bit HPET comparator. Signed-off-by: Dexuan Cui Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c index 5d8ec92150..e86df4e735 100644 --- a/xen/arch/x86/hvm/hpet.c +++ b/xen/arch/x86/hvm/hpet.c @@ -142,9 +142,13 @@ static void hpet_stop_timer(HPETState *h, unsigned int tn) stop_timer(&h->timers[tn]); } +/* the number of HPET tick that stands for + * 1/(2^10) second, namely, 0.9765625 milliseconds */ +#define HPET_TINY_TIME_SPAN (h->tsc_freq >> 10) + static void hpet_set_timer(HPETState *h, unsigned int tn) { - uint64_t tn_cmp, cur_tick; + uint64_t tn_cmp, cur_tick, diff; ASSERT(tn < HPET_TIMER_NUM); @@ -167,11 +171,19 @@ static void hpet_set_timer(HPETState *h, unsigned int tn) cur_tick = (uint32_t)cur_tick; } - if ( (int64_t)(tn_cmp - cur_tick) > 0 ) - set_timer(&h->timers[tn], NOW() + - hpet_tick_to_ns(h, tn_cmp-cur_tick)); - else - set_timer(&h->timers[tn], NOW()); + diff = tn_cmp - cur_tick; + + /* + * Detect time values set in the past. This is hard to do for 32-bit + * comparators as the timer does not have to be set that far in the future + * for the counter difference to wrap a 32-bit signed integer. We fudge + * by looking for a 'small' time value in the past. + */ + if ( (int64_t)diff < 0 ) + diff = (timer_is_32bit(h, tn) && (-diff > HPET_TINY_TIME_SPAN)) + ? (uint32_t)diff : 0; + + set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, diff)); } static inline uint64_t hpet_fixup_reg(