aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/gntdev.c
diff options
context:
space:
mode:
authorOleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>2018-07-20 05:01:47 -0400
committerBoris Ostrovsky <boris.ostrovsky@oracle.com>2018-07-26 23:05:14 -0400
commit1d314567553883d9f606cc59e8e66f465a4b6ccd (patch)
tree9ee9d40f11d02b35ca422ac32a18a3fbacab37b6 /drivers/xen/gntdev.c
parent975ef7ff81bb000af6e6c8e63e81f89f3468dcf7 (diff)
xen/gntdev: Make private routines/structures accessible
This is in preparation for adding support of DMA buffer functionality: make map/unmap related code and structures, used privately by gntdev, ready for dma-buf extension, which will re-use these. Rename corresponding structures as those become non-private to gntdev now. Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Diffstat (limited to 'drivers/xen/gntdev.c')
-rw-r--r--drivers/xen/gntdev.c134
1 files changed, 43 insertions, 91 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 173332f439d8..e03f50052f3e 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -6,6 +6,7 @@
6 * 6 *
7 * Copyright (c) 2006-2007, D G Murray. 7 * Copyright (c) 2006-2007, D G Murray.
8 * (c) 2009 Gerd Hoffmann <kraxel@redhat.com> 8 * (c) 2009 Gerd Hoffmann <kraxel@redhat.com>
9 * (c) 2018 Oleksandr Andrushchenko, EPAM Systems Inc.
9 * 10 *
10 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -26,10 +27,6 @@
26#include <linux/init.h> 27#include <linux/init.h>
27#include <linux/miscdevice.h> 28#include <linux/miscdevice.h>
28#include <linux/fs.h> 29#include <linux/fs.h>
29#include <linux/mm.h>
30#include <linux/mman.h>
31#include <linux/mmu_notifier.h>
32#include <linux/types.h>
33#include <linux/uaccess.h> 30#include <linux/uaccess.h>
34#include <linux/sched.h> 31#include <linux/sched.h>
35#include <linux/sched/mm.h> 32#include <linux/sched/mm.h>
@@ -50,6 +47,8 @@
50#include <asm/xen/hypervisor.h> 47#include <asm/xen/hypervisor.h>
51#include <asm/xen/hypercall.h> 48#include <asm/xen/hypercall.h>
52 49
50#include "gntdev-common.h"
51
53MODULE_LICENSE("GPL"); 52MODULE_LICENSE("GPL");
54MODULE_AUTHOR("Derek G. Murray <Derek.Murray@cl.cam.ac.uk>, " 53MODULE_AUTHOR("Derek G. Murray <Derek.Murray@cl.cam.ac.uk>, "
55 "Gerd Hoffmann <kraxel@redhat.com>"); 54 "Gerd Hoffmann <kraxel@redhat.com>");
@@ -65,73 +64,23 @@ static atomic_t pages_mapped = ATOMIC_INIT(0);
65static int use_ptemod; 64static int use_ptemod;
66#define populate_freeable_maps use_ptemod 65#define populate_freeable_maps use_ptemod
67 66
68struct gntdev_priv { 67static int unmap_grant_pages(struct gntdev_grant_map *map,
69 /* maps with visible offsets in the file descriptor */ 68 int offset, int pages);
70 struct list_head maps;
71 /* maps that are not visible; will be freed on munmap.
72 * Only populated if populate_freeable_maps == 1 */
73 struct list_head freeable_maps;
74 /* lock protects maps and freeable_maps */
75 struct mutex lock;
76 struct mm_struct *mm;
77 struct mmu_notifier mn;
78
79#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
80 /* Device for which DMA memory is allocated. */
81 struct device *dma_dev;
82#endif
83};
84
85struct unmap_notify {
86 int flags;
87 /* Address relative to the start of the grant_map */
88 int addr;
89 int event;
90};
91
92struct grant_map {
93 struct list_head next;
94 struct vm_area_struct *vma;
95 int index;
96 int count;
97 int flags;
98 refcount_t users;
99 struct unmap_notify notify;
100 struct ioctl_gntdev_grant_ref *grants;
101 struct gnttab_map_grant_ref *map_ops;
102 struct gnttab_unmap_grant_ref *unmap_ops;
103 struct gnttab_map_grant_ref *kmap_ops;
104 struct gnttab_unmap_grant_ref *kunmap_ops;
105 struct page **pages;
106 unsigned long pages_vm_start;
107
108#ifdef CONFIG_XEN_GRANT_DMA_ALLOC
109 /*
110 * If dmabuf_vaddr is not NULL then this mapping is backed by DMA
111 * capable memory.
112 */
113
114 struct device *dma_dev;
115 /* Flags used to create this DMA buffer: GNTDEV_DMA_FLAG_XXX. */
116 int dma_flags;
117 void *dma_vaddr;
118 dma_addr_t dma_bus_addr;
119 /* Needed to avoid allocation in gnttab_dma_free_pages(). */
120 xen_pfn_t *frames;
121#endif
122};
123
124static int unmap_grant_pages(struct grant_map *map, int offset, int pages);
125 69
126static struct miscdevice gntdev_miscdev; 70static struct miscdevice gntdev_miscdev;
127 71
128/* ------------------------------------------------------------------ */ 72/* ------------------------------------------------------------------ */
129 73
74bool gntdev_account_mapped_pages(int count)
75{
76 return atomic_add_return(count, &pages_mapped) > limit;
77}
78
130static void gntdev_print_maps(struct gntdev_priv *priv, 79static void gntdev_print_maps(struct gntdev_priv *priv,
131 char *text, int text_index) 80 char *text, int text_index)
132{ 81{
133#ifdef DEBUG 82#ifdef DEBUG
134 struct grant_map *map; 83 struct gntdev_grant_map *map;
135 84
136 pr_debug("%s: maps list (priv %p)\n", __func__, priv); 85 pr_debug("%s: maps list (priv %p)\n", __func__, priv);
137 list_for_each_entry(map, &priv->maps, next) 86 list_for_each_entry(map, &priv->maps, next)
@@ -141,7 +90,7 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
141#endif 90#endif
142} 91}
143 92
144static void gntdev_free_map(struct grant_map *map) 93static void gntdev_free_map(struct gntdev_grant_map *map)
145{ 94{
146 if (map == NULL) 95 if (map == NULL)
147 return; 96 return;
@@ -176,13 +125,13 @@ static void gntdev_free_map(struct grant_map *map)
176 kfree(map); 125 kfree(map);
177} 126}
178 127
179static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count, 128struct gntdev_grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count,
180 int dma_flags) 129 int dma_flags)
181{ 130{
182 struct grant_map *add; 131 struct gntdev_grant_map *add;
183 int i; 132 int i;
184 133
185 add = kzalloc(sizeof(struct grant_map), GFP_KERNEL); 134 add = kzalloc(sizeof(*add), GFP_KERNEL);
186 if (NULL == add) 135 if (NULL == add)
187 return NULL; 136 return NULL;
188 137
@@ -252,9 +201,9 @@ err:
252 return NULL; 201 return NULL;
253} 202}
254 203
255static void gntdev_add_map(struct gntdev_priv *priv, struct grant_map *add) 204void gntdev_add_map(struct gntdev_priv *priv, struct gntdev_grant_map *add)
256{ 205{
257 struct grant_map *map; 206 struct gntdev_grant_map *map;
258 207
259 list_for_each_entry(map, &priv->maps, next) { 208 list_for_each_entry(map, &priv->maps, next) {
260 if (add->index + add->count < map->index) { 209 if (add->index + add->count < map->index) {
@@ -269,10 +218,10 @@ done:
269 gntdev_print_maps(priv, "[new]", add->index); 218 gntdev_print_maps(priv, "[new]", add->index);
270} 219}
271 220
272static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, 221static struct gntdev_grant_map *gntdev_find_map_index(struct gntdev_priv *priv,
273 int index, int count) 222 int index, int count)
274{ 223{
275 struct grant_map *map; 224 struct gntdev_grant_map *map;
276 225
277 list_for_each_entry(map, &priv->maps, next) { 226 list_for_each_entry(map, &priv->maps, next) {
278 if (map->index != index) 227 if (map->index != index)
@@ -284,7 +233,7 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv,
284 return NULL; 233 return NULL;
285} 234}
286 235
287static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) 236void gntdev_put_map(struct gntdev_priv *priv, struct gntdev_grant_map *map)
288{ 237{
289 if (!map) 238 if (!map)
290 return; 239 return;
@@ -315,7 +264,7 @@ static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map)
315static int find_grant_ptes(pte_t *pte, pgtable_t token, 264static int find_grant_ptes(pte_t *pte, pgtable_t token,
316 unsigned long addr, void *data) 265 unsigned long addr, void *data)
317{ 266{
318 struct grant_map *map = data; 267 struct gntdev_grant_map *map = data;
319 unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT; 268 unsigned int pgnr = (addr - map->vma->vm_start) >> PAGE_SHIFT;
320 int flags = map->flags | GNTMAP_application_map | GNTMAP_contains_pte; 269 int flags = map->flags | GNTMAP_application_map | GNTMAP_contains_pte;
321 u64 pte_maddr; 270 u64 pte_maddr;
@@ -348,7 +297,7 @@ static int set_grant_ptes_as_special(pte_t *pte, pgtable_t token,
348} 297}
349#endif 298#endif
350 299
351static int map_grant_pages(struct grant_map *map) 300int gntdev_map_grant_pages(struct gntdev_grant_map *map)
352{ 301{
353 int i, err = 0; 302 int i, err = 0;
354 303
@@ -413,7 +362,8 @@ static int map_grant_pages(struct grant_map *map)
413 return err; 362 return err;
414} 363}
415 364
416static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) 365static int __unmap_grant_pages(struct gntdev_grant_map *map, int offset,
366 int pages)
417{ 367{
418 int i, err = 0; 368 int i, err = 0;
419 struct gntab_unmap_queue_data unmap_data; 369 struct gntab_unmap_queue_data unmap_data;
@@ -448,7 +398,8 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
448 return err; 398 return err;
449} 399}
450 400
451static int unmap_grant_pages(struct grant_map *map, int offset, int pages) 401static int unmap_grant_pages(struct gntdev_grant_map *map, int offset,
402 int pages)
452{ 403{
453 int range, err = 0; 404 int range, err = 0;
454 405
@@ -480,7 +431,7 @@ static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
480 431
481static void gntdev_vma_open(struct vm_area_struct *vma) 432static void gntdev_vma_open(struct vm_area_struct *vma)
482{ 433{
483 struct grant_map *map = vma->vm_private_data; 434 struct gntdev_grant_map *map = vma->vm_private_data;
484 435
485 pr_debug("gntdev_vma_open %p\n", vma); 436 pr_debug("gntdev_vma_open %p\n", vma);
486 refcount_inc(&map->users); 437 refcount_inc(&map->users);
@@ -488,7 +439,7 @@ static void gntdev_vma_open(struct vm_area_struct *vma)
488 439
489static void gntdev_vma_close(struct vm_area_struct *vma) 440static void gntdev_vma_close(struct vm_area_struct *vma)
490{ 441{
491 struct grant_map *map = vma->vm_private_data; 442 struct gntdev_grant_map *map = vma->vm_private_data;
492 struct file *file = vma->vm_file; 443 struct file *file = vma->vm_file;
493 struct gntdev_priv *priv = file->private_data; 444 struct gntdev_priv *priv = file->private_data;
494 445
@@ -512,7 +463,7 @@ static void gntdev_vma_close(struct vm_area_struct *vma)
512static struct page *gntdev_vma_find_special_page(struct vm_area_struct *vma, 463static struct page *gntdev_vma_find_special_page(struct vm_area_struct *vma,
513 unsigned long addr) 464 unsigned long addr)
514{ 465{
515 struct grant_map *map = vma->vm_private_data; 466 struct gntdev_grant_map *map = vma->vm_private_data;
516 467
517 return map->pages[(addr - map->pages_vm_start) >> PAGE_SHIFT]; 468 return map->pages[(addr - map->pages_vm_start) >> PAGE_SHIFT];
518} 469}
@@ -525,7 +476,7 @@ static const struct vm_operations_struct gntdev_vmops = {
525 476
526/* ------------------------------------------------------------------ */ 477/* ------------------------------------------------------------------ */
527 478
528static void unmap_if_in_range(struct grant_map *map, 479static void unmap_if_in_range(struct gntdev_grant_map *map,
529 unsigned long start, unsigned long end) 480 unsigned long start, unsigned long end)
530{ 481{
531 unsigned long mstart, mend; 482 unsigned long mstart, mend;
@@ -554,7 +505,7 @@ static void mn_invl_range_start(struct mmu_notifier *mn,
554 unsigned long start, unsigned long end) 505 unsigned long start, unsigned long end)
555{ 506{
556 struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); 507 struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
557 struct grant_map *map; 508 struct gntdev_grant_map *map;
558 509
559 mutex_lock(&priv->lock); 510 mutex_lock(&priv->lock);
560 list_for_each_entry(map, &priv->maps, next) { 511 list_for_each_entry(map, &priv->maps, next) {
@@ -570,7 +521,7 @@ static void mn_release(struct mmu_notifier *mn,
570 struct mm_struct *mm) 521 struct mm_struct *mm)
571{ 522{
572 struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); 523 struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
573 struct grant_map *map; 524 struct gntdev_grant_map *map;
574 int err; 525 int err;
575 526
576 mutex_lock(&priv->lock); 527 mutex_lock(&priv->lock);
@@ -651,13 +602,14 @@ static int gntdev_open(struct inode *inode, struct file *flip)
651static int gntdev_release(struct inode *inode, struct file *flip) 602static int gntdev_release(struct inode *inode, struct file *flip)
652{ 603{
653 struct gntdev_priv *priv = flip->private_data; 604 struct gntdev_priv *priv = flip->private_data;
654 struct grant_map *map; 605 struct gntdev_grant_map *map;
655 606
656 pr_debug("priv %p\n", priv); 607 pr_debug("priv %p\n", priv);
657 608
658 mutex_lock(&priv->lock); 609 mutex_lock(&priv->lock);
659 while (!list_empty(&priv->maps)) { 610 while (!list_empty(&priv->maps)) {
660 map = list_entry(priv->maps.next, struct grant_map, next); 611 map = list_entry(priv->maps.next,
612 struct gntdev_grant_map, next);
661 list_del(&map->next); 613 list_del(&map->next);
662 gntdev_put_map(NULL /* already removed */, map); 614 gntdev_put_map(NULL /* already removed */, map);
663 } 615 }
@@ -674,7 +626,7 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
674 struct ioctl_gntdev_map_grant_ref __user *u) 626 struct ioctl_gntdev_map_grant_ref __user *u)
675{ 627{
676 struct ioctl_gntdev_map_grant_ref op; 628 struct ioctl_gntdev_map_grant_ref op;
677 struct grant_map *map; 629 struct gntdev_grant_map *map;
678 int err; 630 int err;
679 631
680 if (copy_from_user(&op, u, sizeof(op)) != 0) 632 if (copy_from_user(&op, u, sizeof(op)) != 0)
@@ -688,7 +640,7 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv,
688 if (!map) 640 if (!map)
689 return err; 641 return err;
690 642
691 if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { 643 if (unlikely(gntdev_account_mapped_pages(op.count))) {
692 pr_debug("can't map: over limit\n"); 644 pr_debug("can't map: over limit\n");
693 gntdev_put_map(NULL, map); 645 gntdev_put_map(NULL, map);
694 return err; 646 return err;
@@ -715,7 +667,7 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
715 struct ioctl_gntdev_unmap_grant_ref __user *u) 667 struct ioctl_gntdev_unmap_grant_ref __user *u)
716{ 668{
717 struct ioctl_gntdev_unmap_grant_ref op; 669 struct ioctl_gntdev_unmap_grant_ref op;
718 struct grant_map *map; 670 struct gntdev_grant_map *map;
719 int err = -ENOENT; 671 int err = -ENOENT;
720 672
721 if (copy_from_user(&op, u, sizeof(op)) != 0) 673 if (copy_from_user(&op, u, sizeof(op)) != 0)
@@ -741,7 +693,7 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv,
741{ 693{
742 struct ioctl_gntdev_get_offset_for_vaddr op; 694 struct ioctl_gntdev_get_offset_for_vaddr op;
743 struct vm_area_struct *vma; 695 struct vm_area_struct *vma;
744 struct grant_map *map; 696 struct gntdev_grant_map *map;
745 int rv = -EINVAL; 697 int rv = -EINVAL;
746 698
747 if (copy_from_user(&op, u, sizeof(op)) != 0) 699 if (copy_from_user(&op, u, sizeof(op)) != 0)
@@ -772,7 +724,7 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv,
772static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) 724static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
773{ 725{
774 struct ioctl_gntdev_unmap_notify op; 726 struct ioctl_gntdev_unmap_notify op;
775 struct grant_map *map; 727 struct gntdev_grant_map *map;
776 int rc; 728 int rc;
777 int out_flags; 729 int out_flags;
778 unsigned int out_event; 730 unsigned int out_event;
@@ -1070,7 +1022,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
1070 struct gntdev_priv *priv = flip->private_data; 1022 struct gntdev_priv *priv = flip->private_data;
1071 int index = vma->vm_pgoff; 1023 int index = vma->vm_pgoff;
1072 int count = vma_pages(vma); 1024 int count = vma_pages(vma);
1073 struct grant_map *map; 1025 struct gntdev_grant_map *map;
1074 int i, err = -EINVAL; 1026 int i, err = -EINVAL;
1075 1027
1076 if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) 1028 if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED))
@@ -1127,7 +1079,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
1127 } 1079 }
1128 } 1080 }
1129 1081
1130 err = map_grant_pages(map); 1082 err = gntdev_map_grant_pages(map);
1131 if (err) 1083 if (err)
1132 goto out_put_map; 1084 goto out_put_map;
1133 1085