@@ -523,6 +523,13 @@ static int visit_pgtable_walk(struct io_pgtable_walk_data *walk_data, int lvl,
return 0;
}
+static void visit_pgtable_post_table(struct arm_lpae_io_pgtable_walk_data *data,
+ arm_lpae_iopte *ptep, int lvl)
+{
+ if (data->visit_post_table)
+ data->visit_post_table(data, ptep, lvl);
+}
+
static int arm_lpae_pgtable_walk(struct io_pgtable_ops *ops, unsigned long iova,
size_t size, struct io_pgtable_walk_common *walker)
{
@@ -530,6 +537,7 @@ static int arm_lpae_pgtable_walk(struct io_pgtable_ops *ops, unsigned long iova,
struct io_pgtable_walk_data walk_data = {
.data = walker,
.visit = visit_pgtable_walk,
+ .visit_post_table = visit_pgtable_post_table,
.addr = iova,
.end = iova + size,
};
@@ -562,7 +570,12 @@ static int io_pgtable_visit(struct arm_lpae_io_pgtable *data,
}
ptep = iopte_deref(pte, data);
- return __arm_lpae_iopte_walk(data, walk_data, ptep, lvl + 1);
+ ret = __arm_lpae_iopte_walk(data, walk_data, ptep, lvl + 1);
+
+ if (walk_data->visit_post_table)
+ walk_data->visit_post_table(data, ptep, lvl);
+
+ return ret;
}
static int __arm_lpae_iopte_walk(struct arm_lpae_io_pgtable *data,
@@ -21,6 +21,8 @@ struct io_pgtable_walk_data {
struct io_pgtable_walk_common *data;
int (*visit)(struct io_pgtable_walk_data *walk_data, int lvl,
arm_lpae_iopte *ptep, size_t size);
+ void (*visit_post_table)(struct arm_lpae_io_pgtable_walk_data *data,
+ arm_lpae_iopte *ptep, int lvl);
unsigned long flags;
u64 addr;
const u64 end;
@@ -193,6 +193,8 @@ struct arm_lpae_io_pgtable_walk_data {
u64 ptes[4];
int level;
void *cookie;
+ void (*visit_post_table)(struct arm_lpae_io_pgtable_walk_data *data,
+ arm_lpae_iopte *ptep, int lvl);
};
/**
Add a callback for postable, this would be used by pKVM to cleanup tables next. Signed-off-by: Mostafa Saleh <smostafa@google.com> --- drivers/iommu/io-pgtable-arm-common.c | 15 ++++++++++++++- include/linux/io-pgtable-arm.h | 2 ++ include/linux/io-pgtable.h | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-)