aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/gntdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/gntdev.c')
-rw-r--r--drivers/xen/gntdev.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index f914b26cf0c2..afca14d9042e 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -83,6 +83,7 @@ struct grant_map {
83 struct ioctl_gntdev_grant_ref *grants; 83 struct ioctl_gntdev_grant_ref *grants;
84 struct gnttab_map_grant_ref *map_ops; 84 struct gnttab_map_grant_ref *map_ops;
85 struct gnttab_unmap_grant_ref *unmap_ops; 85 struct gnttab_unmap_grant_ref *unmap_ops;
86 struct gnttab_map_grant_ref *kmap_ops;
86 struct page **pages; 87 struct page **pages;
87}; 88};
88 89
@@ -113,22 +114,25 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
113 if (NULL == add) 114 if (NULL == add)
114 return NULL; 115 return NULL;
115 116
116 add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL); 117 add->grants = kcalloc(count, sizeof(add->grants[0]), GFP_KERNEL);
117 add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL); 118 add->map_ops = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL);
118 add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL); 119 add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL);
119 add->pages = kzalloc(sizeof(add->pages[0]) * count, GFP_KERNEL); 120 add->kmap_ops = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL);
121 add->pages = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL);
120 if (NULL == add->grants || 122 if (NULL == add->grants ||
121 NULL == add->map_ops || 123 NULL == add->map_ops ||
122 NULL == add->unmap_ops || 124 NULL == add->unmap_ops ||
125 NULL == add->kmap_ops ||
123 NULL == add->pages) 126 NULL == add->pages)
124 goto err; 127 goto err;
125 128
126 if (alloc_xenballooned_pages(count, add->pages)) 129 if (alloc_xenballooned_pages(count, add->pages, false /* lowmem */))
127 goto err; 130 goto err;
128 131
129 for (i = 0; i < count; i++) { 132 for (i = 0; i < count; i++) {
130 add->map_ops[i].handle = -1; 133 add->map_ops[i].handle = -1;
131 add->unmap_ops[i].handle = -1; 134 add->unmap_ops[i].handle = -1;
135 add->kmap_ops[i].handle = -1;
132 } 136 }
133 137
134 add->index = 0; 138 add->index = 0;
@@ -142,6 +146,7 @@ err:
142 kfree(add->grants); 146 kfree(add->grants);
143 kfree(add->map_ops); 147 kfree(add->map_ops);
144 kfree(add->unmap_ops); 148 kfree(add->unmap_ops);
149 kfree(add->kmap_ops);
145 kfree(add); 150 kfree(add);
146 return NULL; 151 return NULL;
147} 152}
@@ -188,9 +193,8 @@ static void gntdev_put_map(struct grant_map *map)
188 193
189 atomic_sub(map->count, &pages_mapped); 194 atomic_sub(map->count, &pages_mapped);
190 195
191 if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT) { 196 if (map->notify.flags & UNMAP_NOTIFY_SEND_EVENT)
192 notify_remote_via_evtchn(map->notify.event); 197 notify_remote_via_evtchn(map->notify.event);
193 }
194 198
195 if (map->pages) { 199 if (map->pages) {
196 if (!use_ptemod) 200 if (!use_ptemod)
@@ -243,10 +247,35 @@ static int map_grant_pages(struct grant_map *map)
243 gnttab_set_unmap_op(&map->unmap_ops[i], addr, 247 gnttab_set_unmap_op(&map->unmap_ops[i], addr,
244 map->flags, -1 /* handle */); 248 map->flags, -1 /* handle */);
245 } 249 }
250 } else {
251 /*
252 * Setup the map_ops corresponding to the pte entries pointing
253 * to the kernel linear addresses of the struct pages.
254 * These ptes are completely different from the user ptes dealt
255 * with find_grant_ptes.
256 */
257 for (i = 0; i < map->count; i++) {
258 unsigned level;
259 unsigned long address = (unsigned long)
260 pfn_to_kaddr(page_to_pfn(map->pages[i]));
261 pte_t *ptep;
262 u64 pte_maddr = 0;
263 BUG_ON(PageHighMem(map->pages[i]));
264
265 ptep = lookup_address(address, &level);
266 pte_maddr = arbitrary_virt_to_machine(ptep).maddr;
267 gnttab_set_map_op(&map->kmap_ops[i], pte_maddr,
268 map->flags |
269 GNTMAP_host_map |
270 GNTMAP_contains_pte,
271 map->grants[i].ref,
272 map->grants[i].domid);
273 }
246 } 274 }
247 275
248 pr_debug("map %d+%d\n", map->index, map->count); 276 pr_debug("map %d+%d\n", map->index, map->count);
249 err = gnttab_map_refs(map->map_ops, map->pages, map->count); 277 err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL,
278 map->pages, map->count);
250 if (err) 279 if (err)
251 return err; 280 return err;
252 281
@@ -462,13 +491,11 @@ static int gntdev_release(struct inode *inode, struct file *flip)
462 491
463 pr_debug("priv %p\n", priv); 492 pr_debug("priv %p\n", priv);
464 493
465 spin_lock(&priv->lock);
466 while (!list_empty(&priv->maps)) { 494 while (!list_empty(&priv->maps)) {
467 map = list_entry(priv->maps.next, struct grant_map, next); 495 map = list_entry(priv->maps.next, struct grant_map, next);
468 list_del(&map->next); 496 list_del(&map->next);
469 gntdev_put_map(map); 497 gntdev_put_map(map);
470 } 498 }
471 spin_unlock(&priv->lock);
472 499
473 if (use_ptemod) 500 if (use_ptemod)
474 mmu_notifier_unregister(&priv->mn, priv->mm); 501 mmu_notifier_unregister(&priv->mn, priv->mm);
@@ -532,10 +559,11 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv,
532 map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); 559 map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
533 if (map) { 560 if (map) {
534 list_del(&map->next); 561 list_del(&map->next);
535 gntdev_put_map(map);
536 err = 0; 562 err = 0;
537 } 563 }
538 spin_unlock(&priv->lock); 564 spin_unlock(&priv->lock);
565 if (map)
566 gntdev_put_map(map);
539 return err; 567 return err;
540} 568}
541 569