diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2007-12-12 11:08:21 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2007-12-12 11:08:21 +0000 |
commit | 73f67c0d9a0a3dff0fe27e977706492316126a1e (patch) | |
tree | e8b4b68fc318471f7721edd62de4b8ecf0b61f4c | |
parent | ba25075759a192b3ec87ece653801af25f2ebee1 (diff) | |
download | xen-73f67c0d9a0a3dff0fe27e977706492316126a1e.tar.gz xen-73f67c0d9a0a3dff0fe27e977706492316126a1e.tar.bz2 xen-73f67c0d9a0a3dff0fe27e977706492316126a1e.zip |
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>
-rw-r--r-- | xen/arch/x86/hvm/vioapic.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vlapic.c | 11 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vpt.c | 15 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/vpt.h | 19 |
4 files changed, 29 insertions, 18 deletions
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 670cdf5979..cfc80c5aa1 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -300,7 +300,7 @@ static uint32_t ioapic_get_delivery_bitmask( static inline int pit_channel0_enabled(void) { PITState *pit = ¤t->domain->arch.hvm_domain.pl_time.vpit; - return pit->pt0.enabled; + return pt_active(&pit->pt0); } static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq) diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 5ac455b1fe..2bf3745c8b 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -977,15 +977,12 @@ void vlapic_destroy(struct vcpu *v) int is_lvtt(struct vcpu *v, int vector) { - return vcpu_vlapic(v)->pt.enabled && - vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT); + return (pt_active(&vcpu_vlapic(v)->pt) && + (vector == vlapic_lvt_vector(vcpu_vlapic(v), APIC_LVTT))); } int is_lvtt_enabled(struct vcpu *v) { - if ( unlikely(!vlapic_enabled(vcpu_vlapic(v))) || - !vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT)) - return 0; - - return 1; + return (vlapic_enabled(vcpu_vlapic(v)) && + vlapic_lvt_enabled(vcpu_vlapic(v), APIC_LVTT)); } diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c index 0a780298b8..d4bc8690c8 100644 --- a/xen/arch/x86/hvm/vpt.c +++ b/xen/arch/x86/hvm/vpt.c @@ -225,8 +225,9 @@ void pt_intr_post(struct vcpu *v, struct hvm_intack intack) if ( pt->one_shot ) { - pt->enabled = 0; - list_del(&pt->list); + if ( pt->on_list ) + list_del(&pt->list); + pt->on_list = 0; } else { @@ -294,7 +295,6 @@ void create_periodic_time( spin_lock(&v->arch.hvm_vcpu.tm_lock); - pt->enabled = 1; pt->pending_intr_nr = 0; pt->do_not_freeze = 0; @@ -324,6 +324,7 @@ void create_periodic_time( pt->cb = cb; pt->priv = data; + pt->on_list = 1; list_add(&pt->list, &v->arch.hvm_vcpu.tm_list); init_timer(&pt->timer, pt_timer_fn, pt, v->processor); @@ -334,12 +335,14 @@ void create_periodic_time( void destroy_periodic_time(struct periodic_time *pt) { - if ( !pt->enabled ) + /* Was this structure previously initialised by create_periodic_time()? */ + if ( pt->vcpu == NULL ) return; pt_lock(pt); - pt->enabled = 0; - list_del(&pt->list); + if ( pt->on_list ) + list_del(&pt->list); + pt->on_list = 0; pt_unlock(pt); /* diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h index 9f69024340..0831d37dcc 100644 --- a/xen/include/asm-x86/hvm/vpt.h +++ b/xen/include/asm-x86/hvm/vpt.h @@ -72,12 +72,12 @@ typedef void time_cb(struct vcpu *v, void *opaque); struct periodic_time { struct list_head list; - char enabled; - char one_shot; /* one shot time */ - char do_not_freeze; + bool_t on_list; + bool_t one_shot; + bool_t do_not_freeze; u8 irq; struct vcpu *vcpu; /* vcpu timer interrupt delivers to */ - u32 pending_intr_nr; /* the couner for pending timer interrupts */ + u32 pending_intr_nr; /* pending timer interrupts */ u64 period; /* frequency in ns */ u64 period_cycles; /* frequency in cpu cycles */ s_time_t scheduled; /* scheduled timer interrupt */ @@ -140,6 +140,17 @@ void pt_update_irq(struct vcpu *v); void pt_intr_post(struct vcpu *v, struct hvm_intack intack); void pt_reset(struct vcpu *v); void pt_migrate(struct vcpu *v); + +/* Is given periodic timer active? */ +#define pt_active(pt) ((pt)->on_list) + +/* + * Create/destroy a periodic (or one-shot!) timer. + * The given periodic timer structure must be initialised with zero bytes or + * have been initialised by a previous invocation of create_periodic_time(). + * Note that, for a given periodic timer, invocations of these functions MUST + * be serialised. + */ void create_periodic_time( struct vcpu *v, struct periodic_time *pt, uint64_t period, uint8_t irq, char one_shot, time_cb *cb, void *data); |