diff mbox series

[v3,6/8] x86/iommu: call pi_update_irte through an hvm_function callback

Message ID 20230116070431.905594-7-burzalodowa@gmail.com (mailing list archive)
State Superseded
Headers show
Series Make x86 IOMMU driver support configurable | expand

Commit Message

Xenia Ragiadakou Jan. 16, 2023, 7:04 a.m. UTC
Posted interrupt support in Xen is currently implemented only for the
Intel platforms. Instead of calling directly pi_update_irte() from the
common hvm code, add a pi_update_irte callback to the hvm_function_table.
Then, create a wrapper function hvm_pi_update_irte() to be used by the
common hvm code.

In the pi_update_irte callback prototype, pass the vcpu as first parameter
instead of the posted-interrupt descriptor that is platform specific, and
remove the const qualifier from the parameter gvec since it is not needed
and because it does not compile with the alternative code patching in use.

Since the posted interrupt descriptor is Intel VT-x specific while
msi_msg_write_remap_rte is iommu specific, open code pi_update_irte() inside
vmx_pi_update_irte() but replace msi_msg_write_remap_rte() with generic
iommu_update_ire_from_msi(). That way vmx_pi_update_irte() is not bound to
Intel VT-d anymore.

Remove the now unused pi_update_irte() implementation.

No functional change intended.

Signed-off-by: Xenia Ragiadakou <burzalodowa@gmail.com>
---

Changes in v3:
  - open code pi_update_irte() in vmx_pi_update_irte() but instead of using
    the VT-d specific function msi_msg_write_remap_rte() use the generic
    iommu_update_ire_from_msi()
  - delete pi_update_irte() from vtd/intremap.c
  - move the initialization of vmx pi_update_irte stub to start_vmx() and
    perform it only if iommu_intpost is enabled.
  - move pi_update_irte right after handle_eoi

 xen/arch/x86/hvm/vmx/vmx.c             | 41 ++++++++++++++++++++++++++
 xen/arch/x86/include/asm/hvm/hvm.h     | 10 +++++++
 xen/arch/x86/include/asm/iommu.h       |  3 --
 xen/drivers/passthrough/vtd/intremap.c | 36 ----------------------
 xen/drivers/passthrough/x86/hvm.c      |  5 ++--
 5 files changed, 53 insertions(+), 42 deletions(-)

Comments

