fbce2fe
fbce2fe
# HG changeset patch
fbce2fe
# User Stefano Stabellini <stefano.stabellini@eu.citrix.com>
fbce2fe
# Date 1321623485 0
fbce2fe
# Node ID 5a00ccfc63915650b8e1a262c2cad8e8d8670612
fbce2fe
# Parent  e73ada19a69daf821aa7d80323f1bd76239b9bae
fbce2fe
x86: re-inject emulated level pirqs in PV on HVM guests if still asserted
fbce2fe
fbce2fe
PV on HVM guests can loose level interrupts coming from emulated
fbce2fe
devices if they have been remapped onto event channels.  The reason is
fbce2fe
that we are missing the code to inject a pirq again in the guest when
fbce2fe
the guest EOIs it, if it corresponds to an emulated level interrupt
fbce2fe
and the interrupt is still asserted.
fbce2fe
fbce2fe
Fix this issue and also return error when the guest tries to get the
fbce2fe
irq_status of a non-existing pirq.
fbce2fe
fbce2fe
fbce2fe
Changes in this backport:
fbce2fe
 - move the spinlock afterward to cover the new code only.
fbce2fe
fbce2fe
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
fbce2fe
Committed-by: Keir Fraser <keir@xen.org>
fbce2fe
xen-unstable changeset:   24007:0526644ad2a6
fbce2fe
xen-unstable date:        Thu Oct 27 16:07:18 2011 +0100
fbce2fe
fbce2fe
diff -r e73ada19a69d -r 5a00ccfc6391 xen/arch/x86/physdev.c
fbce2fe
--- a/xen/arch/x86/physdev.c	Thu Nov 17 09:13:25 2011 +0000
fbce2fe
+++ b/xen/arch/x86/physdev.c	Fri Nov 18 13:38:05 2011 +0000
fbce2fe
@@ -268,6 +268,20 @@
fbce2fe
             ret = pirq_guest_eoi(v->domain, eoi.irq);
fbce2fe
         else
fbce2fe
             ret = 0;
fbce2fe
+        spin_lock(&v->domain->event_lock);
fbce2fe
+        if ( is_hvm_domain(v->domain) &&
fbce2fe
+                domain_pirq_to_emuirq(v->domain, eoi.irq) > 0 )
fbce2fe
+        {
fbce2fe
+            struct hvm_irq *hvm_irq = &v->domain->arch.hvm_domain.irq;
fbce2fe
+            int gsi = domain_pirq_to_emuirq(v->domain, eoi.irq);
fbce2fe
+
fbce2fe
+            /* if this is a level irq and count > 0, send another
fbce2fe
+             * notification */ 
fbce2fe
+            if ( gsi >= NR_ISAIRQS /* ISA irqs are edge triggered */
fbce2fe
+                    && hvm_irq->gsi_assert_count[gsi] )
fbce2fe
+                send_guest_pirq(v->domain, eoi.irq);
fbce2fe
+        }
fbce2fe
+        spin_unlock(&v->domain->event_lock);
fbce2fe
         break;
fbce2fe
     }
fbce2fe
 
fbce2fe
@@ -323,9 +337,10 @@
fbce2fe
             break;
fbce2fe
         irq_status_query.flags = 0;
fbce2fe
         if ( is_hvm_domain(v->domain) &&
fbce2fe
-             domain_pirq_to_irq(v->domain, irq) <= 0 )
fbce2fe
+                domain_pirq_to_irq(v->domain, irq) <= 0 &&
fbce2fe
+                domain_pirq_to_emuirq(v->domain, irq) == IRQ_UNBOUND )
fbce2fe
         {
fbce2fe
-            ret = copy_to_guest(arg, &irq_status_query, 1) ? -EFAULT : 0;
fbce2fe
+            ret = -EINVAL;
fbce2fe
             break;
fbce2fe
         }
fbce2fe
 
fbce2fe