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

Jean-Philippe Brucker
2023-02-01T14:02:03Z

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@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