Xenia Ragiadakou Jan. 16, 2023, 9:35 a.m. UTC | #1
On 1/16/23 09:04, Xenia Ragiadakou wrote:
> Posted interrupt support in Xen is currently implemented only for the
> Intel platforms. Instead of calling directly pi_update_irte() from the
> common hvm code, add a pi_update_irte callback to the hvm_function_table.
> Then, create a wrapper function hvm_pi_update_irte() to be used by the
> common hvm code.
> 
> In the pi_update_irte callback prototype, pass the vcpu as first parameter
> instead of the posted-interrupt descriptor that is platform specific, and
> remove the const qualifier from the parameter gvec since it is not needed
> and because it does not compile with the alternative code patching in use.
> 
> Since the posted interrupt descriptor is Intel VT-x specific while
> msi_msg_write_remap_rte is iommu specific, open code pi_update_irte() inside
> vmx_pi_update_irte() but replace msi_msg_write_remap_rte() with generic
> iommu_update_ire_from_msi(). That way vmx_pi_update_irte() is not bound to
> Intel VT-d anymore.
> 
> Remove the now unused pi_update_irte() implementation.
> 
> No functional change intended.
> 
> Signed-off-by: Xenia Ragiadakou <burzalodowa@gmail.com>
> ---
> 
> Changes in v3:
>    - open code pi_update_irte() in vmx_pi_update_irte() but instead of using
>      the VT-d specific function msi_msg_write_remap_rte() use the generic
>      iommu_update_ire_from_msi()
>    - delete pi_update_irte() from vtd/intremap.c
>    - move the initialization of vmx pi_update_irte stub to start_vmx() and
>      perform it only if iommu_intpost is enabled.
>    - move pi_update_irte right after handle_eoi
> 
>   xen/arch/x86/hvm/vmx/vmx.c             | 41 ++++++++++++++++++++++++++
>   xen/arch/x86/include/asm/hvm/hvm.h     | 10 +++++++
>   xen/arch/x86/include/asm/iommu.h       |  3 --
>   xen/drivers/passthrough/vtd/intremap.c | 36 ----------------------
>   xen/drivers/passthrough/x86/hvm.c      |  5 ++--
>   5 files changed, 53 insertions(+), 42 deletions(-)
> 
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index 15a07933ee..a5355dbac2 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -396,6 +396,43 @@ void vmx_pi_hooks_deassign(struct domain *d)
>       domain_unpause(d);
>   }
>   
> +/*
> + * This function is used to update the IRTE for posted-interrupt
> + * when guest changes MSI/MSI-X information.
> + */
> +static int cf_check vmx_pi_update_irte(const struct vcpu *v,
> +                                       const struct pirq *pirq, uint8_t gvec)
> +{
> +    const struct pi_desc *pi_desc = v ? &v->arch.hvm.vmx.pi_desc : NULL;
> +    struct irq_desc *desc;
> +    struct msi_desc *msi_desc;
> +    int rc;
> +
> +    desc = pirq_spin_lock_irq_desc(pirq, NULL);
> +    if ( !desc )
> +        return -EINVAL;
> +
> +    msi_desc = desc->msi_desc;
> +    if ( !msi_desc )
> +    {
> +        rc = -ENODEV;
> +        goto unlock_out;
> +    }
> +    msi_desc->pi_desc = pi_desc;
> +    msi_desc->gvec = gvec;
> +
> +    spin_unlock_irq(&desc->lock);
> +
> +    ASSERT(pcidevs_locked());
> +
> +    return iommu_update_ire_from_msi(msi_desc, &msi_desc->msg);
> +
> + unlock_out:
> +    spin_unlock_irq(&desc->lock);
> +
> +    return rc;
> +}
> +
>   static const struct lbr_info {
>       u32 base, count;
>   } p4_lbr[] = {
> @@ -2969,8 +3006,12 @@ const struct hvm_function_table * __init start_vmx(void)
>       {
>           alloc_direct_apic_vector(&posted_intr_vector, pi_notification_interrupt);
>           if ( iommu_intpost )
> +        {
>               alloc_direct_apic_vector(&pi_wakeup_vector, pi_wakeup_interrupt);
>   
> +            vmx_function_table.pi_update_irte = vmx_pi_update_irte;
> +        }
> +
>           vmx_function_table.deliver_posted_intr = vmx_deliver_posted_intr;
>           vmx_function_table.sync_pir_to_irr     = vmx_sync_pir_to_irr;
>           vmx_function_table.test_pir            = vmx_test_pir;
> diff --git a/xen/arch/x86/include/asm/hvm/hvm.h b/xen/arch/x86/include/asm/hvm/hvm.h
> index 93254651f2..b1990a047c 100644
> --- a/xen/arch/x86/include/asm/hvm/hvm.h
> +++ b/xen/arch/x86/include/asm/hvm/hvm.h
> @@ -28,6 +28,8 @@
>   #include <asm/x86_emulate.h>
>   #include <asm/hvm/asid.h>
>   
> +struct pirq; /* needed by pi_update_irte */
> +
>   #ifdef CONFIG_HVM_FEP
>   /* Permit use of the Forced Emulation Prefix in HVM guests */
>   extern bool_t opt_hvm_fep;
> @@ -213,6 +215,8 @@ struct hvm_function_table {
>       void (*sync_pir_to_irr)(struct vcpu *v);
>       bool (*test_pir)(const struct vcpu *v, uint8_t vector);
>       void (*handle_eoi)(uint8_t vector, int isr);
> +    int (*pi_update_irte)(const struct vcpu *v, const struct pirq *pirq,
> +                          uint8_t gvec);
>   
>       /*Walk nested p2m  */
>       int (*nhvm_hap_walk_L1_p2m)(struct vcpu *v, paddr_t L2_gpa,
> @@ -774,6 +778,12 @@ static inline void hvm_set_nonreg_state(struct vcpu *v,
>           alternative_vcall(hvm_funcs.set_nonreg_state, v, nrs);
>   }
>   
> +static inline int hvm_pi_update_irte(const struct vcpu *v,
> +                                     const struct pirq *pirq, uint8_t gvec)
> +{
> +    return alternative_call(hvm_funcs.pi_update_irte, v, pirq, gvec);
> +}
> +
>   #else  /* CONFIG_HVM */
>   
>   #define hvm_enabled false
> diff --git a/xen/arch/x86/include/asm/iommu.h b/xen/arch/x86/include/asm/iommu.h
> index fc0afe35bf..4794e72cf1 100644
> --- a/xen/arch/x86/include/asm/iommu.h
> +++ b/xen/arch/x86/include/asm/iommu.h
> @@ -129,9 +129,6 @@ void iommu_identity_map_teardown(struct domain *d);
>   
>   extern bool untrusted_msi;
>   
> -int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq,
> -                   const uint8_t gvec);
> -
>   extern bool iommu_non_coherent, iommu_superpages;
>   
>   static inline void iommu_sync_cache(const void *addr, unsigned int size)

Here, I forgot to remove the #include <asm/hvm/vmx/vmcs.h>. I will fix 
it in the next version.

> diff --git a/xen/drivers/passthrough/vtd/intremap.c b/xen/drivers/passthrough/vtd/intremap.c
> index 1512e4866b..b39bc83282 100644
> --- a/xen/drivers/passthrough/vtd/intremap.c
> +++ b/xen/drivers/passthrough/vtd/intremap.c
> @@ -866,39 +866,3 @@ void cf_check intel_iommu_disable_eim(void)
>       for_each_drhd_unit ( drhd )
>           disable_qinval(drhd->iommu);
>   }
> -
> -/*
> - * This function is used to update the IRTE for posted-interrupt
> - * when guest changes MSI/MSI-X information.
> - */
> -int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq,
> -    const uint8_t gvec)
> -{
> -    struct irq_desc *desc;
> -    struct msi_desc *msi_desc;
> -    int rc;
> -
> -    desc = pirq_spin_lock_irq_desc(pirq, NULL);
> -    if ( !desc )
> -        return -EINVAL;
> -
> -    msi_desc = desc->msi_desc;
> -    if ( !msi_desc )
> -    {
> -        rc = -ENODEV;
> -        goto unlock_out;
> -    }
> -    msi_desc->pi_desc = pi_desc;
> -    msi_desc->gvec = gvec;
> -
> -    spin_unlock_irq(&desc->lock);
> -
> -    ASSERT(pcidevs_locked());
> -
> -    return msi_msg_write_remap_rte(msi_desc, &msi_desc->msg);
> -
> - unlock_out:
> -    spin_unlock_irq(&desc->lock);
> -
> -    return rc;
> -}
> diff --git a/xen/drivers/passthrough/x86/hvm.c b/xen/drivers/passthrough/x86/hvm.c
> index a16e0e5344..e720461a14 100644
> --- a/xen/drivers/passthrough/x86/hvm.c
> +++ b/xen/drivers/passthrough/x86/hvm.c
> @@ -381,8 +381,7 @@ int pt_irq_create_bind(
>   
>           /* 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);
> +            hvm_pi_update_irte(vcpu, info, pirq_dpci->gmsi.gvec);
>   
>           if ( pt_irq_bind->u.msi.gflags & XEN_DOMCTL_VMSI_X86_UNMASKED )
>           {
> @@ -672,7 +671,7 @@ int pt_irq_destroy_bind(
>               what = "bogus";
>       }
>       else if ( pirq_dpci && pirq_dpci->gmsi.posted )
> -        pi_update_irte(NULL, pirq, 0);
> +        hvm_pi_update_irte(NULL, pirq, 0);
>   
>       if ( pirq_dpci && (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) &&
>            list_empty(&pirq_dpci->digl_list) )
diff mbox series

Patch

diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 15a07933ee..a5355dbac2 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -396,6 +396,43 @@  void vmx_pi_hooks_deassign(struct domain *d)
     domain_unpause(d);
 }
 
+/*
+ * This function is used to update the IRTE for posted-interrupt
+ * when guest changes MSI/MSI-X information.
+ */
+static int cf_check vmx_pi_update_irte(const struct vcpu *v,
+                                       const struct pirq *pirq, uint8_t gvec)
+{
+    const struct pi_desc *pi_desc = v ? &v->arch.hvm.vmx.pi_desc : NULL;
+    struct irq_desc *desc;
+    struct msi_desc *msi_desc;
+    int rc;
+
+    desc = pirq_spin_lock_irq_desc(pirq, NULL);
+    if ( !desc )
+        return -EINVAL;
+
+    msi_desc = desc->msi_desc;
+    if ( !msi_desc )
+    {
+        rc = -ENODEV;
+        goto unlock_out;
+    }
+    msi_desc->pi_desc = pi_desc;
+    msi_desc->gvec = gvec;
+
+    spin_unlock_irq(&desc->lock);
+
+    ASSERT(pcidevs_locked());
+
+    return iommu_update_ire_from_msi(msi_desc, &msi_desc->msg);
+
+ unlock_out:
+    spin_unlock_irq(&desc->lock);
+
+    return rc;
+}
+
 static const struct lbr_info {
     u32 base, count;
 } p4_lbr[] = {
@@ -2969,8 +3006,12 @@  const struct hvm_function_table * __init start_vmx(void)
     {
         alloc_direct_apic_vector(&posted_intr_vector, pi_notification_interrupt);
         if ( iommu_intpost )
+        {
             alloc_direct_apic_vector(&pi_wakeup_vector, pi_wakeup_interrupt);
 
+            vmx_function_table.pi_update_irte = vmx_pi_update_irte;
+        }
+
         vmx_function_table.deliver_posted_intr = vmx_deliver_posted_intr;
         vmx_function_table.sync_pir_to_irr     = vmx_sync_pir_to_irr;
         vmx_function_table.test_pir            = vmx_test_pir;
diff --git a/xen/arch/x86/include/asm/hvm/hvm.h b/xen/arch/x86/include/asm/hvm/hvm.h
index 93254651f2..b1990a047c 100644
--- a/xen/arch/x86/include/asm/hvm/hvm.h
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
@@ -28,6 +28,8 @@ 
 #include <asm/x86_emulate.h>
 #include <asm/hvm/asid.h>
 
+struct pirq; /* needed by pi_update_irte */
+
 #ifdef CONFIG_HVM_FEP
 /* Permit use of the Forced Emulation Prefix in HVM guests */
 extern bool_t opt_hvm_fep;
@@ -213,6 +215,8 @@  struct hvm_function_table {
     void (*sync_pir_to_irr)(struct vcpu *v);
     bool (*test_pir)(const struct vcpu *v, uint8_t vector);
     void (*handle_eoi)(uint8_t vector, int isr);
+    int (*pi_update_irte)(const struct vcpu *v, const struct pirq *pirq,
+                          uint8_t gvec);
 
     /*Walk nested p2m  */
     int (*nhvm_hap_walk_L1_p2m)(struct vcpu *v, paddr_t L2_gpa,
@@ -774,6 +778,12 @@  static inline void hvm_set_nonreg_state(struct vcpu *v,
         alternative_vcall(hvm_funcs.set_nonreg_state, v, nrs);
 }
 
+static inline int hvm_pi_update_irte(const struct vcpu *v,
+                                     const struct pirq *pirq, uint8_t gvec)
+{
+    return alternative_call(hvm_funcs.pi_update_irte, v, pirq, gvec);
+}
+
 #else  /* CONFIG_HVM */
 
 #define hvm_enabled false
diff --git a/xen/arch/x86/include/asm/iommu.h b/xen/arch/x86/include/asm/iommu.h
index fc0afe35bf..4794e72cf1 100644
--- a/xen/arch/x86/include/asm/iommu.h
+++ b/xen/arch/x86/include/asm/iommu.h
@@ -129,9 +129,6 @@  void iommu_identity_map_teardown(struct domain *d);
 
 extern bool untrusted_msi;
 
-int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq,
-                   const uint8_t gvec);
-
 extern bool iommu_non_coherent, iommu_superpages;
 
 static inline void iommu_sync_cache(const void *addr, unsigned int size)
diff --git a/xen/drivers/passthrough/vtd/intremap.c b/xen/drivers/passthrough/vtd/intremap.c
index 1512e4866b..b39bc83282 100644
--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -866,39 +866,3 @@  void cf_check intel_iommu_disable_eim(void)
     for_each_drhd_unit ( drhd )
         disable_qinval(drhd->iommu);
 }
-
-/*
- * This function is used to update the IRTE for posted-interrupt
- * when guest changes MSI/MSI-X information.
- */
-int pi_update_irte(const struct pi_desc *pi_desc, const struct pirq *pirq,
-    const uint8_t gvec)
-{
-    struct irq_desc *desc;
-    struct msi_desc *msi_desc;
-    int rc;
-
-    desc = pirq_spin_lock_irq_desc(pirq, NULL);
-    if ( !desc )
-        return -EINVAL;
-
-    msi_desc = desc->msi_desc;
-    if ( !msi_desc )
-    {
-        rc = -ENODEV;
-        goto unlock_out;
-    }
-    msi_desc->pi_desc = pi_desc;
-    msi_desc->gvec = gvec;
-
-    spin_unlock_irq(&desc->lock);
-
-    ASSERT(pcidevs_locked());
-
-    return msi_msg_write_remap_rte(msi_desc, &msi_desc->msg);
-
- unlock_out:
-    spin_unlock_irq(&desc->lock);
-
-    return rc;
-}
diff --git a/xen/drivers/passthrough/x86/hvm.c b/xen/drivers/passthrough/x86/hvm.c
index a16e0e5344..e720461a14 100644
--- a/xen/drivers/passthrough/x86/hvm.c
+++ b/xen/drivers/passthrough/x86/hvm.c
@@ -381,8 +381,7 @@  int pt_irq_create_bind(
 
         /* 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);
+            hvm_pi_update_irte(vcpu, info, pirq_dpci->gmsi.gvec);
 
         if ( pt_irq_bind->u.msi.gflags & XEN_DOMCTL_VMSI_X86_UNMASKED )
         {
@@ -672,7 +671,7 @@  int pt_irq_destroy_bind(
             what = "bogus";
     }
     else if ( pirq_dpci && pirq_dpci->gmsi.posted )
-        pi_update_irte(NULL, pirq, 0);
+        hvm_pi_update_irte(NULL, pirq, 0);
 
     if ( pirq_dpci && (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) &&
          list_empty(&pirq_dpci->digl_list) )