iommu: Allow io-pgtable to be used outside of drivers/iommu/
authorRob Herring <robh@kernel.org>
Tue, 5 Feb 2019 16:37:31 +0000 (10:37 -0600)
committerJoerg Roedel <jroedel@suse.de>
Mon, 11 Feb 2019 10:26:48 +0000 (11:26 +0100)
Move io-pgtable.h to include/linux/ and export alloc_io_pgtable_ops
and free_io_pgtable_ops. This enables drivers outside drivers/iommu/ to
use the page table library. Specifically, some ARM Mali GPUs use the
ARM page table formats.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Joerg Roedel <joro@8bytes.org>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: iommu@lists.linux-foundation.org
Cc: linux-mediatek@lists.infradead.org
Cc: linux-arm-msm@vger.kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
drivers/iommu/arm-smmu-v3.c
drivers/iommu/arm-smmu.c
drivers/iommu/io-pgtable-arm-v7s.c
drivers/iommu/io-pgtable-arm.c
drivers/iommu/io-pgtable.c
drivers/iommu/io-pgtable.h [deleted file]
drivers/iommu/ipmmu-vmsa.c
drivers/iommu/msm_iommu.c
drivers/iommu/mtk_iommu.h
drivers/iommu/qcom_iommu.c
include/linux/io-pgtable.h [new file with mode: 0644]

index 0d284029dc73579e62a3d06905de387ca81a7dd5..d3880010c6cfc8c073789807d54cad1fc64f8ad1 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/dma-iommu.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
+#include <linux/io-pgtable.h>
 #include <linux/iommu.h>
 #include <linux/iopoll.h>
 #include <linux/init.h>
@@ -32,8 +33,6 @@
 
 #include <linux/amba/bus.h>
 
-#include "io-pgtable.h"
-
 /* MMIO registers */
 #define ARM_SMMU_IDR0                  0x0
 #define IDR0_ST_LVL                    GENMASK(28, 27)
index af18a7e7f91724d62e7b042d14ecc602418713d9..045d938841640c375f13dbbd3997d5df919a782a 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/io-64-nonatomic-hi-lo.h>
+#include <linux/io-pgtable.h>
 #include <linux/iommu.h>
 #include <linux/iopoll.h>
 #include <linux/init.h>
@@ -56,7 +57,6 @@
 #include <linux/amba/bus.h>
 #include <linux/fsl/mc.h>
 
-#include "io-pgtable.h"
 #include "arm-smmu-regs.h"
 
 #define ARM_MMU500_ACTLR_CPRE          (1 << 1)
index cec29bf45c9bd79d38e4f6c7e97052ca9363255f..75a8273d1ae98e319c08b1f50bed8ea8ef27aa6c 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/atomic.h>
 #include <linux/dma-mapping.h>
 #include <linux/gfp.h>
+#include <linux/io-pgtable.h>
 #include <linux/iommu.h>
 #include <linux/kernel.h>
 #include <linux/kmemleak.h>
@@ -45,8 +46,6 @@
 
 #include <asm/barrier.h>
 
-#include "io-pgtable.h"
-
 /* Struct accessors */
 #define io_pgtable_to_data(x)                                          \
        container_of((x), struct arm_v7s_io_pgtable, iop)
index 237cacd4a62b87685202d3c95f7cf0cd2e4920d8..d3700ec15cbde1ecc6dafa25277573a020e065d8 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <linux/atomic.h>
 #include <linux/bitops.h>
+#include <linux/io-pgtable.h>
 #include <linux/iommu.h>
 #include <linux/kernel.h>
 #include <linux/sizes.h>
@@ -31,8 +32,6 @@
 
 #include <asm/barrier.h>
 
-#include "io-pgtable.h"
-
 #define ARM_LPAE_MAX_ADDR_BITS         52
 #define ARM_LPAE_S2_MAX_CONCAT_PAGES   16
 #define ARM_LPAE_MAX_LEVELS            4
