[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v5 05/11] x86/passthrough: Extract PT_IRQ_TYPE_MSI body into pt_irq_bind_msi()



Move the PT_IRQ_TYPE_MSI case of pt_irq_create_bind() into a new static
helper pt_irq_bind_msi(d, machine_irq, gvec, gflags, gtable, unmasked).
The helper calls pt_irq_dpci_setup() itself, so pt_irq_create_bind() now
invokes the setup helper separately in the PCI / MSI_TRANSLATE case and
the 'default' case no longer needs to drop d->event_lock.

To keep this step "just" a code move, the extracted body is left at its
original (switch/case) indentation inside a compound block. The next
commit re-indents it. References to pt_irq_bind->u.msi.* are replaced by
the corresponding parameters, and the two pt_irq_destroy_bind() error
paths build a local xen_domctl_bind_pt_irq instead. No functional
change.

Signed-off-by: Julian Vetter <julian.vetter@xxxxxxxxxx>
---
Changes in v5:
- New patch: this is the first half of v4's single "Extract
  PT_IRQ_TYPE_MSI body" patch, now split into "extract as-is, keeping
  the switch/case indentation inside a bare block" plus a re-indent
  (next patch), so each step reviews cleanly.
- machine_irq / gflags parameters are now unsigned int.
- The redundant nr_pirqs bound check inside the helper was dropped.
- The "!!" on the unmasked argument was removed.
- pt_irq_dpci_setup() is now called per-case.
- The "default" case no longer double-unlocks d->event_lock.
- The two pt_irq_destroy_bind() error paths build a local
  xen_domctl_bind_pt_irq.
- Comment capitalisation fixed.

Signed-off-by: Julian Vetter <julian.vetter@xxxxxxxxxx>
---
 xen/drivers/passthrough/x86/hvm.c | 81 +++++++++++++++++++++----------
 1 file changed, 55 insertions(+), 26 deletions(-)

diff --git a/xen/drivers/passthrough/x86/hvm.c 
b/xen/drivers/passthrough/x86/hvm.c
index 7fcd3cc046..ed368a7fdb 100644
--- a/xen/drivers/passthrough/x86/hvm.c
+++ b/xen/drivers/passthrough/x86/hvm.c
@@ -287,40 +287,33 @@ static int pt_irq_dpci_setup(struct domain *d, unsigned 
int pirq,
     return 0;
 }
 
