@@ -191,6 +191,18 @@ struct io_pgtable_ops *alloc_io_pgtable_ops(struct io_pgtable_cfg *cfg,
*/
void free_io_pgtable_ops(struct io_pgtable_ops *ops);
+/**
+ * io_pgtable_configure - Create page table config
+ *
+ * @cfg: The page table configuration.
+ * @pgd_size: On success, size of the top-level table in bytes.
+ *
+ * Initialize @cfg in the same way as alloc_io_pgtable_ops(), without allocating
+ * anything.
+ *
+ * Not all io_pgtable drivers implement this operation.
+ */
+int io_pgtable_configure(struct io_pgtable_cfg *cfg, size_t *pgd_size);
/*
* Internal structures for page table allocator implementations.
@@ -241,10 +253,12 @@ io_pgtable_tlb_add_page(struct io_pgtable *iop,
*
* @alloc: Allocate a set of page tables described by cfg.
* @free: Free the page tables associated with iop.
+ * @configure: Create the configuration without allocating anything. Optional.
*/
struct io_pgtable_init_fns {
struct io_pgtable *(*alloc)(struct io_pgtable_cfg *cfg, void *cookie);
void (*free)(struct io_pgtable *iop);
+ int (*configure)(struct io_pgtable_cfg *cfg, size_t *pgd_size);
};
extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns;
@@ -118,6 +118,18 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
return NULL;
}
+static int arm_64_lpae_configure_s1(struct io_pgtable_cfg *cfg, size_t *pgd_size)
+{
+ int ret;
+ struct arm_lpae_io_pgtable data = {};
+
+ ret = arm_lpae_init_pgtable_s1(cfg, &data);
+ if (ret)
+ return ret;
+ *pgd_size = sizeof(arm_lpae_iopte) << data.pgd_bits;
+ return 0;
+}
+
static struct io_pgtable *
arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
{
@@ -148,6 +160,18 @@ arm_64_lpae_alloc_pgtable_s2(struct io_pgtable_cfg *cfg, void *cookie)
return NULL;
}
+static int arm_64_lpae_configure_s2(struct io_pgtable_cfg *cfg, size_t *pgd_size)
+{
+ int ret;
+ struct arm_lpae_io_pgtable data = {};
+
+ ret = arm_lpae_init_pgtable_s2(cfg, &data);
+ if (ret)
+ return ret;
+ *pgd_size = sizeof(arm_lpae_iopte) << data.pgd_bits;
+ return 0;
+}
+
static struct io_pgtable *
arm_32_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
{
@@ -231,28 +255,30 @@ arm_mali_lpae_alloc_pgtable(struct io_pgtable_cfg *cfg, void *cookie)
}
struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns = {
- .alloc = arm_64_lpae_alloc_pgtable_s1,
- .free = arm_lpae_free_pgtable,
+ .alloc = arm_64_lpae_alloc_pgtable_s1,
+ .free = arm_lpae_free_pgtable,
+ .configure = arm_64_lpae_configure_s1,
};
struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns = {
- .alloc = arm_64_lpae_alloc_pgtable_s2,
- .free = arm_lpae_free_pgtable,
+ .alloc = arm_64_lpae_alloc_pgtable_s2,
+ .free = arm_lpae_free_pgtable,
+ .configure = arm_64_lpae_configure_s2,
};
struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns = {
- .alloc = arm_32_lpae_alloc_pgtable_s1,
- .free = arm_lpae_free_pgtable,
+ .alloc = arm_32_lpae_alloc_pgtable_s1,
+ .free = arm_lpae_free_pgtable,
};
struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s2_init_fns = {
- .alloc = arm_32_lpae_alloc_pgtable_s2,
- .free = arm_lpae_free_pgtable,
+ .alloc = arm_32_lpae_alloc_pgtable_s2,
+ .free = arm_lpae_free_pgtable,
};
struct io_pgtable_init_fns io_pgtable_arm_mali_lpae_init_fns = {
- .alloc = arm_mali_lpae_alloc_pgtable,
- .free = arm_lpae_free_pgtable,
+ .alloc = arm_mali_lpae_alloc_pgtable,
+ .free = arm_lpae_free_pgtable,
};
#ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST
@@ -74,3 +74,18 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops)
io_pgtable_init_table[iop->cfg.fmt]->free(iop);
}
EXPORT_SYMBOL_GPL(free_io_pgtable_ops);
+
+int io_pgtable_configure(struct io_pgtable_cfg *cfg, size_t *pgd_size)
+{
+ const struct io_pgtable_init_fns *fns;
+
+ if (cfg->fmt >= IO_PGTABLE_NUM_FMTS)
+ return -EINVAL;
+
+ fns = io_pgtable_init_table[cfg->fmt];
+ if (!fns || !fns->configure)
+ return -EOPNOTSUPP;
+
+ return fns->configure(cfg, pgd_size);
+}
+EXPORT_SYMBOL_GPL(io_pgtable_configure);
Allow IOMMU drivers to create the io-pgtable configuration without allocating any tables. This will be used by the SMMUv3-KVM driver to initialize a config and pass it to KVM. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> --- include/linux/io-pgtable.h | 14 +++++++++++ drivers/iommu/io-pgtable-arm.c | 46 ++++++++++++++++++++++++++-------- drivers/iommu/io-pgtable.c | 15 +++++++++++ 3 files changed, 65 insertions(+), 10 deletions(-)