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.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 7b9b1d1b75a..3e3603f3524 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
@@ -116,10 +117,12 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
116 add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL); 117 add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL);
117 add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL); 118 add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL);
118 add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL); 119 add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL);
120 add->kmap_ops = kzalloc(sizeof(add->kmap_ops[0]) * count, GFP_KERNEL);
119 add->pages = kzalloc(sizeof(add->pages[0]) * count, GFP_KERNEL); 121 add->pages = kzalloc(sizeof(add->pages[0]) * count, 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
@@ -129,6 +132,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
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}
@@ -243,10 +248,35 @@ static int map_grant_pages(struct grant_map *map)
243 gnttab_set_unmap_op(&map->unmap_ops[i], addr, 248 gnttab_set_unmap_op(&map->unmap_ops[i], addr,
244 map->flags, -1 /* handle */); 249 map->flags, -1 /* handle */);
245 } 250 }
251 } else {
252 /*
253 * Setup the map_ops corresponding to the pte entries pointing
254 * to the kernel linear addresses of the struct pages.
255 * These ptes are completely different from the user ptes dealt
256 * with find_grant_ptes.
257 */
258 for (i = 0; i < map->count; i++) {
259 unsigned level;
260 unsigned long address = (unsigned long)
261 pfn_to_kaddr(page_to_pfn(map->pages[i]));
262 pte_t *ptep;
263 u64 pte_maddr = 0;
264 BUG_ON(PageHighMem(map->pages[i]));
265
266 ptep = lookup_address(address, &level);
267 pte_maddr = arbitrary_virt_to_machine(ptep).maddr;
268 gnttab_set_map_op(&map->kmap_ops[i], pte_maddr,
269 map->flags |
270 GNTMAP_host_map |
271 GNTMAP_contains_pte,
272 map->grants[i].ref,
273 map->grants[i].domid);
274 }
246 } 275 }
247 276
248 pr_debug("map %d+%d\n", map->index, map->count); 277 pr_debug("map %d+%d\n", map->index, map->count);
249 err = gnttab_map_refs(map->map_ops, map->pages, map->count); 278 err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL,
279 map->pages, map->count);
250 if (err) 280 if (err)
251 return err; 281 return err;
252 282