aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-12-12 11:08:21 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-12-12 11:08:21 +0000
commit73f67c0d9a0a3dff0fe27e977706492316126a1e (patch)
treee8b4b68fc318471f7721edd62de4b8ecf0b61f4c
parentba25075759a192b3ec87ece653801af25f2ebee1 (diff)
downloadxen-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.c2
-rw-r--r--xen/arch/x86/hvm/vlapic.c11
-rw-r--r--xen/arch/x86/hvm/vpt.c15
-rw-r--r--xen/include/asm-x86/hvm/vpt.h19
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 = &current->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);