]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Sep 2020 12:39:20 +0000 (14:39 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Sep 2020 12:39:20 +0000 (14:39 +0200)
added patches:
iommu-amd-use-cmpxchg_double-when-updating-128-bit-irte.patch

queue-5.4/iommu-amd-use-cmpxchg_double-when-updating-128-bit-irte.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/iommu-amd-use-cmpxchg_double-when-updating-128-bit-irte.patch b/queue-5.4/iommu-amd-use-cmpxchg_double-when-updating-128-bit-irte.patch
new file mode 100644 (file)
index 0000000..f2f3fac
--- /dev/null
@@ -0,0 +1,130 @@
+From e52d58d54a321d4fe9d0ecdabe4f8774449f0d6e Mon Sep 17 00:00:00 2001
+From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Date: Thu, 3 Sep 2020 09:38:22 +0000
+Subject: iommu/amd: Use cmpxchg_double() when updating 128-bit IRTE
+
+From: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+
+commit e52d58d54a321d4fe9d0ecdabe4f8774449f0d6e upstream.
+
+When using 128-bit interrupt-remapping table entry (IRTE) (a.k.a GA mode),
+current driver disables interrupt remapping when it updates the IRTE
+so that the upper and lower 64-bit values can be updated safely.
+
+However, this creates a small window, where the interrupt could
+arrive and result in IO_PAGE_FAULT (for interrupt) as shown below.
+
+  IOMMU Driver            Device IRQ
+  ============            ===========
+  irte.RemapEn=0
+       ...
+   change IRTE            IRQ from device ==> IO_PAGE_FAULT !!
+       ...
+  irte.RemapEn=1
+
+This scenario has been observed when changing irq affinity on a system
+running I/O-intensive workload, in which the destination APIC ID
+in the IRTE is updated.
+
+Instead, use cmpxchg_double() to update the 128-bit IRTE at once without
+disabling the interrupt remapping. However, this means several features,
+which require GA (128-bit IRTE) support will also be affected if cmpxchg16b
+is not supported (which is unprecedented for AMD processors w/ IOMMU).
+
+Fixes: 880ac60e2538 ("iommu/amd: Introduce interrupt remapping ops structure")
+Reported-by: Sean Osborne <sean.m.osborne@oracle.com>
+Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
+Tested-by: Erik Rockstrom <erik.rockstrom@oracle.com>
+Reviewed-by: Joao Martins <joao.m.martins@oracle.com>
+Link: https://lore.kernel.org/r/20200903093822.52012-3-suravee.suthikulpanit@amd.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/Kconfig          |    2 +-
+ drivers/iommu/amd_iommu.c      |   17 +++++++++++++----
+ drivers/iommu/amd_iommu_init.c |   21 +++++++++++++++++++--
+ 3 files changed, 33 insertions(+), 7 deletions(-)
+
+--- a/drivers/iommu/Kconfig
++++ b/drivers/iommu/Kconfig
+@@ -138,7 +138,7 @@ config AMD_IOMMU
+       select PCI_PASID
+       select IOMMU_API
+       select IOMMU_IOVA
+-      depends on X86_64 && PCI && ACPI
++      depends on X86_64 && PCI && ACPI && HAVE_CMPXCHG_DOUBLE
+       ---help---
+         With this option you can enable support for AMD IOMMU hardware in
+         your system. An IOMMU is a hardware component which provides
+--- a/drivers/iommu/amd_iommu.c
++++ b/drivers/iommu/amd_iommu.c
+@@ -3873,6 +3873,7 @@ out:
+ static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte,
+                         struct amd_ir_data *data)
+ {
++      bool ret;
+       struct irq_remap_table *table;
+       struct amd_iommu *iommu;
+       unsigned long flags;
+@@ -3890,10 +3891,18 @@ static int modify_irte_ga(u16 devid, int
+       entry = (struct irte_ga *)table->table;
+       entry = &entry[index];
+-      entry->lo.fields_remap.valid = 0;
+-      entry->hi.val = irte->hi.val;
+-      entry->lo.val = irte->lo.val;
+-      entry->lo.fields_remap.valid = 1;
++
++      ret = cmpxchg_double(&entry->lo.val, &entry->hi.val,
++                           entry->lo.val, entry->hi.val,
++                           irte->lo.val, irte->hi.val);
++      /*
++       * We use cmpxchg16 to atomically update the 128-bit IRTE,
++       * and it cannot be updated by the hardware or other processors
++       * behind us, so the return value of cmpxchg16 should be the
++       * same as the old value.
++       */
++      WARN_ON(!ret);
++
+       if (data)
+               data->ref = entry;
+--- a/drivers/iommu/amd_iommu_init.c
++++ b/drivers/iommu/amd_iommu_init.c
+@@ -1522,7 +1522,14 @@ static int __init init_iommu_one(struct
+                       iommu->mmio_phys_end = MMIO_REG_END_OFFSET;
+               else
+                       iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
+-              if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
++
++              /*
++               * Note: GA (128-bit IRTE) mode requires cmpxchg16b supports.
++               * GAM also requires GA mode. Therefore, we need to
++               * check cmpxchg16b support before enabling it.
++               */
++              if (!boot_cpu_has(X86_FEATURE_CX16) ||
++                  ((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
+                       amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
+               break;
+       case 0x11:
+@@ -1531,8 +1538,18 @@ static int __init init_iommu_one(struct
+                       iommu->mmio_phys_end = MMIO_REG_END_OFFSET;
+               else
+                       iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
+-              if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0))
++
++              /*
++               * Note: GA (128-bit IRTE) mode requires cmpxchg16b supports.
++               * XT, GAM also requires GA mode. Therefore, we need to
++               * check cmpxchg16b support before enabling them.
++               */
++              if (!boot_cpu_has(X86_FEATURE_CX16) ||
++                  ((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0)) {
+                       amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
++                      break;
++              }
++
+               /*
+                * Note: Since iommu_update_intcapxt() leverages
+                * the IOMMU MMIO access to MSI capability block registers
index 3801b93f2f68a7047970b9d364a9f4f3d588e97b..dfff9fa3640cc229b44a940c30a48b01e8cc1fe1 100644 (file)
@@ -40,3 +40,4 @@ net-phy-do-not-warn-in-phy_stop-on-phy_down.patch
 net-qrtr-check-skb_put_padto-return-value.patch
 net-add-__must_check-to-skb_put_padto.patch
 mm-memcg-fix-memcg-reclaim-soft-lockup.patch
+iommu-amd-use-cmpxchg_double-when-updating-128-bit-irte.patch