diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-01-08 15:55:29 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-01-08 15:55:29 +0000 |
commit | 10e3974b14613c687ce84decc019f4e016063caa (patch) | |
tree | 943a7e3ee39b49ce881f817f867cf67c1d03eea2 | |
parent | 926b04bb757d8ca6ecaed077f3247953645630e2 (diff) | |
download | xen-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.c | 32 | ||||
-rw-r--r-- | xen/arch/x86/hvm/svm/intr.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/intr.c | 4 | ||||
-rw-r--r-- | xen/include/asm-x86/event.h | 7 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/irq.h | 3 |
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. */ |