ia64/xen-unstable

changeset 13509:e2539ab3580a

[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 <dexuan.cui@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Jan 18 18:54:28 2007 +0000 (2007-01-18)
parents 16847428f859
children 5633bb2abeaf
files xen/arch/x86/hvm/hpet.c
line diff
     1.1 --- a/xen/arch/x86/hvm/hpet.c	Thu Jan 18 18:40:30 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/hpet.c	Thu Jan 18 18:54:28 2007 +0000
     1.3 @@ -142,9 +142,13 @@ static void hpet_stop_timer(HPETState *h
     1.4      stop_timer(&h->timers[tn]);
     1.5  }
     1.6  
     1.7 +/* the number of HPET tick that stands for
     1.8 + * 1/(2^10) second, namely, 0.9765625 milliseconds */
     1.9 +#define  HPET_TINY_TIME_SPAN  (h->tsc_freq >> 10)
    1.10 +
    1.11  static void hpet_set_timer(HPETState *h, unsigned int tn)
    1.12  {
    1.13 -    uint64_t tn_cmp, cur_tick;
    1.14 +    uint64_t tn_cmp, cur_tick, diff;
    1.15  
    1.16      ASSERT(tn < HPET_TIMER_NUM);
    1.17      
    1.18 @@ -167,11 +171,19 @@ static void hpet_set_timer(HPETState *h,
    1.19          cur_tick = (uint32_t)cur_tick;
    1.20      }
    1.21  
    1.22 -    if ( (int64_t)(tn_cmp - cur_tick) > 0 )
    1.23 -        set_timer(&h->timers[tn], NOW() +
    1.24 -                  hpet_tick_to_ns(h, tn_cmp-cur_tick));
    1.25 -    else
    1.26 -        set_timer(&h->timers[tn], NOW());
    1.27 +    diff = tn_cmp - cur_tick;
    1.28 +
    1.29 +    /*
    1.30 +     * Detect time values set in the past. This is hard to do for 32-bit
    1.31 +     * comparators as the timer does not have to be set that far in the future
    1.32 +     * for the counter difference to wrap a 32-bit signed integer. We fudge
    1.33 +     * by looking for a 'small' time value in the past.
    1.34 +     */
    1.35 +    if ( (int64_t)diff < 0 )
    1.36 +        diff = (timer_is_32bit(h, tn) && (-diff > HPET_TINY_TIME_SPAN))
    1.37 +            ? (uint32_t)diff : 0;
    1.38 +
    1.39 +    set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, diff));
    1.40  }
    1.41  
    1.42  static inline uint64_t hpet_fixup_reg(