index 127558d83667966b4056fc34ad98de88c87e217b..93f2880be6c67ccede1e19f45025379fdd4859cf 100644 (file)
  */
 
 #include <linux/bug.h>
+#include <linux/io-pgtable.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 
-#include "io-pgtable.h"
-
 static const struct io_pgtable_init_fns *
 io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
 #ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE
@@ -61,6 +60,7 @@ struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
 
        return &iop->ops;
 }
+EXPORT_SYMBOL_GPL(alloc_io_pgtable_ops);
 
 /*
  * It is the IOMMU driver's responsibility to ensure that the page table
@@ -77,3 +77,4 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops)
        io_pgtable_tlb_flush_all(iop);
        io_pgtable_init_table[iop->fmt]->free(iop);
 }
+EXPORT_SYMBOL_GPL(free_io_pgtable_ops);
diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h
deleted file mode 100644 (file)
index 47d5ae5..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __IO_PGTABLE_H
-#define __IO_PGTABLE_H
-#include <linux/bitops.h>
-
-/*
- * Public API for use by IOMMU drivers
- */
-enum io_pgtable_fmt {
-       ARM_32_LPAE_S1,
-       ARM_32_LPAE_S2,
-       ARM_64_LPAE_S1,
-       ARM_64_LPAE_S2,
-       ARM_V7S,
-       IO_PGTABLE_NUM_FMTS,
-};
-
-/**
- * struct iommu_gather_ops - IOMMU callbacks for TLB and page table management.
- *
- * @tlb_flush_all: Synchronously invalidate the entire TLB context.
- * @tlb_add_flush: Queue up a TLB invalidation for a virtual address range.
- * @tlb_sync:      Ensure any queued TLB invalidation has taken effect, and
- *                 any corresponding page table updates are visible to the
- *                 IOMMU.
- *
- * Note that these can all be called in atomic context and must therefore
- * not block.
- */
-struct iommu_gather_ops {
-       void (*tlb_flush_all)(void *cookie);
-       void (*tlb_add_flush)(unsigned long iova, size_t size, size_t granule,
-                             bool leaf, void *cookie);
-       void (*tlb_sync)(void *cookie);
-};
-
-/**
- * struct io_pgtable_cfg - Configuration data for a set of page tables.
- *
- * @quirks:        A bitmap of hardware quirks that require some special
- *                 action by the low-level page table allocator.
- * @pgsize_bitmap: A bitmap of page sizes supported by this set of page
- *                 tables.
- * @ias:           Input address (iova) size, in bits.
- * @oas:           Output address (paddr) size, in bits.
- * @tlb:           TLB management callbacks for this set of tables.
- * @iommu_dev:     The device representing the DMA configuration for the
- *                 page table walker.
- */
-struct io_pgtable_cfg {
-       /*
-        * IO_PGTABLE_QUIRK_ARM_NS: (ARM formats) Set NS and NSTABLE bits in
-        *      stage 1 PTEs, for hardware which insists on validating them
-        *      even in non-secure state where they should normally be ignored.
-        *
-        * IO_PGTABLE_QUIRK_NO_PERMS: Ignore the IOMMU_READ, IOMMU_WRITE and
-        *      IOMMU_NOEXEC flags and map everything with full access, for
-        *      hardware which does not implement the permissions of a given
-        *      format, and/or requires some format-specific default value.
-        *
-        * IO_PGTABLE_QUIRK_TLBI_ON_MAP: If the format forbids caching invalid
-        *      (unmapped) entries but the hardware might do so anyway, perform
-        *      TLB maintenance when mapping as well as when unmapping.
-        *
-        * IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 9 in all
-        *      PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit
-        *      when the SoC is in "4GB mode" and they can only access the high
-        *      remap of DRAM (0x1_00000000 to 0x1_ffffffff).
-        *
-        * IO_PGTABLE_QUIRK_NO_DMA: Guarantees that the tables will only ever
-        *      be accessed by a fully cache-coherent IOMMU or CPU (e.g. for a
-        *      software-emulated IOMMU), such that pagetable updates need not
-        *      be treated as explicit DMA data.
-        *
-        * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
-        *      on unmap, for DMA domains using the flush queue mechanism for
-        *      delayed invalidation.
-        */
-       #define IO_PGTABLE_QUIRK_ARM_NS         BIT(0)
-       #define IO_PGTABLE_QUIRK_NO_PERMS       BIT(1)
-       #define IO_PGTABLE_QUIRK_TLBI_ON_MAP    BIT(2)
-       #define IO_PGTABLE_QUIRK_ARM_MTK_4GB    BIT(3)
-       #define IO_PGTABLE_QUIRK_NO_DMA         BIT(4)
-       #define IO_PGTABLE_QUIRK_NON_STRICT     BIT(5)
-       unsigned long                   quirks;
-       unsigned long                   pgsize_bitmap;
-       unsigned int                    ias;
-       unsigned int                    oas;
-       const struct iommu_gather_ops   *tlb;
-       struct device                   *iommu_dev;
-
-       /* Low-level data specific to the table format */
-       union {
-               struct {
-                       u64     ttbr[2];
-                       u64     tcr;
-                       u64     mair[2];
-               } arm_lpae_s1_cfg;
-
-               struct {
-                       u64     vttbr;
-                       u64     vtcr;
-               } arm_lpae_s2_cfg;
-
-               struct {
-                       u32     ttbr[2];
-                       u32     tcr;
-                       u32     nmrr;
-                       u32     prrr;
-               } arm_v7s_cfg;
-       };
-};
-
-/**
- * struct io_pgtable_ops - Page table manipulation API for IOMMU drivers.
- *
- * @map:          Map a physically contiguous memory region.
- * @unmap:        Unmap a physically contiguous memory region.
- * @iova_to_phys: Translate iova to physical address.
- *
- * These functions map directly onto the iommu_ops member functions with
- * the same names.
- */
-struct io_pgtable_ops {
-       int (*map)(struct io_pgtable_ops *ops, unsigned long iova,
-                  phys_addr_t paddr, size_t size, int prot);
-       size_t (*unmap)(struct io_pgtable_ops *ops, unsigned long iova,
-                       size_t size);
-       phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
-                                   unsigned long iova);
-};
-
-/**
- * alloc_io_pgtable_ops() - Allocate a page table allocator for use by an IOMMU.
- *
- * @fmt:    The page table format.
- * @cfg:    The page table configuration. This will be modified to represent
- *          the configuration actually provided by the allocator (e.g. the
- *          pgsize_bitmap may be restricted).
- * @cookie: An opaque token provided by the IOMMU driver and passed back to
- *          the callback routines in cfg->tlb.
- */
-struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
-                                           struct io_pgtable_cfg *cfg,
-                                           void *cookie);
-
-/**
- * free_io_pgtable_ops() - Free an io_pgtable_ops structure. The caller
- *                         *must* ensure that the page table is no longer
- *                         live, but the TLB can be dirty.
- *
- * @ops: The ops returned from alloc_io_pgtable_ops.
- */
-void free_io_pgtable_ops(struct io_pgtable_ops *ops);
-
-
-/*
- * Internal structures for page table allocator implementations.
- */
-
-/**
- * struct io_pgtable - Internal structure describing a set of page tables.
- *
- * @fmt:    The page table format.
- * @cookie: An opaque token provided by the IOMMU driver and passed back to
- *          any callback routines.
- * @cfg:    A copy of the page table configuration.
- * @ops:    The page table operations in use for this set of page tables.
- */
-struct io_pgtable {
-       enum io_pgtable_fmt     fmt;
-       void                    *cookie;
-       struct io_pgtable_cfg   cfg;
-       struct io_pgtable_ops   ops;
-};
-
-#define io_pgtable_ops_to_pgtable(x) container_of((x), struct io_pgtable, ops)
-
-static inline void io_pgtable_tlb_flush_all(struct io_pgtable *iop)
-{
-       iop->cfg.tlb->tlb_flush_all(iop->cookie);
-}
-
-static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop,
-               unsigned long iova, size_t size, size_t granule, bool leaf)
-{
-       iop->cfg.tlb->tlb_add_flush(iova, size, granule, leaf, iop->cookie);
-}
-
-static inline void io_pgtable_tlb_sync(struct io_pgtable *iop)
-{
-       iop->cfg.tlb->tlb_sync(iop->cookie);
-}
-
-/**
- * struct io_pgtable_init_fns - Alloc/free a set of page tables for a
- *                              particular format.
- *
- * @alloc: Allocate a set of page tables described by cfg.
- * @free:  Free the page tables associated with iop.
- */
-struct io_pgtable_init_fns {
-       struct io_pgtable *(*alloc)(struct io_pgtable_cfg *cfg, void *cookie);
-       void (*free)(struct io_pgtable *iop);
-};
-
-extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns;
-extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s2_init_fns;
-extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns;
-extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns;
-extern struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns;
-
-#endif /* __IO_PGTABLE_H */
index 7a4529c61c19f3d4c531fdbe18d77d44c70aca66..9a380c10655e182d35d9f6c170336aeaa05030f6 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/io-pgtable.h>
 #include <linux/iommu.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -35,8 +36,6 @@
 #define arm_iommu_detach_device(...)   do {} while (0)
 #endif
 
