xref: /linux/drivers/vdpa/vdpa_user/iova_domain.c (revision fab183d632628381b466a41479489541ac0e29a0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * MMU-based software IOTLB.
4  *
5  * Copyright (C) 2020-2021 Bytedance Inc. and/or its affiliates. All rights reserved.
6  *
7  * Author: Xie Yongji <xieyongji@bytedance.com>
8  *
9  */
10 
11 #include <linux/slab.h>
12 #include <linux/file.h>
13 #include <linux/anon_inodes.h>
14 #include <linux/highmem.h>
15 #include <linux/moduleparam.h>
16 #include <linux/vmalloc.h>
17 #include <linux/vdpa.h>
18 
19 #include "iova_domain.h"
20 
21 static int max_iotlb_entries = 2048;
22 module_param(max_iotlb_entries, int, 0444);
23 MODULE_PARM_DESC(max_iotlb_entries,
24 		 "Maximum number of iotlb entries. (default: 2048)");
25 
vduse_iotlb_add_range(struct vduse_iova_domain * domain,u64 start,u64 last,u64 addr,unsigned int perm,struct file * file,u64 offset)26 static int vduse_iotlb_add_range(struct vduse_iova_domain *domain,
27 				 u64 start, u64 last,
28 				 u64 addr, unsigned int perm,
29 				 struct file *file, u64 offset)
30 {
31 	struct vdpa_map_file *map_file;
32 	int ret;
33 
34 	map_file = kmalloc_obj(*map_file, GFP_ATOMIC);
35 	if (!map_file)
36 		return -ENOMEM;
37 
38 	map_file->file = get_file(file);
39 	map_file->offset = offset;
40 
41 	ret = vhost_iotlb_add_range_ctx(domain->iotlb, start, last,
42 					addr, perm, map_file);
43 	if (ret) {
44 		fput(map_file->file);
45 		kfree(map_file);
46 		return ret;
47 	}
48 	return 0;
49 }
50 
vduse_iotlb_del_range(struct vduse_iova_domain * domain,u64 start,u64 last)51 static void vduse_iotlb_del_range(struct vduse_iova_domain *domain,
52 				  u64 start, u64 last)
53 {
54 	struct vdpa_map_file *map_file;
55 	struct vhost_iotlb_map *map;
56 
57 	while ((map = vhost_iotlb_itree_first(domain->iotlb, start, last))) {
58 		map_file = (struct vdpa_map_file *)map->opaque;
59 		fput(map_file->file);
60 		kfree(map_file);
61 		vhost_iotlb_map_free(domain->iotlb, map);
62 	}
63 }
64 
vduse_domain_set_map(struct vduse_iova_domain * domain,struct vhost_iotlb * iotlb)65 int vduse_domain_set_map(struct vduse_iova_domain *domain,
66 			 struct vhost_iotlb *iotlb)
67 {
68 	struct vdpa_map_file *map_file;
69 	struct vhost_iotlb_map *map;
70 	u64 start = 0ULL, last = ULLONG_MAX;
71 	int ret;
72 
73 	spin_lock(&domain->iotlb_lock);
74 	vduse_iotlb_del_range(domain, start, last);
75 
76 	for (map = vhost_iotlb_itree_first(iotlb, start, last); map;
77 	     map = vhost_iotlb_itree_next(map, start, last)) {
78 		map_file = (struct vdpa_map_file *)map->opaque;
79 		ret = vduse_iotlb_add_range(domain, map->start, map->last,
80 					    map->addr, map->perm,
81 					    map_file->file,
82 					    map_file->offset);
83 		if (ret)
84 			goto err;
85 	}
86 	spin_unlock(&domain->iotlb_lock);
87 
88 	return 0;
89 err:
90 	vduse_iotlb_del_range(domain, start, last);
91 	spin_unlock(&domain->iotlb_lock);
92 	return ret;
93 }
94 
vduse_domain_clear_map(struct vduse_iova_domain * domain,struct vhost_iotlb * iotlb)95 void vduse_domain_clear_map(struct vduse_iova_domain *domain,
96 			    struct vhost_iotlb *iotlb)
97 {
98 	struct vhost_iotlb_map *map;
99 	u64 start = 0ULL, last = ULLONG_MAX;
100 
101 	spin_lock(&domain->iotlb_lock);
102 	for (map = vhost_iotlb_itree_first(iotlb, start, last); map;
103 	     map = vhost_iotlb_itree_next(map, start, last)) {
104 		vduse_iotlb_del_range(domain, map->start, map->last);
105 	}
106 	spin_unlock(&domain->iotlb_lock);
107 }
108 
vduse_domain_map_bounce_page(struct vduse_iova_domain * domain,u64 iova,u64 size,u64 paddr)109 static int vduse_domain_map_bounce_page(struct vduse_iova_domain *domain,
110 					 u64 iova, u64 size, u64 paddr)
111 {
112 	struct vduse_bounce_map *map, *head_map;
113 	struct page *tmp_page;
114 	u64 last = iova + size - 1;
115 
116 	while (iova <= last) {
117 		/*
118 		 * When PAGE_SIZE is larger than 4KB, multiple adjacent bounce_maps will
119 		 * point to the same memory page of PAGE_SIZE. Since bounce_maps originate
120 		 * from IO requests, we may not be able to guarantee that the orig_phys
121 		 * values of all IO requests within the same 64KB memory page are contiguous.
122 		 * Therefore, we need to store them separately.
123 		 *
124 		 * Bounce pages are allocated on demand. As a result, it may occur that
125 		 * multiple bounce pages corresponding to the same 64KB memory page attempt
126 		 * to allocate memory simultaneously, so we use cmpxchg to handle this
127 		 * concurrency.
128 		 */
129 		map = &domain->bounce_maps[iova >> BOUNCE_MAP_SHIFT];
130 		if (!map->bounce_page) {
131 			head_map = &domain->bounce_maps[(iova & PAGE_MASK) >> BOUNCE_MAP_SHIFT];
132 			if (!head_map->bounce_page) {
133 				tmp_page = alloc_page(GFP_ATOMIC | __GFP_ZERO);
134 				if (!tmp_page)
135 					return -ENOMEM;
136 				if (cmpxchg(&head_map->bounce_page, NULL, tmp_page))
137 					__free_page(tmp_page);
138 			}
139 			map->bounce_page = head_map->bounce_page;
140 		}
141 		map->orig_phys = paddr;
142 		paddr += BOUNCE_MAP_SIZE;
143 		iova += BOUNCE_MAP_SIZE;
144 	}
145 	return 0;
146 }
147 
vduse_domain_unmap_bounce_page(struct vduse_iova_domain * domain,u64 iova,u64 size)148 static void vduse_domain_unmap_bounce_page(struct vduse_iova_domain *domain,
149 					   u64 iova, u64 size)
150 {
151 	struct vduse_bounce_map *map;
152 	u64 last = iova + size - 1;
153 
154 	while (iova <= last) {
155 		map = &domain->bounce_maps[iova >> BOUNCE_MAP_SHIFT];
156 		map->orig_phys = INVALID_PHYS_ADDR;
157 		iova += BOUNCE_MAP_SIZE;
158 	}
159 }
160 
offset_in_bounce_page(dma_addr_t addr)161 static unsigned int offset_in_bounce_page(dma_addr_t addr)
162 {
163 	return (addr & ~BOUNCE_MAP_MASK);
164 }
165 
do_bounce(phys_addr_t orig,void * addr,size_t size,enum dma_data_direction dir)166 static void do_bounce(phys_addr_t orig, void *addr, size_t size,
167 		      enum dma_data_direction dir)
168 {
169 	unsigned long pfn = PFN_DOWN(orig);
170 	unsigned int offset = offset_in_page(orig);
171 	struct page *page;
172 	unsigned int sz = 0;
173 
174 	while (size) {
175 		sz = min_t(size_t, PAGE_SIZE - offset, size);
176 
177 		page = pfn_to_page(pfn);
178 		if (dir == DMA_TO_DEVICE)
179 			memcpy_from_page(addr, page, offset, sz);
180 		else
181 			memcpy_to_page(page, offset, addr, sz);
182 
183 		size -= sz;
184 		pfn++;
185 		addr += sz;
186 		offset = 0;
187 	}
188 }
189 
vduse_domain_bounce(struct vduse_iova_domain * domain,dma_addr_t iova,size_t size,enum dma_data_direction dir)190 static void vduse_domain_bounce(struct vduse_iova_domain *domain,
191 				dma_addr_t iova, size_t size,
192 				enum dma_data_direction dir)
193 {
194 	struct vduse_bounce_map *map;
195 	struct page *page;
196 	unsigned int offset, head_offset;
197 	void *addr;
198 	size_t sz;
199 
200 	if (iova >= domain->bounce_size)
201 		return;
202 
203 	while (size) {
204 		map = &domain->bounce_maps[iova >> BOUNCE_MAP_SHIFT];
205 		head_offset = offset_in_page(iova);
206 		offset = offset_in_bounce_page(iova);
207 		sz = min_t(size_t, BOUNCE_MAP_SIZE - offset, size);
208 
209 		if (WARN_ON(!map->bounce_page ||
210 			    map->orig_phys == INVALID_PHYS_ADDR))
211 			return;
212 
213 		page = domain->user_bounce_pages ?
214 		       map->user_bounce_page : map->bounce_page;
215 
216 		addr = kmap_local_page(page);
217 		do_bounce(map->orig_phys + offset, addr + head_offset, sz, dir);
218 		kunmap_local(addr);
219 		size -= sz;
220 		iova += sz;
221 	}
222 }
223 
224 static struct page *
vduse_domain_get_coherent_page(struct vduse_iova_domain * domain,u64 iova)225 vduse_domain_get_coherent_page(struct vduse_iova_domain *domain, u64 iova)
226 {
227 	u64 start = iova & PAGE_MASK;
228 	u64 last = start + PAGE_SIZE - 1;
229 	struct vhost_iotlb_map *map;
230 	struct page *page = NULL;
231 
232 	spin_lock(&domain->iotlb_lock);
233 	map = vhost_iotlb_itree_first(domain->iotlb, start, last);
234 	if (!map)
235 		goto out;
236 
237 	page = pfn_to_page((map->addr + iova - map->start) >> PAGE_SHIFT);
238 	get_page(page);
239 out:
240 	spin_unlock(&domain->iotlb_lock);
241 
242 	return page;
243 }
244 
245 static struct page *
vduse_domain_get_bounce_page(struct vduse_iova_domain * domain,u64 iova)246 vduse_domain_get_bounce_page(struct vduse_iova_domain *domain, u64 iova)
247 {
248 	struct vduse_bounce_map *map;
249 	struct page *page = NULL;
250 
251 	read_lock(&domain->bounce_lock);
252 	map = &domain->bounce_maps[iova >> BOUNCE_MAP_SHIFT];
253 	if (domain->user_bounce_pages || !map->bounce_page)
254 		goto out;
255 
256 	page = map->bounce_page;
257 	get_page(page);
258 out:
259 	read_unlock(&domain->bounce_lock);
260 
261 	return page;
262 }
263 
264 static void
vduse_domain_free_kernel_bounce_pages(struct vduse_iova_domain * domain)265 vduse_domain_free_kernel_bounce_pages(struct vduse_iova_domain *domain)
266 {
267 	struct vduse_bounce_map *map;
268 	unsigned long pfn, bounce_pfns;
269 
270 	bounce_pfns = domain->bounce_size >> BOUNCE_MAP_SHIFT;
271 
272 	for (pfn = 0; pfn < bounce_pfns; pfn++) {
273 		map = &domain->bounce_maps[pfn];
274 		if (WARN_ON(map->orig_phys != INVALID_PHYS_ADDR))
275 			continue;
276 
277 		if (!map->bounce_page)
278 			continue;
279 
280 		if (!((pfn << BOUNCE_MAP_SHIFT) & ~PAGE_MASK))
281 			__free_page(map->bounce_page);
282 		map->bounce_page = NULL;
283 	}
284 }
285 
vduse_domain_add_user_bounce_pages(struct vduse_iova_domain * domain,struct page ** pages,int count)286 int vduse_domain_add_user_bounce_pages(struct vduse_iova_domain *domain,
287 				       struct page **pages, int count)
288 {
289 	struct vduse_bounce_map *map, *head_map;
290 	int i, j, ret;
291 	int inner_pages = PAGE_SIZE / BOUNCE_MAP_SIZE;
292 	int bounce_pfns = domain->bounce_size >> BOUNCE_MAP_SHIFT;
293 	struct page *head_page = NULL;
294 	bool need_copy;
295 
296 	/* Now we don't support partial mapping */
297 	if (count != (domain->bounce_size >> PAGE_SHIFT))
298 		return -EINVAL;
299 
300 	write_lock(&domain->bounce_lock);
301 	ret = -EEXIST;
302 	if (domain->user_bounce_pages)
303 		goto out;
304 
305 	for (i = 0; i < count; i++) {
306 		need_copy = false;
307 		head_map = &domain->bounce_maps[(i * inner_pages)];
308 		head_page = head_map->bounce_page;
309 		for (j = 0; j < inner_pages; j++) {
310 			if ((i * inner_pages + j) >= bounce_pfns)
311 				break;
312 			map = &domain->bounce_maps[(i * inner_pages + j)];
313 			/* Copy kernel page to user page if it's in use */
314 			if ((head_page) && (map->orig_phys != INVALID_PHYS_ADDR))
315 				need_copy = true;
316 			map->user_bounce_page = pages[i];
317 		}
318 		get_page(pages[i]);
319 		if ((head_page) && (need_copy))
320 			memcpy_to_page(pages[i], 0,
321 				       page_address(head_page),
322 				       PAGE_SIZE);
323 	}
324 	domain->user_bounce_pages = true;
325 	ret = 0;
326 out:
327 	write_unlock(&domain->bounce_lock);
328 
329 	return ret;
330 }
331 
vduse_domain_remove_user_bounce_pages(struct vduse_iova_domain * domain)332 void vduse_domain_remove_user_bounce_pages(struct vduse_iova_domain *domain)
333 {
334 	struct vduse_bounce_map *map, *head_map;
335 	unsigned long i, j, count;
336 	int inner_pages = PAGE_SIZE / BOUNCE_MAP_SIZE;
337 	int bounce_pfns = domain->bounce_size >> BOUNCE_MAP_SHIFT;
338 	struct page *head_page = NULL;
339 	bool need_copy;
340 
341 	write_lock(&domain->bounce_lock);
342 	if (!domain->user_bounce_pages)
343 		goto out;
344 
345 	count = domain->bounce_size >> PAGE_SHIFT;
346 	for (i = 0; i < count; i++) {
347 		need_copy = false;
348 		head_map = &domain->bounce_maps[(i * inner_pages)];
349 		if (WARN_ON(!head_map->user_bounce_page))
350 			continue;
351 		head_page = head_map->user_bounce_page;
352 
353 		for (j = 0; j < inner_pages; j++) {
354 			if ((i * inner_pages + j) >= bounce_pfns)
355 				break;
356 			map = &domain->bounce_maps[(i * inner_pages + j)];
357 			if (WARN_ON(!map->user_bounce_page))
358 				continue;
359 			/* Copy user page to kernel page if it's in use */
360 			if ((map->orig_phys != INVALID_PHYS_ADDR) && (head_map->bounce_page))
361 				need_copy = true;
362 			map->user_bounce_page = NULL;
363 		}
364 		if (need_copy)
365 			memcpy_from_page(page_address(head_map->bounce_page),
366 					 head_page, 0, PAGE_SIZE);
367 		put_page(head_page);
368 	}
369 	domain->user_bounce_pages = false;
370 out:
371 	write_unlock(&domain->bounce_lock);
372 }
373 
vduse_domain_reset_bounce_map(struct vduse_iova_domain * domain)374 void vduse_domain_reset_bounce_map(struct vduse_iova_domain *domain)
375 {
376 	if (!domain->bounce_map)
377 		return;
378 
379 	spin_lock(&domain->iotlb_lock);
380 	if (!domain->bounce_map)
381 		goto unlock;
382 
383 	vduse_iotlb_del_range(domain, 0, domain->bounce_size - 1);
384 	domain->bounce_map = 0;
385 unlock:
386 	spin_unlock(&domain->iotlb_lock);
387 }
388 
vduse_domain_init_bounce_map(struct vduse_iova_domain * domain)389 static int vduse_domain_init_bounce_map(struct vduse_iova_domain *domain)
390 {
391 	int ret = 0;
392 
393 	if (domain->bounce_map)
394 		return 0;
395 
396 	spin_lock(&domain->iotlb_lock);
397 	if (domain->bounce_map)
398 		goto unlock;
399 
400 	ret = vduse_iotlb_add_range(domain, 0, domain->bounce_size - 1,
401 				    0, VHOST_MAP_RW, domain->file, 0);
402 	if (ret)
403 		goto unlock;
404 
405 	domain->bounce_map = 1;
406 unlock:
407 	spin_unlock(&domain->iotlb_lock);
408 	return ret;
409 }
410 
411 static dma_addr_t
vduse_domain_alloc_iova(struct iova_domain * iovad,unsigned long size,unsigned long limit)412 vduse_domain_alloc_iova(struct iova_domain *iovad,
413 			unsigned long size, unsigned long limit)
414 {
415 	unsigned long shift = iova_shift(iovad);
416 	unsigned long iova_len = iova_align(iovad, size) >> shift;
417 	unsigned long iova_pfn;
418 
419 	iova_pfn = alloc_iova_fast(iovad, iova_len, limit >> shift, true);
420 
421 	return (dma_addr_t)iova_pfn << shift;
422 }
423 
vduse_domain_free_iova(struct iova_domain * iovad,dma_addr_t iova,size_t size)424 static void vduse_domain_free_iova(struct iova_domain *iovad,
425 				   dma_addr_t iova, size_t size)
426 {
427 	unsigned long shift = iova_shift(iovad);
428 	unsigned long iova_len = iova_align(iovad, size) >> shift;
429 
430 	free_iova_fast(iovad, iova >> shift, iova_len);
431 }
432 
vduse_domain_sync_single_for_device(struct vduse_iova_domain * domain,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir)433 void vduse_domain_sync_single_for_device(struct vduse_iova_domain *domain,
434 				      dma_addr_t dma_addr, size_t size,
435 				      enum dma_data_direction dir)
436 {
437 	read_lock(&domain->bounce_lock);
438 	if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
439 		vduse_domain_bounce(domain, dma_addr, size, DMA_TO_DEVICE);
440 	read_unlock(&domain->bounce_lock);
441 }
442 
vduse_domain_sync_single_for_cpu(struct vduse_iova_domain * domain,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir)443 void vduse_domain_sync_single_for_cpu(struct vduse_iova_domain *domain,
444 				      dma_addr_t dma_addr, size_t size,
445 				      enum dma_data_direction dir)
446 {
447 	read_lock(&domain->bounce_lock);
448 	if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
449 		vduse_domain_bounce(domain, dma_addr, size, DMA_FROM_DEVICE);
450 	read_unlock(&domain->bounce_lock);
451 }
452 
vduse_domain_map_page(struct vduse_iova_domain * domain,struct page * page,unsigned long offset,size_t size,enum dma_data_direction dir,unsigned long attrs)453 dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain,
454 				 struct page *page, unsigned long offset,
455 				 size_t size, enum dma_data_direction dir,
456 				 unsigned long attrs)
457 {
458 	struct iova_domain *iovad = &domain->stream_iovad;
459 	unsigned long limit = domain->bounce_size - 1;
460 	phys_addr_t pa = page_to_phys(page) + offset;
461 	dma_addr_t iova = vduse_domain_alloc_iova(iovad, size, limit);
462 
463 	if (!iova)
464 		return DMA_MAPPING_ERROR;
465 
466 	if (vduse_domain_init_bounce_map(domain))
467 		goto err;
468 
469 	read_lock(&domain->bounce_lock);
470 	if (vduse_domain_map_bounce_page(domain, (u64)iova, (u64)size, pa))
471 		goto err_unlock;
472 
473 	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
474 	    (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
475 		vduse_domain_bounce(domain, iova, size, DMA_TO_DEVICE);
476 
477 	read_unlock(&domain->bounce_lock);
478 
479 	return iova;
480 err_unlock:
481 	read_unlock(&domain->bounce_lock);
482 err:
483 	vduse_domain_free_iova(iovad, iova, size);
484 	return DMA_MAPPING_ERROR;
485 }
486 
vduse_domain_unmap_page(struct vduse_iova_domain * domain,dma_addr_t dma_addr,size_t size,enum dma_data_direction dir,unsigned long attrs)487 void vduse_domain_unmap_page(struct vduse_iova_domain *domain,
488 			     dma_addr_t dma_addr, size_t size,
489 			     enum dma_data_direction dir, unsigned long attrs)
490 {
491 	struct iova_domain *iovad = &domain->stream_iovad;
492 	read_lock(&domain->bounce_lock);
493 	if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
494 	    (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
495 		vduse_domain_bounce(domain, dma_addr, size, DMA_FROM_DEVICE);
496 
497 	vduse_domain_unmap_bounce_page(domain, (u64)dma_addr, (u64)size);
498 	read_unlock(&domain->bounce_lock);
499 	vduse_domain_free_iova(iovad, dma_addr, size);
500 }
501 
vduse_domain_alloc_coherent(struct vduse_iova_domain * domain,size_t size,void * orig)502 dma_addr_t vduse_domain_alloc_coherent(struct vduse_iova_domain *domain,
503 				       size_t size, void *orig)
504 {
505 	struct iova_domain *iovad = &domain->consistent_iovad;
506 	unsigned long limit = domain->iova_limit;
507 	dma_addr_t iova = vduse_domain_alloc_iova(iovad, size, limit);
508 
509 	if (!iova)
510 		return DMA_MAPPING_ERROR;
511 
512 	spin_lock(&domain->iotlb_lock);
513 	if (vduse_iotlb_add_range(domain, (u64)iova, (u64)iova + size - 1,
514 				  virt_to_phys(orig), VHOST_MAP_RW,
515 				  domain->file, (u64)iova)) {
516 		spin_unlock(&domain->iotlb_lock);
517 		goto err;
518 	}
519 	spin_unlock(&domain->iotlb_lock);
520 
521 	return iova;
522 
523 err:
524 	vduse_domain_free_iova(iovad, iova, size);
525 
526 	return DMA_MAPPING_ERROR;
527 }
528 
vduse_domain_free_coherent(struct vduse_iova_domain * domain,size_t size,dma_addr_t dma_addr,unsigned long attrs)529 void vduse_domain_free_coherent(struct vduse_iova_domain *domain, size_t size,
530 				dma_addr_t dma_addr, unsigned long attrs)
531 {
532 	struct iova_domain *iovad = &domain->consistent_iovad;
533 	struct vhost_iotlb_map *map;
534 	struct vdpa_map_file *map_file;
535 
536 	spin_lock(&domain->iotlb_lock);
537 	map = vhost_iotlb_itree_first(domain->iotlb, (u64)dma_addr,
538 				      (u64)dma_addr + size - 1);
539 	if (WARN_ON(!map)) {
540 		spin_unlock(&domain->iotlb_lock);
541 		return;
542 	}
543 	map_file = (struct vdpa_map_file *)map->opaque;
544 	fput(map_file->file);
545 	kfree(map_file);
546 	vhost_iotlb_map_free(domain->iotlb, map);
547 	spin_unlock(&domain->iotlb_lock);
548 
549 	vduse_domain_free_iova(iovad, dma_addr, size);
550 }
551 
vduse_domain_mmap_fault(struct vm_fault * vmf)552 static vm_fault_t vduse_domain_mmap_fault(struct vm_fault *vmf)
553 {
554 	struct vduse_iova_domain *domain = vmf->vma->vm_private_data;
555 	unsigned long iova = vmf->pgoff << PAGE_SHIFT;
556 	struct page *page;
557 
558 	if (!domain)
559 		return VM_FAULT_SIGBUS;
560 
561 	if (iova < domain->bounce_size)
562 		page = vduse_domain_get_bounce_page(domain, iova);
563 	else
564 		page = vduse_domain_get_coherent_page(domain, iova);
565 
566 	if (!page)
567 		return VM_FAULT_SIGBUS;
568 
569 	vmf->page = page;
570 
571 	return 0;
572 }
573 
574 static const struct vm_operations_struct vduse_domain_mmap_ops = {
575 	.fault = vduse_domain_mmap_fault,
576 };
577 
vduse_domain_mmap(struct file * file,struct vm_area_struct * vma)578 static int vduse_domain_mmap(struct file *file, struct vm_area_struct *vma)
579 {
580 	struct vduse_iova_domain *domain = file->private_data;
581 
582 	vm_flags_set(vma, VM_DONTDUMP | VM_DONTEXPAND);
583 	vma->vm_private_data = domain;
584 	vma->vm_ops = &vduse_domain_mmap_ops;
585 
586 	return 0;
587 }
588 
vduse_domain_release(struct inode * inode,struct file * file)589 static int vduse_domain_release(struct inode *inode, struct file *file)
590 {
591 	struct vduse_iova_domain *domain = file->private_data;
592 
593 	spin_lock(&domain->iotlb_lock);
594 	vduse_iotlb_del_range(domain, 0, ULLONG_MAX);
595 	vduse_domain_remove_user_bounce_pages(domain);
596 	vduse_domain_free_kernel_bounce_pages(domain);
597 	spin_unlock(&domain->iotlb_lock);
598 	put_iova_domain(&domain->stream_iovad);
599 	put_iova_domain(&domain->consistent_iovad);
600 	vhost_iotlb_free(domain->iotlb);
601 	vfree(domain->bounce_maps);
602 	kfree(domain);
603 
604 	return 0;
605 }
606 
607 static const struct file_operations vduse_domain_fops = {
608 	.owner = THIS_MODULE,
609 	.mmap = vduse_domain_mmap,
610 	.release = vduse_domain_release,
611 };
612 
vduse_domain_destroy(struct vduse_iova_domain * domain)613 void vduse_domain_destroy(struct vduse_iova_domain *domain)
614 {
615 	fput(domain->file);
616 }
617 
618 struct vduse_iova_domain *
vduse_domain_create(unsigned long iova_limit,size_t bounce_size)619 vduse_domain_create(unsigned long iova_limit, size_t bounce_size)
620 {
621 	struct vduse_iova_domain *domain;
622 	struct file *file;
623 	struct vduse_bounce_map *map;
624 	unsigned long pfn, bounce_pfns;
625 	int ret;
626 
627 	bounce_pfns = PAGE_ALIGN(bounce_size) >> BOUNCE_MAP_SHIFT;
628 	if (iova_limit <= bounce_size)
629 		return NULL;
630 
631 	if (max_iotlb_entries <= 0)
632 		return NULL;
633 
634 	domain = kzalloc_obj(*domain);
635 	if (!domain)
636 		return NULL;
637 
638 	domain->iotlb = vhost_iotlb_alloc(max_iotlb_entries, 0);
639 	if (!domain->iotlb)
640 		goto err_iotlb;
641 
642 	domain->iova_limit = iova_limit;
643 	domain->bounce_size = PAGE_ALIGN(bounce_size);
644 	domain->bounce_maps = vzalloc(bounce_pfns *
645 				sizeof(struct vduse_bounce_map));
646 	if (!domain->bounce_maps)
647 		goto err_map;
648 
649 	for (pfn = 0; pfn < bounce_pfns; pfn++) {
650 		map = &domain->bounce_maps[pfn];
651 		map->orig_phys = INVALID_PHYS_ADDR;
652 	}
653 	file = anon_inode_getfile("[vduse-domain]", &vduse_domain_fops,
654 				domain, O_RDWR);
655 	if (IS_ERR(file))
656 		goto err_file;
657 
658 	domain->file = file;
659 	rwlock_init(&domain->bounce_lock);
660 	spin_lock_init(&domain->iotlb_lock);
661 	init_iova_domain(&domain->stream_iovad,
662 			BOUNCE_MAP_SIZE, IOVA_START_PFN);
663 	ret = iova_domain_init_rcaches(&domain->stream_iovad);
664 	if (ret)
665 		goto err_iovad_stream;
666 	init_iova_domain(&domain->consistent_iovad,
667 			PAGE_SIZE, bounce_pfns);
668 	ret = iova_domain_init_rcaches(&domain->consistent_iovad);
669 	if (ret)
670 		goto err_iovad_consistent;
671 
672 	return domain;
673 err_iovad_consistent:
674 	put_iova_domain(&domain->stream_iovad);
675 err_iovad_stream:
676 	fput(file);
677 err_file:
678 	vfree(domain->bounce_maps);
679 err_map:
680 	vhost_iotlb_free(domain->iotlb);
681 err_iotlb:
682 	kfree(domain);
683 	return NULL;
684 }
685 
vduse_domain_init(void)686 int vduse_domain_init(void)
687 {
688 	return iova_cache_get();
689 }
690 
vduse_domain_exit(void)691 void vduse_domain_exit(void)
692 {
693 	iova_cache_put();
694 }
695