# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1197470499 0
# Node ID 03551b644e35dbec62d657e6f943faa5dd310409
# Parent 1caed71f2a357533a569a7fdac7bfb06ca2368a7
[HVM] Don't count "missed ticks" on one-shot timers.
It's not clear what it would mean, and it leads to division by zero.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx>
xen-unstable changeset: 15943:c0d1825f51899b329495efb2078dd15e0fb3b479
xen-unstable date: Mon Sep 24 13:44:29 2007 +0100
hvm: Fix one-shot timers. Do not disable until the interrupt has been
latched by the target VCPU.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
xen-unstable changeset: 16125:b4278beaf3549f410a5a6086dbd8af93c495aeac
xen-unstable date: Wed Oct 17 13:12:03 2007 +0100
hvm: Fix destroy_periodic_time() to not race destruction of one-shot
timers.
This bug was tracked down by Dexuan Cui <dexuan.cui@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset: 16595:f2f7c92bf1c15206aa7072f6a4e470a132d528e2
xen-unstable date: Wed Dec 12 11:08:21 2007 +0000
---
xen/arch/x86/hvm/vioapic.c | 2 +-
xen/arch/x86/hvm/vlapic.c | 13 +++++--------
xen/arch/x86/hvm/vpt.c | 35 ++++++++++++++++++++++++-----------
xen/include/asm-x86/hvm/vpt.h | 17 ++++++++++++++---
4 files changed, 44 insertions(+), 23 deletions(-)
diff -r 1caed71f2a35 -r 03551b644e35 xen/arch/x86/hvm/vioapic.c
--- a/xen/arch/x86/hvm/vioapic.c Wed Dec 12 14:32:10 2007 +0000
+++ b/xen/arch/x86/hvm/vioapic.c Wed Dec 12 14:41:39 2007 +0000
@@ -311,7 +311,7 @@ static inline int pit_channel0_enabled(v
{
PITState *pit = ¤t->domain->arch.hvm_domain.pl_time.vpit;
struct periodic_time *pt = &pit->pt[0];
- return pt->enabled;
+ return pt_active(pt);
}
static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq)
diff -r 1caed71f2a35 -r 03551b644e35 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Wed Dec 12 14:32:10 2007 +0000
+++ b/xen/arch/x86/hvm/vlapic.c Wed Dec 12 14:41:39 2007 +0000
@@ -957,15 +957,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 -r 1caed71f2a35 -r 03551b644e35 xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c Wed Dec 12 14:32:10 2007 +0000
+++ b/xen/arch/x86/hvm/vpt.c Wed Dec 12 14:41:39 2007 +0000
@@ -46,6 +46,9 @@ static void missed_ticks(struct periodic
{
s_time_t missed_ticks;
+ if ( pt->one_shot )
+ return;
+
missed_ticks = NOW() - pt->scheduled;
if ( missed_ticks <= 0 )
return;
@@ -111,12 +114,13 @@ static void pt_timer_fn(void *data)
pt_lock(pt);
pt->pending_intr_nr++;
- pt->scheduled += pt->period;
-
- missed_ticks(pt);
if ( !pt->one_shot )
+ {
+ pt->scheduled += pt->period;
+ missed_ticks(pt);
set_timer(&pt->timer, pt->scheduled);
+ }
vcpu_kick(pt->vcpu);
@@ -201,10 +205,17 @@ void pt_intr_post(struct vcpu *v, int ve
return;
}
- ASSERT(pt->vcpu == v);
-
- pt->pending_intr_nr--;
- pt->last_plt_gtime += pt->period_cycles;
+ if ( pt->one_shot )
+ {
+ if ( pt->on_list )
+ list_del(&pt->list);
+ pt->on_list = 0;
+ }
+ else
+ {
+ pt->pending_intr_nr--;
+ pt->last_plt_gtime += pt->period_cycles;
+ }
if ( hvm_get_guest_time(v) < pt->last_plt_gtime )
hvm_set_guest_time(v, pt->last_plt_gtime);
@@ -257,7 +268,6 @@ void create_periodic_time(
spin_lock(&v->arch.hvm_vcpu.tm_lock);
- pt->enabled = 1;
pt->pending_intr_nr = 0;
/* Periodic timer must be at least 0.9ms. */
@@ -279,6 +289,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);
@@ -289,12 +300,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 -r 1caed71f2a35 -r 03551b644e35 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h Wed Dec 12 14:32:10 2007 +0000
+++ b/xen/include/asm-x86/hvm/vpt.h Wed Dec 12 14:41:39 2007 +0000
@@ -55,11 +55,11 @@ typedef void time_cb(struct vcpu *v, voi
struct periodic_time {
struct list_head list;
- char enabled;
- char one_shot; /* one shot time */
+ bool_t on_list;
+ bool_t one_shot;
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 */
@@ -122,6 +122,17 @@ void pt_intr_post(struct vcpu *v, int ve
void pt_intr_post(struct vcpu *v, int vector, int type);
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);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|