ia64/xen-unstable

changeset 16692:9865d5e82802

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>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Jan 08 15:55:29 2008 +0000 (2008-01-08)
parents 1ffa3c1335a4
children 9ff64d045e61
files xen/arch/x86/hvm/irq.c xen/arch/x86/hvm/svm/intr.c xen/arch/x86/hvm/vmx/intr.c xen/include/asm-x86/event.h xen/include/asm-x86/hvm/irq.h
line diff
     1.1 --- a/xen/arch/x86/hvm/irq.c	Tue Jan 08 14:35:18 2008 +0000
     1.2 +++ b/xen/arch/x86/hvm/irq.c	Tue Jan 08 15:55:29 2008 +0000
     1.3 @@ -125,17 +125,13 @@ void hvm_isa_irq_deassert(
     1.4      spin_unlock(&d->arch.hvm_domain.irq_lock);
     1.5  }
     1.6  
     1.7 -void hvm_set_callback_irq_level(void)
     1.8 +static void hvm_set_callback_irq_level(struct vcpu *v)
     1.9  {
    1.10 -    struct vcpu *v = current;
    1.11      struct domain *d = v->domain;
    1.12      struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.13      unsigned int gsi, pdev, pintx, asserted;
    1.14  
    1.15 -    /* Fast lock-free tests. */
    1.16 -    if ( (v->vcpu_id != 0) ||
    1.17 -         (hvm_irq->callback_via_type == HVMIRQ_callback_none) )
    1.18 -        return;
    1.19 +    ASSERT(v->vcpu_id == 0);
    1.20  
    1.21      spin_lock(&d->arch.hvm_domain.irq_lock);
    1.22  
    1.23 @@ -177,6 +173,22 @@ void hvm_set_callback_irq_level(void)
    1.24      spin_unlock(&d->arch.hvm_domain.irq_lock);
    1.25  }
    1.26  
    1.27 +void hvm_maybe_deassert_evtchn_irq(void)
    1.28 +{
    1.29 +    struct domain *d = current->domain;
    1.30 +    struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.31 +
    1.32 +    if ( hvm_irq->callback_via_asserted &&
    1.33 +         !vcpu_info(d->vcpu[0], evtchn_upcall_pending) )
    1.34 +        hvm_set_callback_irq_level(d->vcpu[0]);
    1.35 +}
    1.36 +
    1.37 +void hvm_assert_evtchn_irq(struct vcpu *v)
    1.38 +{
    1.39 +    if ( v->vcpu_id == 0 )
    1.40 +        hvm_set_callback_irq_level(v);
    1.41 +}
    1.42 +
    1.43  void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
    1.44  {
    1.45      struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
    1.46 @@ -349,13 +361,7 @@ struct hvm_intack hvm_vcpu_ack_pending_i
    1.47  
    1.48  int hvm_local_events_need_delivery(struct vcpu *v)
    1.49  {
    1.50 -    struct hvm_intack intack;
    1.51 -
    1.52 -    /* TODO: Get rid of event-channel special case. */
    1.53 -    if ( vcpu_info(v, evtchn_upcall_pending) )
    1.54 -        intack = hvm_intack_pic(0);
    1.55 -    else
    1.56 -        intack = hvm_vcpu_has_pending_irq(v);
    1.57 +    struct hvm_intack intack = hvm_vcpu_has_pending_irq(v);
    1.58  
    1.59      if ( likely(intack.source == hvm_intsrc_none) )
    1.60          return 0;
     2.1 --- a/xen/arch/x86/hvm/svm/intr.c	Tue Jan 08 14:35:18 2008 +0000
     2.2 +++ b/xen/arch/x86/hvm/svm/intr.c	Tue Jan 08 15:55:29 2008 +0000
     2.3 @@ -102,7 +102,7 @@ asmlinkage void svm_intr_assist(void)
     2.4  
     2.5      /* Crank the handle on interrupt state. */
     2.6      pt_update_irq(v);
     2.7 -    hvm_set_callback_irq_level();
     2.8 +    hvm_maybe_deassert_evtchn_irq();
     2.9  
    2.10      do {
    2.11          intack = hvm_vcpu_has_pending_irq(v);
     3.1 --- a/xen/arch/x86/hvm/vmx/intr.c	Tue Jan 08 14:35:18 2008 +0000
     3.2 +++ b/xen/arch/x86/hvm/vmx/intr.c	Tue Jan 08 15:55:29 2008 +0000
     3.3 @@ -156,10 +156,8 @@ asmlinkage void vmx_intr_assist(void)
     3.4  
     3.5      /* Crank the handle on interrupt state. */
     3.6      pt_update_irq(v);
     3.7 -
     3.8      vmx_dirq_assist(v);
     3.9 -  
    3.10 -    hvm_set_callback_irq_level();
    3.11 +    hvm_maybe_deassert_evtchn_irq();
    3.12  
    3.13      do {
    3.14          intack = hvm_vcpu_has_pending_irq(v);
     4.1 --- a/xen/include/asm-x86/event.h	Tue Jan 08 14:35:18 2008 +0000
     4.2 +++ b/xen/include/asm-x86/event.h	Tue Jan 08 15:55:29 2008 +0000
     4.3 @@ -30,7 +30,12 @@ static inline void vcpu_kick(struct vcpu
     4.4  
     4.5  static inline void vcpu_mark_events_pending(struct vcpu *v)
     4.6  {
     4.7 -    if ( !test_and_set_bit(0, &vcpu_info(v, evtchn_upcall_pending)) )
     4.8 +    if ( test_and_set_bit(0, &vcpu_info(v, evtchn_upcall_pending)) )
     4.9 +        return;
    4.10 +
    4.11 +    if ( is_hvm_vcpu(v) )
    4.12 +        hvm_assert_evtchn_irq(v);
    4.13 +    else
    4.14          vcpu_kick(v);
    4.15  }
    4.16  
     5.1 --- a/xen/include/asm-x86/hvm/irq.h	Tue Jan 08 14:35:18 2008 +0000
     5.2 +++ b/xen/include/asm-x86/hvm/irq.h	Tue Jan 08 15:55:29 2008 +0000
     5.3 @@ -152,7 +152,8 @@ void hvm_isa_irq_deassert(
     5.4  
     5.5  void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq);
     5.6  
     5.7 -void hvm_set_callback_irq_level(void);
     5.8 +void hvm_maybe_deassert_evtchn_irq(void);
     5.9 +void hvm_assert_evtchn_irq(struct vcpu *v);
    5.10  void hvm_set_callback_via(struct domain *d, uint64_t via);
    5.11  
    5.12  /* Check/Acknowledge next pending interrupt. */