aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2014-11-14 12:16:49 -0500
committerWill Deacon <will.deacon@arm.com>2015-01-19 09:46:43 -0500
commitfdb1d7be7c4d452e9735aeb2b60ae8a2fcf0a514 (patch)
tree108b994fbb99aed086654bae4badabc13d9d7adf /drivers/iommu
parenteaa27f34e91a14cdceed26ed6c6793ec1d186115 (diff)
iommu: introduce generic page table allocation framework
This patch introduces a generic framework for allocating page tables for an IOMMU. There are a number of reasons we want to do this: - It avoids duplication of complex table management code in IOMMU drivers that use the same page table format - It removes any coupling with the CPU table format (and even the architecture!) - It defines an API for IOMMU TLB maintenance Tested-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/Kconfig8
-rw-r--r--drivers/iommu/Makefile1
-rw-r--r--drivers/iommu/io-pgtable.c71
-rw-r--r--drivers/iommu/io-pgtable.h128
4 files changed, 208 insertions, 0 deletions
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 325188eef1c1..3faaa41db8ff 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -13,6 +13,14 @@ menuconfig IOMMU_SUPPORT
13 13
14if IOMMU_SUPPORT 14if IOMMU_SUPPORT
15 15
16menu "Generic IOMMU Pagetable Support"
17
18# Selected by the actual pagetable implementations
19config IOMMU_IO_PGTABLE
20 bool
21
22endmenu
23
16config OF_IOMMU 24config OF_IOMMU
17 def_bool y 25 def_bool y
18 depends on OF && IOMMU_API 26 depends on OF && IOMMU_API
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 7b976f294a69..701c9516e2ae 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,6 +1,7 @@
1obj-$(CONFIG_IOMMU_API) += iommu.o 1obj-$(CONFIG_IOMMU_API) += iommu.o
2obj-$(CONFIG_IOMMU_API) += iommu-traces.o 2obj-$(CONFIG_IOMMU_API) += iommu-traces.o
3obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o 3obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
4obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
4obj-$(CONFIG_OF_IOMMU) += of_iommu.o 5obj-$(CONFIG_OF_IOMMU) += of_iommu.o
5obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o 6obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
6obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o 7obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c
new file mode 100644
index 000000000000..f664a1ca49cf
--- /dev/null
+++ b/drivers/iommu/io-pgtable.c
@@ -0,0 +1,71 @@
1/*
2 * Generic page table allocator for IOMMUs.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Copyright (C) 2014 ARM Limited
17 *
18 * Author: Will Deacon <will.deacon@arm.com>
19 */
20
21#include <linux/bug.h>
22#include <linux/kernel.h>
23#include <linux/types.h>
24
25#include "io-pgtable.h"
26
27static const struct io_pgtable_init_fns *
28io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] =
29{
30};
31
32struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
33 struct io_pgtable_cfg *cfg,
34 void *cookie)
35{
36 struct io_pgtable *iop;
37 const struct io_pgtable_init_fns *fns;
38
39 if (fmt >= IO_PGTABLE_NUM_FMTS)
40 return NULL;
41
42 fns = io_pgtable_init_table[fmt];
43 if (!fns)
44 return NULL;
45
46 iop = fns->alloc(cfg, cookie);
47 if (!iop)
48 return NULL;
49
50 iop->fmt = fmt;
51 iop->cookie = cookie;
52 iop->cfg = *cfg;
53
54 return &iop->ops;
55}
56
57/*
58 * It is the IOMMU driver's responsibility to ensure that the page table
59 * is no longer accessible to the walker by this point.
60 */
61void free_io_pgtable_ops(struct io_pgtable_ops *ops)
62{
63 struct io_pgtable *iop;
64
65 if (!ops)
66 return;
67
68 iop = container_of(ops, struct io_pgtable, ops);
69 iop->cfg.tlb->tlb_flush_all(iop->cookie);
70 io_pgtable_init_table[iop->fmt]->free(iop);
71}
diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h
new file mode 100644
index 000000000000..fdd792c37698
--- /dev/null
+++ b/drivers/iommu/io-pgtable.h
@@ -0,0 +1,128 @@
1#ifndef __IO_PGTABLE_H
2#define __IO_PGTABLE_H
3
4/*
5 * Public API for use by IOMMU drivers
6 */
7enum io_pgtable_fmt {
8 IO_PGTABLE_NUM_FMTS,
9};
10
11/**
12 * struct iommu_gather_ops - IOMMU callbacks for TLB and page table management.
13 *
14 * @tlb_flush_all: Synchronously invalidate the entire TLB context.
15 * @tlb_add_flush: Queue up a TLB invalidation for a virtual address range.
16 * @tlb_sync: Ensure any queue TLB invalidation has taken effect.
17 * @flush_pgtable: Ensure page table updates are visible to the IOMMU.
18 *
19 * Note that these can all be called in atomic context and must therefore
20 * not block.
21 */
22struct iommu_gather_ops {
23 void (*tlb_flush_all)(void *cookie);
24 void (*tlb_add_flush)(unsigned long iova, size_t size, bool leaf,
25 void *cookie);
26 void (*tlb_sync)(void *cookie);
27 void (*flush_pgtable)(void *ptr, size_t size, void *cookie);
28};
29
30/**
31 * struct io_pgtable_cfg - Configuration data for a set of page tables.
32 *
33 * @quirks: A bitmap of hardware quirks that require some special
34 * action by the low-level page table allocator.
35 * @pgsize_bitmap: A bitmap of page sizes supported by this set of page
36 * tables.
37 * @ias: Input address (iova) size, in bits.
38 * @oas: Output address (paddr) size, in bits.
39 * @tlb: TLB management callbacks for this set of tables.
40 */
41struct io_pgtable_cfg {
42 int quirks; /* IO_PGTABLE_QUIRK_* */
43 unsigned long pgsize_bitmap;
44 unsigned int ias;
45 unsigned int oas;
46 const struct iommu_gather_ops *tlb;
47
48 /* Low-level data specific to the table format */
49 union {
50 };
51};
52
53/**
54 * struct io_pgtable_ops - Page table manipulation API for IOMMU drivers.
55 *
56 * @map: Map a physically contiguous memory region.
57 * @unmap: Unmap a physically contiguous memory region.
58 * @iova_to_phys: Translate iova to physical address.
59 *
60 * These functions map directly onto the iommu_ops member functions with
61 * the same names.
62 */
63struct io_pgtable_ops {
64 int (*map)(struct io_pgtable_ops *ops, unsigned long iova,
65 phys_addr_t paddr, size_t size, int prot);
66 int (*unmap)(struct io_pgtable_ops *ops, unsigned long iova,
67 size_t size);
68 phys_addr_t (*iova_to_phys)(struct io_pgtable_ops *ops,
69 unsigned long iova);
70};
71
72/**
73 * alloc_io_pgtable_ops() - Allocate a page table allocator for use by an IOMMU.
74 *
75 * @fmt: The page table format.
76 * @cfg: The page table configuration. This will be modified to represent
77 * the configuration actually provided by the allocator (e.g. the
78 * pgsize_bitmap may be restricted).
79 * @cookie: An opaque token provided by the IOMMU driver and passed back to
80 * the callback routines in cfg->tlb.
81 */
82struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
83 struct io_pgtable_cfg *cfg,
84 void *cookie);
85
86/**
87 * free_io_pgtable_ops() - Free an io_pgtable_ops structure. The caller
88 * *must* ensure that the page table is no longer
89 * live, but the TLB can be dirty.
90 *
91 * @ops: The ops returned from alloc_io_pgtable_ops.
92 */
93void free_io_pgtable_ops(struct io_pgtable_ops *ops);
94
95
96/*
97 * Internal structures for page table allocator implementations.
98 */
99
100/**
101 * struct io_pgtable - Internal structure describing a set of page tables.
102 *
103 * @fmt: The page table format.
104 * @cookie: An opaque token provided by the IOMMU driver and passed back to
105 * any callback routines.
106 * @cfg: A copy of the page table configuration.
107 * @ops: The page table operations in use for this set of page tables.
108 */
109struct io_pgtable {
110 enum io_pgtable_fmt fmt;
111 void *cookie;
112 struct io_pgtable_cfg cfg;
113 struct io_pgtable_ops ops;
114};
115
116/**
117 * struct io_pgtable_init_fns - Alloc/free a set of page tables for a
118 * particular format.
119 *
120 * @alloc: Allocate a set of page tables described by cfg.
121 * @free: Free the page tables associated with iop.
122 */
123struct io_pgtable_init_fns {
124 struct io_pgtable *(*alloc)(struct io_pgtable_cfg *cfg, void *cookie);
125 void (*free)(struct io_pgtable *iop);
126};
127
128#endif /* __IO_PGTABLE_H */