xen: fix hvm_domain_use_pirq's behavior
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>
Wed, 31 Aug 2011 14:23:12 +0000 (15:23 +0100)
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>
Wed, 31 Aug 2011 14:23:12 +0000 (15:23 +0100)
hvm_domain_use_pirq should return true when the guest is using a
certain pirq, no matter if the corresponding event channel is
currently enabled or disabled.  As an additional complication, qemu is
going to request pirqs for passthrough devices even for Xen unaware
HVM guests, so we need to wait for an event channel to be connected
before considering the pirq of a passthrough device as "in use".

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
xen/arch/x86/irq.c
xen/arch/x86/physdev.c
xen/common/event_channel.c

index 267b96faffada5d32e9682abea2252e7247e6603..4d0c590687297d102c6c2ed038d3634eedf31624 100644 (file)
@@ -2027,6 +2027,5 @@ int unmap_domain_pirq_emuirq(struct domain *d, int pirq)
 bool_t hvm_domain_use_pirq(const struct domain *d, const struct pirq *pirq)
 {
     return is_hvm_domain(d) && pirq &&
-           pirq->arch.hvm.emuirq != IRQ_UNBOUND &&
-           pirq->evtchn != 0;
+           pirq->arch.hvm.emuirq != IRQ_UNBOUND; 
 }
index 35fbbeb348b727a180e7be8cc8eabb4c7856468b..d51f4a081f00fe838dc29a336e95ed7f085ac8a6 100644 (file)
@@ -196,9 +196,6 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p,
     if ( ret == 0 )
         *pirq_p = pirq;
 
-    if ( !ret && is_hvm_domain(d) )
-        map_domain_emuirq_pirq(d, pirq, IRQ_PT);
-
  done:
     spin_unlock(&d->event_lock);
     spin_unlock(&pcidevs_lock);
@@ -271,7 +268,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
              v->domain->arch.pv_domain.pirq_eoi_map )
             evtchn_unmask(pirq->evtchn);
         if ( !is_hvm_domain(v->domain) ||
-             pirq->arch.hvm.emuirq == IRQ_PT )
+             domain_pirq_to_irq(v->domain, eoi.irq) > 0 )
             pirq_guest_eoi(pirq);
         spin_unlock(&v->domain->event_lock);
         ret = 0;
@@ -331,7 +328,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
             break;
         irq_status_query.flags = 0;
         if ( is_hvm_domain(v->domain) &&
-             domain_pirq_to_emuirq(v->domain, irq) != IRQ_PT )
+             domain_pirq_to_irq(v->domain, irq) <= 0 )
         {
             ret = copy_to_guest(arg, &irq_status_query, 1) ? -EFAULT : 0;
             break;
index 631bbede221166f41914b08cfc00db05c9af8abb..0628120c24759a925b22c7434b8b714bce3ade80 100644 (file)
@@ -366,6 +366,9 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
 
     bind->port = port;
 
+    if ( is_hvm_domain(d) && domain_pirq_to_irq(d, pirq) > 0 )
+        map_domain_emuirq_pirq(d, pirq, IRQ_PT);
+
  out:
     spin_unlock(&d->event_lock);
 
@@ -419,6 +422,8 @@ static long __evtchn_close(struct domain *d1, int port1)
         pirq->evtchn = 0;
         pirq_cleanup_check(pirq, d1);
         unlink_pirq_port(chn1, d1->vcpu[chn1->notify_vcpu_id]);
+        if ( is_hvm_domain(d1) && domain_pirq_to_irq(d1, pirq->pirq) > 0 )
+            unmap_domain_pirq_emuirq(d1, pirq->pirq);
         break;
     }