File Index
Files and directories
Sign in
FILE

io_pagetable.h

File preview with syntax highlighting.

linux-6.19.14/drivers/iommu/iommufd/io_pagetable.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES.
  3 *
  4 */
  5#ifndef __IO_PAGETABLE_H
  6#define __IO_PAGETABLE_H
  7
  8#include <linux/dma-buf.h>
  9#include <linux/interval_tree.h>
 10#include <linux/kref.h>
 11#include <linux/mutex.h>
 12#include <linux/xarray.h>
 13
 14#include "iommufd_private.h"
 15
 16struct iommu_domain;
 17
 18/*
 19 * Each io_pagetable is composed of intervals of areas which cover regions of
 20 * the iova that are backed by something. iova not covered by areas is not
 21 * populated in the page table. Each area is fully populated with pages.
 22 *
 23 * iovas are in byte units, but must be iopt->iova_alignment aligned.
 24 *
 25 * pages can be NULL, this means some other thread is still working on setting
 26 * up or tearing down the area. When observed under the write side of the
 27 * domain_rwsem a NULL pages must mean the area is still being setup and no
 28 * domains are filled.
 29 *
 30 * storage_domain points at an arbitrary iommu_domain that is holding the PFNs
 31 * for this area. It is locked by the pages->mutex. This simplifies the locking
 32 * as the pages code can rely on the storage_domain without having to get the
 33 * iopt->domains_rwsem.
 34 *
 35 * The io_pagetable::iova_rwsem protects node
 36 * The iopt_pages::mutex protects pages_node
 37 * iopt and iommu_prot are immutable
 38 * The pages::mutex protects num_accesses
 39 */
 40struct iopt_area {
 41	struct interval_tree_node node;
 42	struct interval_tree_node pages_node;
 43	struct io_pagetable *iopt;
 44	struct iopt_pages *pages;
 45	struct iommu_domain *storage_domain;
 46	/* How many bytes into the first page the area starts */
 47	unsigned int page_offset;
 48	/* IOMMU_READ, IOMMU_WRITE, etc */
 49	int iommu_prot;
 50	bool prevent_access : 1;
 51	unsigned int num_accesses;
 52	unsigned int num_locks;
 53};
 54
 55struct iopt_allowed {
 56	struct interval_tree_node node;
 57};
 58
 59struct iopt_reserved {
 60	struct interval_tree_node node;
 61	void *owner;
 62};
 63
 64int iopt_area_fill_domains(struct iopt_area *area, struct iopt_pages *pages);
 65void iopt_area_unfill_domains(struct iopt_area *area, struct iopt_pages *pages);
 66
 67int iopt_area_fill_domain(struct iopt_area *area, struct iommu_domain *domain);
 68void iopt_area_unfill_domain(struct iopt_area *area, struct iopt_pages *pages,
 69			     struct iommu_domain *domain);
 70void iopt_area_unmap_domain(struct iopt_area *area,
 71			    struct iommu_domain *domain);
 72
 73int iopt_dmabuf_track_domain(struct iopt_pages *pages, struct iopt_area *area,
 74			     struct iommu_domain *domain);
 75void iopt_dmabuf_untrack_domain(struct iopt_pages *pages,
 76				struct iopt_area *area,
 77				struct iommu_domain *domain);
 78int iopt_dmabuf_track_all_domains(struct iopt_area *area,
 79				  struct iopt_pages *pages);
 80void iopt_dmabuf_untrack_all_domains(struct iopt_area *area,
 81				     struct iopt_pages *pages);
 82
 83static inline unsigned long iopt_area_index(struct iopt_area *area)
 84{
 85	return area->pages_node.start;
 86}
 87
 88static inline unsigned long iopt_area_last_index(struct iopt_area *area)
 89{
 90	return area->pages_node.last;
 91}
 92
 93static inline unsigned long iopt_area_iova(struct iopt_area *area)
 94{
 95	return area->node.start;
 96}
 97
 98static inline unsigned long iopt_area_last_iova(struct iopt_area *area)
 99{
100	return area->node.last;
101}
102
103static inline size_t iopt_area_length(struct iopt_area *area)
104{
105	return (area->node.last - area->node.start) + 1;
106}
107
108/*
109 * Number of bytes from the start of the iopt_pages that the iova begins.
110 * iopt_area_start_byte() / PAGE_SIZE encodes the starting page index
111 * iopt_area_start_byte() % PAGE_SIZE encodes the offset within that page
112 */
113static inline unsigned long iopt_area_start_byte(struct iopt_area *area,
114						 unsigned long iova)
115{
116	if (IS_ENABLED(CONFIG_IOMMUFD_TEST))
117		WARN_ON(iova < iopt_area_iova(area) ||
118			iova > iopt_area_last_iova(area));
119	return (iova - iopt_area_iova(area)) + area->page_offset +
120	       iopt_area_index(area) * PAGE_SIZE;
121}
122
123static inline unsigned long iopt_area_iova_to_index(struct iopt_area *area,
124						    unsigned long iova)
125{
126	return iopt_area_start_byte(area, iova) / PAGE_SIZE;
127}
128
129#define __make_iopt_iter(name)                                                 \
130	static inline struct iopt_##name *iopt_##name##_iter_first(            \
131		struct io_pagetable *iopt, unsigned long start,                \
132		unsigned long last)                                            \
133	{                                                                      \
134		struct interval_tree_node *node;                               \
135									       \
136		lockdep_assert_held(&iopt->iova_rwsem);                        \
137		node = interval_tree_iter_first(&iopt->name##_itree, start,    \
138						last);                         \
139		if (!node)                                                     \
140			return NULL;                                           \
141		return container_of(node, struct iopt_##name, node);           \
142	}                                                                      \
143	static inline struct iopt_##name *iopt_##name##_iter_next(             \
144		struct iopt_##name *last_node, unsigned long start,            \
145		unsigned long last)                                            \
146	{                                                                      \
147		struct interval_tree_node *node;                               \
148									       \
149		node = interval_tree_iter_next(&last_node->node, start, last); \
150		if (!node)                                                     \
151			return NULL;                                           \
152		return container_of(node, struct iopt_##name, node);           \
153	}
154
155__make_iopt_iter(area)
156__make_iopt_iter(allowed)
157__make_iopt_iter(reserved)
158
159struct iopt_area_contig_iter {
160	unsigned long cur_iova;
161	unsigned long last_iova;
162	struct iopt_area *area;
163};
164struct iopt_area *iopt_area_contig_init(struct iopt_area_contig_iter *iter,
165					struct io_pagetable *iopt,
166					unsigned long iova,
167					unsigned long last_iova);
168struct iopt_area *iopt_area_contig_next(struct iopt_area_contig_iter *iter);
169
170static inline bool iopt_area_contig_done(struct iopt_area_contig_iter *iter)
171{
172	return iter->area && iter->last_iova <= iopt_area_last_iova(iter->area);
173}
174
175/*
176 * Iterate over a contiguous list of areas that span the iova,last_iova range.
177 * The caller must check iopt_area_contig_done() after the loop to see if
178 * contiguous areas existed.
179 */
180#define iopt_for_each_contig_area(iter, area, iopt, iova, last_iova)          \
181	for (area = iopt_area_contig_init(iter, iopt, iova, last_iova); area; \
182	     area = iopt_area_contig_next(iter))
183
184enum {
185	IOPT_PAGES_ACCOUNT_NONE = 0,
186	IOPT_PAGES_ACCOUNT_USER = 1,
187	IOPT_PAGES_ACCOUNT_MM = 2,
188	IOPT_PAGES_ACCOUNT_MODE_NUM = 3,
189};
190
191enum iopt_address_type {
192	IOPT_ADDRESS_USER = 0,
193	IOPT_ADDRESS_FILE,
194	IOPT_ADDRESS_DMABUF,
195};
196
197struct iopt_pages_dmabuf_track {
198	struct iommu_domain *domain;
199	struct iopt_area *area;
200	struct list_head elm;
201};
202
203struct iopt_pages_dmabuf {
204	struct dma_buf_attachment *attach;
205	struct dma_buf_phys_vec phys;
206	/* Always PAGE_SIZE aligned */
207	unsigned long start;
208	struct list_head tracker;
209};
210
211/*
212 * This holds a pinned page list for multiple areas of IO address space. The
213 * pages always originate from a linear chunk of userspace VA. Multiple
214 * io_pagetable's, through their iopt_area's, can share a single iopt_pages
215 * which avoids multi-pinning and double accounting of page consumption.
216 *
217 * indexes in this structure are measured in PAGE_SIZE units, are 0 based from
218 * the start of the uptr and extend to npages. pages are pinned dynamically
219 * according to the intervals in the access_itree and domains_itree, npinned
220 * records the current number of pages pinned.
221 */
222struct iopt_pages {
223	struct kref kref;
224	struct mutex mutex;
225	size_t npages;
226	size_t npinned;
227	size_t last_npinned;
228	struct task_struct *source_task;
229	struct mm_struct *source_mm;
230	struct user_struct *source_user;
231	enum iopt_address_type type;
232	union {
233		void __user *uptr;		/* IOPT_ADDRESS_USER */
234		struct {			/* IOPT_ADDRESS_FILE */
235			struct file *file;
236			unsigned long start;
237		};
238		/* IOPT_ADDRESS_DMABUF */
239		struct iopt_pages_dmabuf dmabuf;
240	};
241	bool writable:1;
242	u8 account_mode;
243
244	struct xarray pinned_pfns;
245	/* Of iopt_pages_access::node */
246	struct rb_root_cached access_itree;
247	/* Of iopt_area::pages_node */
248	struct rb_root_cached domains_itree;
249};
250
251static inline bool iopt_is_dmabuf(struct iopt_pages *pages)
252{
253	if (!IS_ENABLED(CONFIG_DMA_SHARED_BUFFER))
254		return false;
255	return pages->type == IOPT_ADDRESS_DMABUF;
256}
257
258static inline bool iopt_dmabuf_revoked(struct iopt_pages *pages)
259{
260	lockdep_assert_held(&pages->mutex);
261	if (iopt_is_dmabuf(pages))
262		return pages->dmabuf.phys.len == 0;
263	return false;
264}
265
266struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
267					 unsigned long length, bool writable);
268struct iopt_pages *iopt_alloc_file_pages(struct file *file,
269					 unsigned long start_byte,
270					 unsigned long start,
271					 unsigned long length, bool writable);
272struct iopt_pages *iopt_alloc_dmabuf_pages(struct iommufd_ctx *ictx,
273					   struct dma_buf *dmabuf,
274					   unsigned long start_byte,
275					   unsigned long start,
276					   unsigned long length, bool writable);
277void iopt_release_pages(struct kref *kref);
278static inline void iopt_put_pages(struct iopt_pages *pages)
279{
280	kref_put(&pages->kref, iopt_release_pages);
281}
282
283void iopt_pages_fill_from_xarray(struct iopt_pages *pages, unsigned long start,
284				 unsigned long last, struct page **out_pages);
285int iopt_pages_fill_xarray(struct iopt_pages *pages, unsigned long start,
286			   unsigned long last, struct page **out_pages);
287void iopt_pages_unfill_xarray(struct iopt_pages *pages, unsigned long start,
288			      unsigned long last);
289
290int iopt_area_add_access(struct iopt_area *area, unsigned long start,
291			 unsigned long last, struct page **out_pages,
292			 unsigned int flags, bool lock_area);
293void iopt_area_remove_access(struct iopt_area *area, unsigned long start,
294			     unsigned long last, bool unlock_area);
295int iopt_pages_rw_access(struct iopt_pages *pages, unsigned long start_byte,
296			 void *data, unsigned long length, unsigned int flags);
297
298/*
299 * Each interval represents an active iopt_access_pages(), it acts as an
300 * interval lock that keeps the PFNs pinned and stored in the xarray.
301 */
302struct iopt_pages_access {
303	struct interval_tree_node node;
304	unsigned int users;
305};
306
307struct pfn_reader_user;
308
309int iopt_pages_update_pinned(struct iopt_pages *pages, unsigned long npages,
310			     bool inc, struct pfn_reader_user *user);
311
312#endif
~/ Read-only file preview.