Jiri Slaby c5b460
From: Gaurav Batra <gbatra@linux.vnet.ibm.com>
Jiri Slaby c5b460
Date: Fri, 5 May 2023 13:47:01 -0500
Jiri Slaby c5b460
Subject: [PATCH] powerpc/iommu: Incorrect DDW Table is referenced for SR-IOV
Jiri Slaby c5b460
 device
Jiri Slaby c5b460
References: bsc#1012628
Jiri Slaby c5b460
Patch-mainline: 6.3.4
Jiri Slaby c5b460
Git-commit: 1f7aacc5eb9ed2cc17be7a90da5cd559effb9d59
Jiri Slaby c5b460
Jiri Slaby c5b460
commit 1f7aacc5eb9ed2cc17be7a90da5cd559effb9d59 upstream.
Jiri Slaby c5b460
Jiri Slaby c5b460
For an SR-IOV device, while enabling DDW, a new table is created and
Jiri Slaby c5b460
added at index 1 in the group. In the below 2 scenarios, the table is
Jiri Slaby c5b460
incorrectly referenced at index 0 (which is where the table is for
Jiri Slaby c5b460
default DMA window).
Jiri Slaby c5b460
Jiri Slaby c5b460
1. When adding DDW
Jiri Slaby c5b460
Jiri Slaby c5b460
   This issue is exposed with "slub_debug". Error thrown out from
Jiri Slaby c5b460
   dma_iommu_dma_supported()
Jiri Slaby c5b460
Jiri Slaby c5b460
   Warning: IOMMU offset too big for device mask
Jiri Slaby c5b460
   mask: 0xffffffff, table offset: 0x800000000000000
Jiri Slaby c5b460
Jiri Slaby c5b460
2. During Dynamic removal of the PCI device.
Jiri Slaby c5b460
Jiri Slaby c5b460
   Error is from iommu_tce_table_put() since a NULL table pointer is
Jiri Slaby c5b460
   passed in.
Jiri Slaby c5b460
Jiri Slaby c5b460
Fixes: 381ceda88c4c ("powerpc/pseries/iommu: Make use of DDW for indirect mapping")
Jiri Slaby c5b460
Cc: stable@vger.kernel.org # v5.15+
Jiri Slaby c5b460
Signed-off-by: Gaurav Batra <gbatra@linux.vnet.ibm.com>
Jiri Slaby c5b460
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
Jiri Slaby c5b460
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Jiri Slaby c5b460
Link: https://msgid.link/20230505184701.91613-1-gbatra@linux.vnet.ibm.com
Jiri Slaby c5b460
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby c5b460
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby c5b460
---
Jiri Slaby c5b460
 arch/powerpc/kernel/dma-iommu.c        |  4 +++-
Jiri Slaby c5b460
 arch/powerpc/platforms/pseries/iommu.c | 13 +++++++++----
Jiri Slaby c5b460
 2 files changed, 12 insertions(+), 5 deletions(-)
Jiri Slaby c5b460
Jiri Slaby c5b460
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
Jiri Slaby c5b460
index 038ce8d9..8920862f 100644
Jiri Slaby c5b460
--- a/arch/powerpc/kernel/dma-iommu.c
Jiri Slaby c5b460
+++ b/arch/powerpc/kernel/dma-iommu.c
Jiri Slaby c5b460
@@ -144,7 +144,7 @@ static bool dma_iommu_bypass_supported(struct device *dev, u64 mask)
Jiri Slaby c5b460
 /* We support DMA to/from any memory page via the iommu */
Jiri Slaby c5b460
 int dma_iommu_dma_supported(struct device *dev, u64 mask)
Jiri Slaby c5b460
 {
Jiri Slaby c5b460
-	struct iommu_table *tbl = get_iommu_table_base(dev);
Jiri Slaby c5b460
+	struct iommu_table *tbl;
Jiri Slaby c5b460
 
Jiri Slaby c5b460
 	if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) {
Jiri Slaby c5b460
 		/*
Jiri Slaby c5b460
@@ -162,6 +162,8 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask)
Jiri Slaby c5b460
 		return 1;
Jiri Slaby c5b460
 	}
Jiri Slaby c5b460
 
Jiri Slaby c5b460
+	tbl = get_iommu_table_base(dev);
Jiri Slaby c5b460
+
Jiri Slaby c5b460
 	if (!tbl) {
Jiri Slaby c5b460
 		dev_err(dev, "Warning: IOMMU dma not supported: mask 0x%08llx, table unavailable\n", mask);
Jiri Slaby c5b460
 		return 0;
Jiri Slaby c5b460
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
Jiri Slaby c5b460
index c74b71d4..a8acd3b4 100644
Jiri Slaby c5b460
--- a/arch/powerpc/platforms/pseries/iommu.c
Jiri Slaby c5b460
+++ b/arch/powerpc/platforms/pseries/iommu.c
Jiri Slaby c5b460
@@ -85,19 +85,24 @@ static struct iommu_table_group *iommu_pseries_alloc_group(int node)
Jiri Slaby c5b460
 static void iommu_pseries_free_group(struct iommu_table_group *table_group,
Jiri Slaby c5b460
 		const char *node_name)
Jiri Slaby c5b460
 {
Jiri Slaby c5b460
-	struct iommu_table *tbl;
Jiri Slaby c5b460
-
Jiri Slaby c5b460
 	if (!table_group)
Jiri Slaby c5b460
 		return;
Jiri Slaby c5b460
 
Jiri Slaby c5b460
-	tbl = table_group->tables[0];
Jiri Slaby c5b460
 #ifdef CONFIG_IOMMU_API
Jiri Slaby c5b460
 	if (table_group->group) {
Jiri Slaby c5b460
 		iommu_group_put(table_group->group);
Jiri Slaby c5b460
 		BUG_ON(table_group->group);
Jiri Slaby c5b460
 	}
Jiri Slaby c5b460
 #endif
Jiri Slaby c5b460
-	iommu_tce_table_put(tbl);
Jiri Slaby c5b460
+
Jiri Slaby c5b460
+	/* Default DMA window table is at index 0, while DDW at 1. SR-IOV
Jiri Slaby c5b460
+	 * adapters only have table on index 1.
Jiri Slaby c5b460
+	 */
Jiri Slaby c5b460
+	if (table_group->tables[0])
Jiri Slaby c5b460
+		iommu_tce_table_put(table_group->tables[0]);
Jiri Slaby c5b460
+
Jiri Slaby c5b460
+	if (table_group->tables[1])
Jiri Slaby c5b460
+		iommu_tce_table_put(table_group->tables[1]);
Jiri Slaby c5b460
 
Jiri Slaby c5b460
 	kfree(table_group);
Jiri Slaby c5b460
 }
Jiri Slaby c5b460
-- 
Jiri Slaby c5b460
2.35.3
Jiri Slaby c5b460