diff options
Diffstat (limited to 'drivers/xen/gntdev.c')
-rw-r--r-- | drivers/xen/gntdev.c | 32 |
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 | ||