ia64/xen-unstable

changeset 16697:1b2be7cf0b7b

hvm: hpet: Clamp period to sane values to prevent excessive looping in
hpet_timer_fn(), or excessive numbers of set_timer() callbacks.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jan 09 10:32:13 2008 +0000 (2008-01-09)
parents b5b3e27f1af3
children f983aa8e4b26
files xen/arch/x86/hvm/hpet.c
line diff
     1.1 --- a/xen/arch/x86/hvm/hpet.c	Wed Jan 09 10:11:31 2008 +0000
     1.2 +++ b/xen/arch/x86/hvm/hpet.c	Wed Jan 09 10:32:13 2008 +0000
     1.3 @@ -303,7 +303,10 @@ static void hpet_write(
     1.4          }
     1.5  
     1.6          if ( new_val & HPET_TN_32BIT )
     1.7 +        {
     1.8              h->hpet.timers[tn].cmp = (uint32_t)h->hpet.timers[tn].cmp;
     1.9 +            h->hpet.period[tn] = (uint32_t)h->hpet.period[tn];
    1.10 +        }
    1.11  
    1.12          break;
    1.13  
    1.14 @@ -317,7 +320,17 @@ static void hpet_write(
    1.15               (h->hpet.timers[tn].config & HPET_TN_SETVAL) )
    1.16              h->hpet.timers[tn].cmp = new_val;
    1.17          else
    1.18 +        {
    1.19 +            /*
    1.20 +             * Clamp period to reasonable min/max values:
    1.21 +             *  - minimum is 900us, same as timers controlled by vpt.c
    1.22 +             *  - maximum is to prevent overflow in time_after() calculations
    1.23 +             */
    1.24 +            if ( hpet_tick_to_ns(h, new_val) < MICROSECS(900) )
    1.25 +                new_val = (MICROSECS(900) << 10) / h->hpet_to_ns_scale;
    1.26 +            new_val &= (timer_is_32bit(h, tn) ? ~0u : ~0ull) >> 1;
    1.27              h->hpet.period[tn] = new_val;
    1.28 +        }
    1.29          h->hpet.timers[tn].config &= ~HPET_TN_SETVAL;
    1.30          if ( hpet_enabled(h) )
    1.31              hpet_set_timer(h, tn);
    1.32 @@ -376,7 +389,7 @@ static void hpet_route_interrupt(HPETSta
    1.33          return;
    1.34      }
    1.35  
    1.36 -    /* We only support edge-triggered interrupt now  */
    1.37 +    /* We support only edge-triggered interrupt. */
    1.38      spin_lock(&d->arch.hvm_domain.irq_lock);
    1.39      vioapic_irq_positive_edge(d, tn_int_route);
    1.40      spin_unlock(&d->arch.hvm_domain.irq_lock);
    1.41 @@ -401,20 +414,19 @@ static void hpet_timer_fn(void *opaque)
    1.42  
    1.43      if ( timer_is_periodic(h, tn) && (h->hpet.period[tn] != 0) )
    1.44      {
    1.45 -        uint64_t mc = hpet_read_maincounter(h);
    1.46 +        uint64_t mc = hpet_read_maincounter(h), period = h->hpet.period[tn];
    1.47          if ( timer_is_32bit(h, tn) )
    1.48          {
    1.49              while ( hpet_time_after(mc, h->hpet.timers[tn].cmp) )
    1.50                  h->hpet.timers[tn].cmp = (uint32_t)(
    1.51 -                    h->hpet.timers[tn].cmp + h->hpet.period[tn]);
    1.52 +                    h->hpet.timers[tn].cmp + period);
    1.53          }
    1.54          else
    1.55          {
    1.56              while ( hpet_time_after64(mc, h->hpet.timers[tn].cmp) )
    1.57 -                h->hpet.timers[tn].cmp += h->hpet.period[tn];
    1.58 +                h->hpet.timers[tn].cmp += period;
    1.59          }
    1.60 -        set_timer(&h->timers[tn], 
    1.61 -                  NOW() + hpet_tick_to_ns(h, h->hpet.period[tn]));
    1.62 +        set_timer(&h->timers[tn], NOW() + hpet_tick_to_ns(h, period));
    1.63      }
    1.64  
    1.65      spin_unlock(&h->lock);