[RFC PATCH 06/45] iommu/io-pgtable-arm: Extend __arm_lpae_free_pgtable() to only free child tables

Jean-Philippe Brucker jean-philippe at linaro.org
Wed Feb 1 04:52:50 PST 2023


The hypervisor side of io-pgtable-arm needs to free the top-level page
table separately from the other tables (which are page-sized and will
use a page queue).

Signed-off-by: Jean-Philippe Brucker <jean-philippe at linaro.org>
---
 include/linux/io-pgtable-arm.h        |  2 +-
 drivers/iommu/io-pgtable-arm-common.c | 11 +++++++----
 drivers/iommu/io-pgtable-arm.c        |  2 +-
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/include/linux/io-pgtable-arm.h b/include/linux/io-pgtable-arm.h
index 5199bd9851b6..2b3e69386d08 100644
--- a/include/linux/io-pgtable-arm.h
+++ b/include/linux/io-pgtable-arm.h
@@ -166,7 +166,7 @@ static inline bool iopte_leaf(arm_lpae_iopte pte, int lvl,
 
 /* Generic functions */
 void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
-			     arm_lpae_iopte *ptep);
+			     arm_lpae_iopte *ptep, bool only_children);
 
 int arm_lpae_init_pgtable(struct io_pgtable_cfg *cfg,
 			  struct arm_lpae_io_pgtable *data);
diff --git a/drivers/iommu/io-pgtable-arm-common.c b/drivers/iommu/io-pgtable-arm-common.c
index 359086cace34..009c35d4095f 100644
--- a/drivers/iommu/io-pgtable-arm-common.c
+++ b/drivers/iommu/io-pgtable-arm-common.c
@@ -299,7 +299,7 @@ int arm_lpae_map_pages(struct io_pgtable *iop, unsigned long iova,
 }
 
 void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
-			     arm_lpae_iopte *ptep)
+			     arm_lpae_iopte *ptep, bool only_children)
 {
 	arm_lpae_iopte *start, *end;
 	unsigned long table_size;
@@ -323,10 +323,12 @@ void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
 		if (!pte || iopte_leaf(pte, lvl, data->iop.cfg.fmt))
 			continue;
 
-		__arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
+		__arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data),
+					false);
 	}
 
-	__arm_lpae_free_pages(start, table_size, &data->iop.cfg);
+	if (!only_children)
+		__arm_lpae_free_pages(start, table_size, &data->iop.cfg);
 }
 
 static size_t arm_lpae_split_blk_unmap(struct io_pgtable *iop,
@@ -428,7 +430,8 @@ static size_t __arm_lpae_unmap(struct io_pgtable *iop,
 				/* Also flush any partial walks */
 				io_pgtable_tlb_flush_walk(cfg, iop, iova + i * size, size,
 							  ARM_LPAE_GRANULE(data));
-				__arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data));
+				__arm_lpae_free_pgtable(data, lvl + 1, iopte_deref(pte, data),
+							false);
 			} else if (!iommu_iotlb_gather_queued(gather)) {
 				io_pgtable_tlb_add_page(cfg, iop, gather,
 							iova + i * size, size);
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index bee8980c89eb..b7920637126c 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -84,7 +84,7 @@ static void arm_lpae_free_pgtable(struct io_pgtable *iop)
 {
 	struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(iop->ops);
 
-	__arm_lpae_free_pgtable(data, data->start_level, iop->pgd);
+	__arm_lpae_free_pgtable(data, data->start_level, iop->pgd, false);
 	kfree(data);
 }
 
-- 
2.39.0




More information about the linux-arm-kernel mailing list