diff -u b/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c --- b/xen/arch/x86/hvm/hpet.c Thu Jan 03 20:10:52 2008 +0800 +++ b/xen/arch/x86/hvm/hpet.c Thu Jan 03 20:14:17 2008 +0800 @@ -71,8 +71,8 @@ #define HPET_TN_INT_ROUTE_CAP_MASK (0xffffffffULL \ << HPET_TN_INT_ROUTE_CAP_SHIFT) -#define hpet_tick_to_ns(h, tick) ((s_time_t)(tick)* \ - (S_TO_NS*TSC_PER_HPET_TICK)/h->tsc_freq) +#define hpet_tick_to_ns(h, tick) ((s_time_t)((((tick) > (h)->hpet_limit)? \ + (h)->hpet_limit : (tick)*(h)->hpet_scale) >> 10)) #define timer_config(h, n) (h->hpet.timers[n].config) #define timer_int_enabled(h, n) (timer_config(h, n) & HPET_TN_ENABLE) @@ -219,9 +219,10 @@ * 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; + if ( tn_cmp < cur_tick && -diff < HPET_TINY_TIME_SPAN ) + diff = 0; + if ( timer_is_32bit(h, tn) ) + diff = (uint32_t)diff; set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, diff)); } @@ -537,6 +538,9 @@ h->vcpu = v; h->tsc_freq = ticks_per_sec(v); + + h->hpet_scale = ((S_TO_NS*TSC_PER_HPET_TICK) << 10)/h->tsc_freq; + h->hpet_limit = (~0ULL >> 1)/h->hpet_scale; /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */ h->hpet.capability = 0x8086A201ULL; only in patch2: unchanged: --- a/xen/include/asm-x86/hvm/vpt.h Sat Dec 29 17:57:47 2007 +0000 +++ b/xen/include/asm-x86/hvm/vpt.h Thu Jan 03 20:14:17 2008 +0800 @@ -58,6 +58,8 @@ typedef struct HPETState { struct hpet_registers hpet; struct vcpu *vcpu; uint64_t tsc_freq; + uint64_t hpet_scale; //hpet tick to ns scale + uint64_t hpet_limit; //largest ticks converted to ns without overflow uint64_t mc_offset; struct timer timers[HPET_TIMER_NUM]; struct HPET_timer_fn_info timer_fn_info[HPET_TIMER_NUM];