-int pt_irq_create_bind(
-    struct domain *d, const struct xen_domctl_bind_pt_irq *pt_irq_bind)
+static int pt_irq_bind_msi(struct domain *d, unsigned int machine_irq,
+                           uint8_t gvec, unsigned int gflags, uint64_t gtable,
+                           bool unmasked)
 {
     struct hvm_irq_dpci *hvm_irq_dpci;
     struct hvm_pirq_dpci *pirq_dpci;
     struct pirq *info;
-    int rc, pirq = pt_irq_bind->machine_irq;
-
-    if ( pirq < 0 || pirq >= d->nr_pirqs )
-        return -EINVAL;
+    int rc;
 
-    rc = pt_irq_dpci_setup(d, pirq, &hvm_irq_dpci, &pirq_dpci, &info);
+    rc = pt_irq_dpci_setup(d, machine_irq, &hvm_irq_dpci, &pirq_dpci, &info);
     if ( rc )
         return rc;
 
-    switch ( pt_irq_bind->irq_type )
-    {
-    case PT_IRQ_TYPE_MSI:
     {
         uint8_t dest, delivery_mode;
         bool dest_mode;
         int dest_vcpu_id;
         const struct vcpu *vcpu;
-        uint32_t gflags = pt_irq_bind->u.msi.gflags &
-                          ~XEN_DOMCTL_VMSI_X86_UNMASKED;
 
         if ( !(pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) )
         {
             pirq_dpci->flags = HVM_IRQ_DPCI_MAPPED | HVM_IRQ_DPCI_MACH_MSI |
                                HVM_IRQ_DPCI_GUEST_MSI;
-            pirq_dpci->gmsi.gvec = pt_irq_bind->u.msi.gvec;
+            pirq_dpci->gmsi.gvec = gvec;
             pirq_dpci->gmsi.gflags = gflags;
             /*
-             * 'pt_irq_create_bind' can be called after 'pt_irq_destroy_bind'.
+             * 'pt_irq_bind_msi' can be called after 'pt_irq_destroy_bind'.
              * The 'pirq_cleanup_check' which would free the structure is only
              * called if the event channel for the PIRQ is active. However
              * OS-es that use event channels usually bind PIRQs to eventds
@@ -328,14 +321,14 @@ int pt_irq_create_bind(
              * result that we re-use the 'dpci' structure. This can be
              * reproduced with unloading and loading the driver for a device.
              *
-             * As such on every 'pt_irq_create_bind' call we MUST set it.
+             * As such on every 'pt_irq_bind_msi' call we MUST set it.
              */
             pirq_dpci->dom = d;
-            /* bind after hvm_irq_dpci is setup to avoid race with irq 
handler*/
+            /* Bind after hvm_irq_dpci is setup to avoid race with irq 
handler. */
             rc = pirq_guest_bind(d->vcpu[0], info, 0);
-            if ( rc == 0 && pt_irq_bind->u.msi.gtable )
+            if ( rc == 0 && gtable )
             {
-                rc = msixtbl_pt_register(d, info, pt_irq_bind->u.msi.gtable);
+                rc = msixtbl_pt_register(d, info, gtable);
                 if ( unlikely(rc) )
                 {
                     pirq_guest_unbind(d, info);
@@ -371,13 +364,13 @@ int pt_irq_create_bind(
             }
 
             /* If pirq is already mapped as vmsi, update guest data/addr. */
-            if ( pirq_dpci->gmsi.gvec != pt_irq_bind->u.msi.gvec ||
+            if ( pirq_dpci->gmsi.gvec != gvec ||
                  pirq_dpci->gmsi.gflags != gflags )
             {
                 /* Directly clear pending EOIs before enabling new MSI info. */
                 pirq_guest_eoi(info);
 
-                pirq_dpci->gmsi.gvec = pt_irq_bind->u.msi.gvec;
+                pirq_dpci->gmsi.gvec = gvec;
                 pirq_dpci->gmsi.gflags = gflags;
             }
         }
@@ -408,23 +401,31 @@ int pt_irq_create_bind(
         /* Use interrupt posting if it is supported. */
         if ( iommu_intpost )
         {
-            rc = hvm_pi_update_irte(vcpu, info, pirq_dpci->gmsi.gvec);
+            struct xen_domctl_bind_pt_irq pt_irq_bind = {
+                .machine_irq = machine_irq,
+                .irq_type = PT_IRQ_TYPE_MSI,
+            };
 
+            rc = hvm_pi_update_irte(vcpu, info, pirq_dpci->gmsi.gvec);
             if ( rc )
             {
-                pt_irq_destroy_bind(d, pt_irq_bind);
+                pt_irq_destroy_bind(d, &pt_irq_bind);
                 return rc;
             }
         }
 
-        if ( pt_irq_bind->u.msi.gflags & XEN_DOMCTL_VMSI_X86_UNMASKED )
+        if ( unmasked )
         {
+            struct xen_domctl_bind_pt_irq pt_irq_bind = {
+                .machine_irq = machine_irq,
+                .irq_type = PT_IRQ_TYPE_MSI,
+            };
             unsigned long flags;
             struct irq_desc *desc = pirq_spin_lock_irq_desc(info, &flags);
 
             if ( !desc )
             {
-                pt_irq_destroy_bind(d, pt_irq_bind);
+                pt_irq_destroy_bind(d, &pt_irq_bind);
                 return -EINVAL;
             }
 
@@ -432,15 +433,44 @@ int pt_irq_create_bind(
             spin_unlock_irqrestore(&desc->lock, flags);
         }
 
-        break;
+        return 0;
+    }
+}
+
+int pt_irq_create_bind(
+    struct domain *d, const struct xen_domctl_bind_pt_irq *pt_irq_bind)
+{
+    int pirq = pt_irq_bind->machine_irq;
+
+    if ( pirq < 0 || pirq >= d->nr_pirqs )
+        return -EINVAL;
+
+    switch ( pt_irq_bind->irq_type )
+    {
+    case PT_IRQ_TYPE_MSI:
+    {
+        unsigned int gflags = pt_irq_bind->u.msi.gflags;
+
+        return pt_irq_bind_msi(d, pirq, pt_irq_bind->u.msi.gvec,
+                               gflags & ~XEN_DOMCTL_VMSI_X86_UNMASKED,
+                               pt_irq_bind->u.msi.gtable,
+                               gflags & XEN_DOMCTL_VMSI_X86_UNMASKED);
     }
 
     case PT_IRQ_TYPE_PCI:
     case PT_IRQ_TYPE_MSI_TRANSLATE:
     {
+        struct hvm_irq_dpci *hvm_irq_dpci;
+        struct hvm_pirq_dpci *pirq_dpci;
+        struct pirq *info;
         struct dev_intx_gsi_link *digl = NULL;
         struct hvm_girq_dpci_mapping *girq = NULL;
         unsigned int guest_gsi;
+        int rc;
+
+        rc = pt_irq_dpci_setup(d, pirq, &hvm_irq_dpci, &pirq_dpci, &info);
+        if ( rc )
+            return rc;
 
         /*
          * Mapping GSIs for the hardware domain is different than doing it for
@@ -589,7 +619,6 @@ int pt_irq_create_bind(
     }
 
     default:
-        write_unlock(&d->event_lock);
         return -EOPNOTSUPP;
     }
 
-- 
2.53.0



--
Julian Vetter | Vates Hypervisor & Kernel Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.