Re: [XEN PATCH v5 3/3] x86/iommu: Disable intrerrupt remapping if cx16 is not supported

2024-04-24 Thread Jan Beulich
On 18.04.2024 13:57, Teddy Astie wrote:
> All hardware with VT-d/AMD-Vi has CMPXCHG16B support.  Check this at
> initialisation time, and remove the effectively-dead logic for the non-cx16
> case.
> 
> Suggested-by: Andrew Cooper 
> Signed-off-by: Teddy Astie 

Hmm, so this looks to be the code that I commented on as missing in patch 1.
I don't think this can be two separate patches. If you want to keep things
in small chunks, move the removal of "the effectively-dead logic" to a
separate, follow-on patch.

Jan



[XEN PATCH v5 3/3] x86/iommu: Disable intrerrupt remapping if cx16 is not supported

2024-04-18 Thread Teddy Astie
All hardware with VT-d/AMD-Vi has CMPXCHG16B support.  Check this at
initialisation time, and remove the effectively-dead logic for the non-cx16
case.

Suggested-by: Andrew Cooper 
Signed-off-by: Teddy Astie 
---
 xen/drivers/passthrough/amd/iommu_intr.c |  6 ++
 xen/drivers/passthrough/vtd/intremap.c   | 70 +++-
 xen/drivers/passthrough/vtd/iommu.c  |  7 +--
 3 files changed, 27 insertions(+), 56 deletions(-)

diff --git a/xen/drivers/passthrough/amd/iommu_intr.c 
b/xen/drivers/passthrough/amd/iommu_intr.c
index 7fc796dec2..9ab7c68749 100644
--- a/xen/drivers/passthrough/amd/iommu_intr.c
+++ b/xen/drivers/passthrough/amd/iommu_intr.c
@@ -649,6 +649,12 @@ bool __init cf_check iov_supports_xt(void)
 if ( !iommu_enable || !iommu_intremap )
 return false;
 
+if ( unlikely(!cpu_has_cx16) )
+{
+AMD_IOMMU_WARN("CPU doesn't support CMPXCHG16B, disable interrupt 
remapping\n");
+return false;
+}
+
 if ( amd_iommu_prepare(true) )
 return false;
 
diff --git a/xen/drivers/passthrough/vtd/intremap.c 
b/xen/drivers/passthrough/vtd/intremap.c
index c504852eb8..7d4d907b4f 100644
--- a/xen/drivers/passthrough/vtd/intremap.c
+++ b/xen/drivers/passthrough/vtd/intremap.c
@@ -150,6 +150,13 @@ bool __init cf_check intel_iommu_supports_eim(void)
 if ( !iommu_qinval || !iommu_intremap || list_empty(_drhd_units) )
 return false;
 
+if ( unlikely(!cpu_has_cx16) )
+{
+printk(XENLOG_WARNING VTDPREFIX
+   "CPU doesn't support CMPXCHG16B, disable interrupt 
remapping\n");
+return false;
+}
+
 /* We MUST have a DRHD unit for each IOAPIC. */
 for ( apic = 0; apic < nr_ioapics; apic++ )
 if ( !ioapic_to_drhd(IO_APIC_ID(apic)) )
@@ -173,47 +180,26 @@ bool __init cf_check intel_iommu_supports_eim(void)
  * Assume iremap_lock has been acquired. It is to make sure software will not
  * change the same IRTE behind us. With this assumption, if only high qword or
  * low qword in IRTE is to be updated, this function's atomic variant can
- * present an atomic update to VT-d hardware even when cmpxchg16b
- * instruction is not supported.
+ * present an atomic update to VT-d hardware.
  */
 static void update_irte(struct vtd_iommu *iommu, struct iremap_entry *entry,
 const struct iremap_entry *new_ire, bool atomic)
 {
-ASSERT(spin_is_locked(>intremap.lock));
+__uint128_t ret;
+struct iremap_entry old_ire;
 
-if ( cpu_has_cx16 )
-{
-__uint128_t ret;
-struct iremap_entry old_ire;
+ASSERT(spin_is_locked(>intremap.lock));
 
-old_ire = *entry;
-ret = cmpxchg16b(entry, _ire, new_ire);
+old_ire = *entry;
+ret = cmpxchg16b(entry, _ire, new_ire);
 
-/*
- * In the above, we use cmpxchg16 to atomically update the 128-bit
- * IRTE, and the hardware cannot update the IRTE behind us, so
- * the return value of cmpxchg16 should be the same as old_ire.
- * This ASSERT validate it.
- */
-ASSERT(ret == old_ire.val);
-}
-else
-{
-/*
- * VT-d hardware doesn't update IRTEs behind us, nor the software
- * since we hold iremap_lock. If the caller wants VT-d hardware to
- * always see a consistent entry, but we can't meet it, a bug will
- * be raised.
- */
-if ( entry->lo == new_ire->lo )
-write_atomic(>hi, new_ire->hi);
-else if ( entry->hi == new_ire->hi )
-write_atomic(>lo, new_ire->lo);
-else if ( !atomic )
-*entry = *new_ire;
-else
-BUG();
-}
+/*
+ * In the above, we use cmpxchg16 to atomically update the 128-bit
+ * IRTE, and the hardware cannot update the IRTE behind us, so
+ * the return value of cmpxchg16 should be the same as old_ire.
+ * This ASSERT validate it.
+ */
+ASSERT(ret == old_ire.val);
 }
 
 /* Mark specified intr remap entry as free */
@@ -395,7 +381,6 @@ static int ioapic_rte_to_remap_entry(struct vtd_iommu 
*iommu,
 /* Indicate remap format. */
 remap_rte->format = 1;
 
-/* If cmpxchg16b is not available the caller must mask the IO-APIC pin. */
 update_irte(iommu, iremap_entry, _ire, !init && !masked);
 iommu_sync_cache(iremap_entry, sizeof(*iremap_entry));
 iommu_flush_iec_index(iommu, 0, index);
@@ -437,21 +422,6 @@ void cf_check io_apic_write_remap_rte(
 bool masked = true;
 int rc;
 
-if ( !cpu_has_cx16 )
-{
-   /*
-* Cannot atomically update the IRTE entry: mask the IO-APIC pin to
-* avoid interrupts seeing an inconsistent IRTE entry.
-*/
-old_rte = __ioapic_read_entry(apic, pin, true);
-if ( !old_rte.mask )
-{
-masked = false;
-old_rte.mask = 1;
-__ioapic_write_entry(apic, pin, true, old_rte);
-}
-}
-
 /* Not the initializer, for old gcc to cope.