direct-io.hg

changeset 15285:b4c16658ca30

hvm: Fix multiplication overflow in hvm/pmtimer.c

Too many ACPI events (SCI) are raised on hvm because of
multiplication overflow.

FREQUENCE_PMTIMER=3579545
(1000000000ULL << 32) / FREQUENCE_PMTIMER = 0xae9a7b1663a
pmt_cycles_until_flip =~ 0x80000000
0xae9a7b1663a*0x80000000 = overflow!!!

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
author Keir Fraser <keir@xensource.com>
date Fri Jun 15 09:42:39 2007 +0100 (2007-06-15)
parents 276b48771f1e
children 9a915873be8c
files xen/arch/x86/hvm/pmtimer.c
line diff
     1.1 --- a/xen/arch/x86/hvm/pmtimer.c	Fri Jun 15 09:32:22 2007 +0100
     1.2 +++ b/xen/arch/x86/hvm/pmtimer.c	Fri Jun 15 09:42:39 2007 +0100
     1.3 @@ -50,7 +50,6 @@
     1.4  #define TMR_VAL_MASK  (0xffffffff)
     1.5  #define TMR_VAL_MSB   (0x80000000)
     1.6  
     1.7 -
     1.8  /* Dispatch SCIs based on the PM1a_STS and PM1a_EN registers */
     1.9  static void pmt_update_sci(PMTState *s)
    1.10  {
    1.11 @@ -89,19 +88,19 @@ static void pmt_timer_callback(void *opa
    1.12      PMTState *s = opaque;
    1.13      uint32_t pmt_cycles_until_flip;
    1.14      uint64_t time_until_flip;
    1.15 -    
    1.16 +
    1.17      /* Recalculate the timer and make sure we get an SCI if we need one */
    1.18      pmt_update_time(s);
    1.19 -    
    1.20 +
    1.21      /* How close are we to the next MSB flip? */
    1.22      pmt_cycles_until_flip = TMR_VAL_MSB - (s->pm.tmr_val & (TMR_VAL_MSB - 1));
    1.23 -    
    1.24 +
    1.25      /* Overall time between MSB flips */
    1.26 -    time_until_flip = (1000000000ULL << 31) / FREQUENCE_PMTIMER;
    1.27 -    
    1.28 +    time_until_flip = (1000000000ULL << 23) / FREQUENCE_PMTIMER;
    1.29 +
    1.30      /* Reduced appropriately */
    1.31 -    time_until_flip = (time_until_flip * pmt_cycles_until_flip) / (1ULL<<31);
    1.32 -    
    1.33 +    time_until_flip = (time_until_flip * pmt_cycles_until_flip) >> 23;
    1.34 +
    1.35      /* Wake up again near the next bit-flip */
    1.36      set_timer(&s->timer, NOW() + time_until_flip + MILLISECS(1));
    1.37  }