When testing with an UP guest with a pass-thru device with vt-d pi
enabled in host, we observed that guest couldn't receive interrupts
from that pass-thru device. Dumping IRTE, we found the corresponding
IRTE is set to posted format with "vector" field as 0.

We would fall into this issue when guest used the pirq format of MSI
(see the comment xen_msi_compose_msg() in linux kernel). As 'dest_id'
is repurposed, skip migration which is based on 'dest_id'.

Signed-off-by: Chao Gao <chao....@intel.com>
---
 xen/drivers/passthrough/io.c | 68 ++++++++++++++++++++++++++++----------------
 1 file changed, 43 insertions(+), 25 deletions(-)

diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c
index 4290c7c..362d4bd 100644
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -413,34 +413,52 @@ int pt_irq_create_bind(
                 pirq_dpci->gmsi.gflags = gflags;
             }
         }
-        /* Calculate dest_vcpu_id for MSI-type pirq migration. */
-        dest = MASK_EXTR(pirq_dpci->gmsi.gflags,
-                         XEN_DOMCTL_VMSI_X86_DEST_ID_MASK);
-        dest_mode = pirq_dpci->gmsi.gflags & XEN_DOMCTL_VMSI_X86_DM_MASK;
-        delivery_mode = MASK_EXTR(pirq_dpci->gmsi.gflags,
-                                  XEN_DOMCTL_VMSI_X86_DELIV_MASK);
-
-        dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
-        pirq_dpci->gmsi.dest_vcpu_id = dest_vcpu_id;
-        spin_unlock(&d->event_lock);
-
-        pirq_dpci->gmsi.posted = false;
-        vcpu = (dest_vcpu_id >= 0) ? d->vcpu[dest_vcpu_id] : NULL;
-        if ( iommu_intpost )
+        /*
+         * Migrate pirq and create posted format IRTE only if we know the 
gmsi's
+         * dest_id and vector.
+         */
+        if ( pirq_dpci->gmsi.gvec )
         {
-            if ( delivery_mode == dest_LowestPrio )
-                vcpu = vector_hashing_dest(d, dest, dest_mode,
-                                           pirq_dpci->gmsi.gvec);
-            if ( vcpu )
-                pirq_dpci->gmsi.posted = true;
+            /* Calculate dest_vcpu_id for MSI-type pirq migration. */
+            dest = MASK_EXTR(pirq_dpci->gmsi.gflags,
+                             XEN_DOMCTL_VMSI_X86_DEST_ID_MASK);
+            dest_mode = pirq_dpci->gmsi.gflags & XEN_DOMCTL_VMSI_X86_DM_MASK;
+            delivery_mode = MASK_EXTR(pirq_dpci->gmsi.gflags,
+                                      XEN_DOMCTL_VMSI_X86_DELIV_MASK);
+
+            dest_vcpu_id = hvm_girq_dest_2_vcpu_id(d, dest, dest_mode);
+            pirq_dpci->gmsi.dest_vcpu_id = dest_vcpu_id;
+            spin_unlock(&d->event_lock);
+
+            pirq_dpci->gmsi.posted = false;
+            vcpu = (dest_vcpu_id >= 0) ? d->vcpu[dest_vcpu_id] : NULL;
+            if ( iommu_intpost )
+            {
+                if ( delivery_mode == dest_LowestPrio )
+                    vcpu = vector_hashing_dest(d, dest, dest_mode,
+                                               pirq_dpci->gmsi.gvec);
+                if ( vcpu )
+                    pirq_dpci->gmsi.posted = true;
+            }
+            if ( vcpu && iommu_enabled )
+                hvm_migrate_pirq(pirq_dpci, vcpu);
+
+            /* Use interrupt posting if it is supported. */
+            if ( iommu_intpost )
+                pi_update_irte(vcpu ? &vcpu->arch.hvm.vmx.pi_desc : NULL,
+                               info, pirq_dpci->gmsi.gvec);
         }
-        if ( vcpu && iommu_enabled )
-            hvm_migrate_pirq(pirq_dpci, vcpu);
+        else /* pirq_dpci->gmsi.gvec == 0 */
+        {
+            pirq_dpci->gmsi.dest_vcpu_id = -1;
+            spin_unlock(&d->event_lock);
 
-        /* Use interrupt posting if it is supported. */
-        if ( iommu_intpost )
-            pi_update_irte(vcpu ? &vcpu->arch.hvm.vmx.pi_desc : NULL,
-                           info, pirq_dpci->gmsi.gvec);
+            if ( unlikely(pirq_dpci->gmsi.posted) )
+            {
+                pi_update_irte(NULL, info, 0);
+                pirq_dpci->gmsi.posted = false;
+            }
+        }
 
         if ( pt_irq_bind->u.msi.gflags & XEN_DOMCTL_VMSI_X86_UNMASKED )
         {
-- 
1.9.1


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to