aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2011-09-29 06:57:56 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-09-29 10:32:58 -0400
commit0930bba674e248b921ea659b036ff02564e5a5f4 (patch)
tree52df16f477e1e63b034ee2e28f2d5c916bb53097 /drivers/xen
parent693394b8c3dcee1a3baa52e30fdc3323d88cd579 (diff)
xen: modify kernel mappings corresponding to granted pages
If we want to use granted pages for AIO, changing the mappings of a user vma and the corresponding p2m is not enough, we also need to update the kernel mappings accordingly. Currently this is only needed for pages that are created for user usages through /dev/xen/gntdev. As in, pages that have been in use by the kernel and use the P2M will not need this special mapping. However there are no guarantees that in the future the kernel won't start accessing pages through the 1:1 even for internal usage. In order to avoid the complexity of dealing with highmem, we allocated the pages lowmem. We issue a HYPERVISOR_grant_table_op right away in m2p_add_override and we remove the mappings using another HYPERVISOR_grant_table_op in m2p_remove_override. Considering that m2p_add_override and m2p_remove_override are called once per page we use multicalls and hypercall batching. Use the kmap_op pointer directly as argument to do the mapping as it is guaranteed to be present up until the unmapping is done. Before issuing any unmapping multicalls, we need to make sure that the mapping has already being done, because we need the kmap->handle to be set correctly. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> [v1: Removed GRANT_FRAME_BIT usage] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/gntdev.c32
-rw-r--r--drivers/xen/grant-table.c6
2 files changed, 34 insertions, 4 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 7b9b1d1b75a5..3e3603f35242 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
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 4f44b347b24a..8c71ab801756 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -448,7 +448,8 @@ unsigned int gnttab_max_grant_frames(void)
448EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); 448EXPORT_SYMBOL_GPL(gnttab_max_grant_frames);
449 449
450int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, 450int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
451 struct page **pages, unsigned int count) 451 struct gnttab_map_grant_ref *kmap_ops,
452 struct page **pages, unsigned int count)
452{ 453{
453 int i, ret; 454 int i, ret;
454 pte_t *pte; 455 pte_t *pte;
@@ -488,8 +489,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
488 */ 489 */
489 return -EOPNOTSUPP; 490 return -EOPNOTSUPP;
490 } 491 }
491 ret = m2p_add_override(mfn, pages[i], 492 ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]);
492 map_ops[i].flags & GNTMAP_contains_pte);
493 if (ret) 493 if (ret)
494 return ret; 494 return ret;
495 } 495 }