aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-01-08 15:55:29 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-01-08 15:55:29 +0000
commit10e3974b14613c687ce84decc019f4e016063caa (patch)
tree943a7e3ee39b49ce881f817f867cf67c1d03eea2
parent926b04bb757d8ca6ecaed077f3247953645630e2 (diff)
downloadxen-10e3974b14613c687ce84decc019f4e016063caa.tar.gz
xen-10e3974b14613c687ce84decc019f4e016063caa.tar.bz2
xen-10e3974b14613c687ce84decc019f4e016063caa.zip
hvm: Fix evtchn-to-fake-pci interrupt propagation.
Previously the evtchn_upcall_pending flag would only ever be sampled on VCPU0, possibly leading to long delays in deasserting the fake-pci-device INTx line if the interrupt is actually delivered to other than VCPU0. Diagnosed by Ian Jackson <ian.jackson@eu.citrix.com> Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/arch/x86/hvm/irq.c32
-rw-r--r--xen/arch/x86/hvm/svm/intr.c2
-rw-r--r--xen/arch/x86/hvm/vmx/intr.c4
-rw-r--r--xen/include/asm-x86/event.h7
-rw-r--r--xen/include/asm-x86/hvm/irq.h3
5 files changed, 29 insertions, 19 deletions
diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c
index dc35eda989..072452a861 100644
--- a/xen/arch/x86/hvm/irq.c
+++ b/xen/arch/x86/hvm/irq.c
@@ -125,17 +125,13 @@ void hvm_isa_irq_deassert(
spin_unlock(&d->arch.hvm_domain.irq_lock);
}
-void hvm_set_callback_irq_level(void)
+static void hvm_set_callback_irq_level(struct vcpu *v)
{
- struct vcpu *v = current;
struct domain *d = v->domain;
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
unsigned int gsi, pdev, pintx, asserted;
- /* Fast lock-free tests. */
- if ( (v->vcpu_id != 0) ||
- (hvm_irq->callback_via_type == HVMIRQ_callback_none) )
- return;
+ ASSERT(v->vcpu_id == 0);
spin_lock(&d->arch.hvm_domain.irq_lock);
@@ -177,6 +173,22 @@ void hvm_set_callback_irq_level(void)
spin_unlock(&d->arch.hvm_domain.irq_lock);
}
+void hvm_maybe_deassert_evtchn_irq(void)
+{
+ struct domain *d = current->domain;
+ struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
+
+ if ( hvm_irq->callback_via_asserted &&
+ !vcpu_info(d->vcpu[0], evtchn_upcall_pending) )
+ hvm_set_callback_irq_level(d->vcpu[0]);
+}
+
+void hvm_assert_evtchn_irq(struct vcpu *v)
+{
+ if ( v->vcpu_id == 0 )
+ hvm_set_callback_irq_level(v);
+}
+
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
{
struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
@@ -349,13 +361,7 @@ struct hvm_intack hvm_vcpu_ack_pending_irq(
int hvm_local_events_need_delivery(struct vcpu *v)
{
- struct hvm_intack intack;
-
- /* TODO: Get rid of event-channel special case. */
- if ( vcpu_info(v, evtchn_upcall_pending) )
- intack = hvm_intack_pic(0);
- else
- intack = hvm_vcpu_has_pending_irq(v);
+ struct hvm_intack intack = hvm_vcpu_has_pending_irq(v);
if ( likely(intack.source == hvm_intsrc_none) )
return 0;
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index 268f900459..08bc897543 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -102,7 +102,7 @@ asmlinkage void svm_intr_assist(void)
/* Crank the handle on interrupt state. */
pt_update_irq(v);
- hvm_set_callback_irq_level();
+ hvm_maybe_deassert_evtchn_irq();
do {
intack = hvm_vcpu_has_pending_irq(v);
diff --git a/xen/arch/x86/hvm/vmx/intr.c b/xen/arch/x86/hvm/vmx/intr.c
index 9476155f2a..a4eb205392 100644
--- a/xen/arch/x86/hvm/vmx/intr.c
+++ b/xen/arch/x86/hvm/vmx/intr.c
@@ -156,10 +156,8 @@ asmlinkage void vmx_intr_assist(void)
/* Crank the handle on interrupt state. */
pt_update_irq(v);
-
vmx_dirq_assist(v);
-
- hvm_set_callback_irq_level();
+ hvm_maybe_deassert_evtchn_irq();
do {
intack = hvm_vcpu_has_pending_irq(v);
diff --git a/xen/include/asm-x86/event.h b/xen/include/asm-x86/event.h
index 05671f7ef3..6b1bf6a52d 100644
--- a/xen/include/asm-x86/event.h
+++ b/xen/include/asm-x86/event.h
@@ -30,7 +30,12 @@ static inline void vcpu_kick(struct vcpu *v)
static inline void vcpu_mark_events_pending(struct vcpu *v)
{
- if ( !test_and_set_bit(0, &vcpu_info(v, evtchn_upcall_pending)) )
+ if ( test_and_set_bit(0, &vcpu_info(v, evtchn_upcall_pending)) )
+ return;
+
+ if ( is_hvm_vcpu(v) )
+ hvm_assert_evtchn_irq(v);
+ else
vcpu_kick(v);
}
diff --git a/xen/include/asm-x86/hvm/irq.h b/xen/include/asm-x86/hvm/irq.h
index 5fd0db3b7d..355928d3ba 100644
--- a/xen/include/asm-x86/hvm/irq.h
+++ b/xen/include/asm-x86/hvm/irq.h
@@ -152,7 +152,8 @@ void hvm_isa_irq_deassert(
void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
-void hvm_set_callback_irq_level(void);
+void hvm_maybe_deassert_evtchn_irq(void);
+void hvm_assert_evtchn_irq(struct vcpu *v);
void hvm_set_callback_via(struct domain *d, uint64_t via);
/* Check/Acknowledge next pending interrupt. */