ia64/xen-unstable

changeset 16598:f2f7c92bf1c1

hvm: Fix destroy_periodic_time() to not race destruction of one-shot timers.

This bug was tracked down by Dexuan Cui <dexuan.cui@intel.com>

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Dec 12 11:08:21 2007 +0000 (2007-12-12)
parents 686b75b31f3c
children 514d450ad729
files xen/arch/x86/hvm/vioapic.c xen/arch/x86/hvm/vlapic.c xen/arch/x86/hvm/vpt.c xen/include/asm-x86/hvm/vpt.h
line diff
     1.1 --- a/xen/arch/x86/hvm/vioapic.c	Wed Dec 12 10:40:02 2007 +0000
     1.2 +++ b/xen/arch/x86/hvm/vioapic.c	Wed Dec 12 11:08:21 2007 +0000
     1.3 @@ -300,7 +300,7 @@ static uint32_t ioapic_get_delivery_bitm
     1.4  static inline int pit_channel0_enabled(void)
     1.5  {
     1.6      PITState *pit = &current->domain->arch.hvm_domain.pl_time.vpit;
     1.7 -    return pit->pt0.enabled;
     1.8 +    return pt_active(&pit->pt0);
     1.9  }
    1.10  
    1.11  static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq)
     2.1 --- a/xen/arch/x86/hvm/vlapic.c	Wed Dec 12 10:40:02 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/vlapic.c	Wed Dec 12 11:08:21 2007 +0000
     2.3 @@ -977,15 +977,12 @@ void vlapic_destroy(struct vcpu *v)
     2.4  
     2.5  int is_lvtt(struct vcpu *v, int vector)
     2.6  {
     2.7 -    return vcpu_vlapic(v)->pt.enabled &&
     2.8 -           vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT);
     2.9 +    return (pt_active(&vcpu_vlapic(v)->pt) &&
    2.10 +            (vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT)));
    2.11  }
    2.12  
    2.13  int is_lvtt_enabled(struct vcpu *v)
    2.14  {
    2.15 -    if ( unlikely(!vlapic_enabled(vcpu_vlapic(v))) ||
    2.16 -            !vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT)) 
    2.17 -        return 0;
    2.18 -
    2.19 -    return 1;
    2.20 +    return (vlapic_enabled(vcpu_vlapic(v)) &&
    2.21 +            vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT));
    2.22  }
     3.1 --- a/xen/arch/x86/hvm/vpt.c	Wed Dec 12 10:40:02 2007 +0000
     3.2 +++ b/xen/arch/x86/hvm/vpt.c	Wed Dec 12 11:08:21 2007 +0000
     3.3 @@ -225,8 +225,9 @@ void pt_intr_post(struct vcpu *v, struct
     3.4  
     3.5      if ( pt->one_shot )
     3.6      {
     3.7 -        pt->enabled = 0;
     3.8 -        list_del(&pt->list);
     3.9 +        if ( pt->on_list )
    3.10 +            list_del(&pt->list);
    3.11 +        pt->on_list = 0;
    3.12      }
    3.13      else
    3.14      {
    3.15 @@ -294,7 +295,6 @@ void create_periodic_time(
    3.16  
    3.17      spin_lock(&v->arch.hvm_vcpu.tm_lock);
    3.18  
    3.19 -    pt->enabled = 1;
    3.20      pt->pending_intr_nr = 0;
    3.21      pt->do_not_freeze = 0;
    3.22  
    3.23 @@ -324,6 +324,7 @@ void create_periodic_time(
    3.24      pt->cb = cb;
    3.25      pt->priv = data;
    3.26  
    3.27 +    pt->on_list = 1;
    3.28      list_add(&pt->list, &v->arch.hvm_vcpu.tm_list);
    3.29  
    3.30      init_timer(&pt->timer, pt_timer_fn, pt, v->processor);
    3.31 @@ -334,12 +335,14 @@ void create_periodic_time(
    3.32  
    3.33  void destroy_periodic_time(struct periodic_time *pt)
    3.34  {
    3.35 -    if ( !pt->enabled )
    3.36 +    /* Was this structure previously initialised by create_periodic_time()? */
    3.37 +    if ( pt->vcpu == NULL )
    3.38          return;
    3.39  
    3.40      pt_lock(pt);
    3.41 -    pt->enabled = 0;
    3.42 -    list_del(&pt->list);
    3.43 +    if ( pt->on_list )
    3.44 +        list_del(&pt->list);
    3.45 +    pt->on_list = 0;
    3.46      pt_unlock(pt);
    3.47  
    3.48      /*
     4.1 --- a/xen/include/asm-x86/hvm/vpt.h	Wed Dec 12 10:40:02 2007 +0000
     4.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Wed Dec 12 11:08:21 2007 +0000
     4.3 @@ -72,12 +72,12 @@ typedef void time_cb(struct vcpu *v, voi
     4.4  
     4.5  struct periodic_time {
     4.6      struct list_head list;
     4.7 -    char enabled;
     4.8 -    char one_shot;              /* one shot time */
     4.9 -    char do_not_freeze;
    4.10 +    bool_t on_list;
    4.11 +    bool_t one_shot;
    4.12 +    bool_t do_not_freeze;
    4.13      u8 irq;
    4.14      struct vcpu *vcpu;          /* vcpu timer interrupt delivers to */
    4.15 -    u32 pending_intr_nr;        /* the couner for pending timer interrupts */
    4.16 +    u32 pending_intr_nr;        /* pending timer interrupts */
    4.17      u64 period;                 /* frequency in ns */
    4.18      u64 period_cycles;          /* frequency in cpu cycles */
    4.19      s_time_t scheduled;         /* scheduled timer interrupt */
    4.20 @@ -140,6 +140,17 @@ void pt_update_irq(struct vcpu *v);
    4.21  void pt_intr_post(struct vcpu *v, struct hvm_intack intack);
    4.22  void pt_reset(struct vcpu *v);
    4.23  void pt_migrate(struct vcpu *v);
    4.24 +
    4.25 +/* Is given periodic timer active? */
    4.26 +#define pt_active(pt) ((pt)->on_list)
    4.27 +
    4.28 +/*
    4.29 + * Create/destroy a periodic (or one-shot!) timer.
    4.30 + * The given periodic timer structure must be initialised with zero bytes or
    4.31 + * have been initialised by a previous invocation of create_periodic_time().
    4.32 + * Note that, for a given periodic timer, invocations of these functions MUST
    4.33 + * be serialised.
    4.34 + */
    4.35  void create_periodic_time(
    4.36      struct vcpu *v, struct periodic_time *pt, uint64_t period,
    4.37      uint8_t irq, char one_shot, time_cb *cb, void *data);