-#include "io-pgtable.h"
-
 #define IPMMU_CTX_MAX 8
 
 struct ipmmu_features {
index fc4270733f11fad52179aecf7206fa02ce53b81d..ef7d1f995d6b0c11a1b87af5c6ac742f12a59d8e 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/io-pgtable.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
@@ -37,7 +38,6 @@
 
 #include "msm_iommu_hw-8xxx.h"
 #include "msm_iommu.h"
-#include "io-pgtable.h"
 
 #define MRC(reg, processor, op1, crn, crm, op2)                                \
 __asm__ __volatile__ (                                                 \
index 778498b8633fc63d4383ee0975741a8acffb3b5f..62c2c3e8c5dfb1148e933aa1fdd91f2033158f3b 100644 (file)
 #include <linux/component.h>
 #include <linux/device.h>
 #include <linux/io.h>
+#include <linux/io-pgtable.h>
 #include <linux/iommu.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <soc/mediatek/smi.h>
 
-#include "io-pgtable.h"
-
 struct mtk_iommu_suspend_reg {
        u32                             standard_axi_mode;
        u32                             dcm_dis;
index d8595f0a987d66bbec2a897646813cdc55a1cd07..8cdd3f0595138a09cdf1ebfc62fce48bdcfb9890 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/io-64-nonatomic-hi-lo.h>
+#include <linux/io-pgtable.h>
 #include <linux/iommu.h>
 #include <linux/iopoll.h>
 #include <linux/kconfig.h>
@@ -42,7 +43,6 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 
-#include "io-pgtable.h"
 #include "arm-smmu-regs.h"
 
 #define SMMU_INTR_SEL_NS     0x2000
diff --git a/include/linux/io-pgtable.h b/include/linux/io-pgtable.h
new file mode 100644 (file)
index 0000000..47d5ae5
--- /dev/null
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __IO_PGTABLE_H
+#define __IO_PGTABLE_H
+#include <linux/bitops.h>
+
+/*
+ * Public API for use by IOMMU drivers
+ */
+enum io_pgtable_fmt {
+       ARM_32_LPAE_S1,
+       ARM_32_LPAE_S2,
+       ARM_64_LPAE_S1,
+       ARM_64_LPAE_S2,
+       ARM_V7S,
+       IO_PGTABLE_NUM_FMTS,
+};
+
+/**
+ * struct iommu_gather_ops - IOMMU callbacks for TLB and page table management.
+ *
+ * @tlb_flush_all: Synchronously invalidate the entire TLB context.
+ * @tlb_add_flush: Queue up a TLB invalidation for a virtual address range.
+ * @tlb_sync:      Ensure any queued TLB invalidation has taken effect, and
+ *                 any corresponding page table updates are visible to the
+ *                 IOMMU.
+ *
+ * Note that these can all be called in atomic context and must therefore
+ * not block.
+ */
+struct iommu_gather_ops {
+       void (*tlb_flush_all)(void *cookie);
+       void (*tlb_add_flush)(unsigned long iova, size_t size, size_t granule,
+                             bool leaf, void *cookie);
+       void (*tlb_sync)(void *cookie);
+};
+
+/**
+ * struct io_pgtable_cfg - Configuration data for a set of page tables.
+ *
+ * @quirks:        A bitmap of hardware quirks that require some special
+ *                 action by the low-level page table allocator.
+ * @pgsize_bitmap: A bitmap of page sizes supported by this set of page
+ *                 tables.
+ * @ias:           Input address (iova) size, in bits.
+ * @oas:           Output address (paddr) size, in bits.
+ * @tlb:           TLB management callbacks for this set of tables.
+ * @iommu_dev:     The device representing the DMA configuration for the
+ *                 page table walker.
+ */
+struct io_pgtable_cfg {
+       /*
+        * IO_PGTABLE_QUIRK_ARM_NS: (ARM formats) Set NS and NSTABLE bits in
+        *      stage 1 PTEs, for hardware which insists on validating them
+        *      even in non-secure state where they should normally be ignored.
+        *
+        * IO_PGTABLE_QUIRK_NO_PERMS: Ignore the IOMMU_READ, IOMMU_WRITE and
+        *      IOMMU_NOEXEC flags and map everything with full access, for
+        *      hardware which does not implement the permissions of a given
+        *      format, and/or requires some format-specific default value.
+        *
+        * IO_PGTABLE_QUIRK_TLBI_ON_MAP: If the format forbids caching invalid
+        *      (unmapped) entries but the hardware might do so anyway, perform
+        *      TLB maintenance when mapping as well as when unmapping.
+        *
+        * IO_PGTABLE_QUIRK_ARM_MTK_4GB: (ARM v7s format) Set bit 9 in all
+        *      PTEs, for Mediatek IOMMUs which treat it as a 33rd address bit
+        *      when the SoC is in "4GB mode" and they can only access the high
+        *      remap of DRAM (0x1_00000000 to 0x1_ffffffff).
+        *
+        * IO_PGTABLE_QUIRK_NO_DMA: Guarantees that the tables will only ever
+        *      be accessed by a fully cache-coherent IOMMU or CPU (e.g. for a
+        *      software-emulated IOMMU), such that pagetable updates need not
+        *      be treated as explicit DMA data.
+        *
+        * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
+        *      on unmap, for DMA domains using the flush queue mechanism for
+        *      delayed invalidation.
+        */
+       #define IO_PGTABLE_QUIRK_ARM_NS         BIT(0)
+       #define IO_PGTABLE_QUIRK_NO_PERMS       BIT(1)
+       #define IO_PGTABLE_QUIRK_TLBI_ON_MAP    BIT(2)
+       #define IO_PGTABLE_QUIRK_ARM_MTK_4GB    BIT(3)
+       #define IO_PGTABLE_QUIRK_NO_DMA         BIT(4)
+       #define IO_PGTABLE_QUIRK_NON_STRICT     BIT(5)
+       unsigned long                   quirks;
+       unsigned long                   pgsize_bitmap;
+       unsigned int                    ias;
+       unsigned int                    oas;
+       const struct iommu_gather_ops   *tlb;
+       struct device                   *iommu_dev;
+
+       /* Low-level data specific to the table format */
+       union {
+               struct {
+                       u64     ttbr[2];
+                       u64     tcr;
+                       u64     mair[2];
+               } arm_lpae_s1_cfg;
+
+               struct {
+                       u64     vttbr;
+                       u64     vtcr;
+               } arm_lpae_s2_cfg;
+
+               struct {
+                       u32     ttbr[2];
+                       u32     tcr;
+                       u32     nmrr;
+                       u32     prrr;
+               } arm_v7s_cfg;
+       };
+};
+
+/**
+ * struct io_pgtable_ops - Page table manipulation API for IOMMU drivers.
+ *
+ * @map:          Map a physically contiguous memory region.
+ * @unmap:        Unmap a physically contiguous memory region.
+ * @iova_to_phys: Translate iova to physical address.
+ *
+ * These functions map directly onto the iommu_ops member functions with
+ * the same names.
+ */
+struct io_pgtable_ops {
+       int (*map)(struct io_pgtable_ops *ops, unsigned long iova,
+                  phys_addr_t paddr, size_t size, int prot);
+       size_t (*unmap)(struct io_pgtable_ops *ops, unsigned long iova,
+                       size_t size);
+       phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
+                                   unsigned long iova);
+};
+
+/**
+ * alloc_io_pgtable_ops() - Allocate a page table allocator for use by an IOMMU.
+ *
+ * @fmt:    The page table format.
+ * @cfg:    The page table configuration. This will be modified to represent
+ *          the configuration actually provided by the allocator (e.g. the
+ *          pgsize_bitmap may be restricted).
+ * @cookie: An opaque token provided by the IOMMU driver and passed back to
+ *          the callback routines in cfg->tlb.
+ */
+struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
+                                           struct io_pgtable_cfg *cfg,
+                                           void *cookie);
+
+/**
+ * free_io_pgtable_ops() - Free an io_pgtable_ops structure. The caller
+ *                         *must* ensure that the page table is no longer
+ *                         live, but the TLB can be dirty.
+ *
+ * @ops: The ops returned from alloc_io_pgtable_ops.
+ */
+void free_io_pgtable_ops(struct io_pgtable_ops *ops);
+
+
+/*
+ * Internal structures for page table allocator implementations.
+ */
+
+/**
+ * struct io_pgtable - Internal structure describing a set of page tables.
+ *
+ * @fmt:    The page table format.
+ * @cookie: An opaque token provided by the IOMMU driver and passed back to
+ *          any callback routines.
+ * @cfg:    A copy of the page table configuration.
+ * @ops:    The page table operations in use for this set of page tables.
+ */
+struct io_pgtable {
+       enum io_pgtable_fmt     fmt;
+       void                    *cookie;
+       struct io_pgtable_cfg   cfg;
+       struct io_pgtable_ops   ops;
+};
+
+#define io_pgtable_ops_to_pgtable(x) container_of((x), struct io_pgtable, ops)
+
+static inline void io_pgtable_tlb_flush_all(struct io_pgtable *iop)
+{
+       iop->cfg.tlb->tlb_flush_all(iop->cookie);
+}
+
+static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop,
+               unsigned long iova, size_t size, size_t granule, bool leaf)
+{
+       iop->cfg.tlb->tlb_add_flush(iova, size, granule, leaf, iop->cookie);
+}
+
+static inline void io_pgtable_tlb_sync(struct io_pgtable *iop)
+{
+       iop->cfg.tlb->tlb_sync(iop->cookie);
+}
+
+/**
+ * struct io_pgtable_init_fns - Alloc/free a set of page tables for a
+ *                              particular format.
+ *
+ * @alloc: Allocate a set of page tables described by cfg.
+ * @free:  Free the page tables associated with iop.
+ */
+struct io_pgtable_init_fns {
+       struct io_pgtable *(*alloc)(struct io_pgtable_cfg *cfg, void *cookie);
+       void (*free)(struct io_pgtable *iop);
+};
+
+extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns;
+extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s2_init_fns;
+extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns;
+extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns;
+extern struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns;
+
+#endif /* __IO_PGTABLE_H */