summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2021-02-15 08:51:07 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-02-23 13:59:17 +0100
commitc5b81504415eeee141036834eb4d756db4f8105a (patch)
tree9b7202114c9587154532403f644059fbd05e2228
parenta3c335bbc0ec0b56975a82d4c29c95279631e9bf (diff)
downloadlinux-stable-c5b81504415eeee141036834eb4d756db4f8105a.tar.gz
linux-stable-c5b81504415eeee141036834eb4d756db4f8105a.tar.bz2
linux-stable-c5b81504415eeee141036834eb4d756db4f8105a.zip
Xen/gntdev: correct dev_bus_addr handling in gntdev_map_grant_pages()
commit dbe5283605b3bc12ca45def09cc721a0a5c853a2 upstream. We may not skip setting the field in the unmap structure when GNTMAP_device_map is in use - such an unmap would fail to release the respective resources (a page ref in the hypervisor). Otoh the field doesn't need setting at all when GNTMAP_device_map is not in use. To record the value for unmapping, we also better don't use our local p2m: In particular after a subsequent change it may not have got updated for all the batch elements. Instead it can simply be taken from the respective map's results. We can additionally avoid playing this game altogether for the kernel part of the mappings in (x86) PV mode. This is part of XSA-361. Signed-off-by: Jan Beulich <jbeulich@suse.com> Cc: stable@vger.kernel.org Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> Signed-off-by: Juergen Gross <jgross@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/xen/gntdev.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 910b5d40c6e9..1244c839fd18 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -293,18 +293,25 @@ static int map_grant_pages(struct grant_map *map)
* to the kernel linear addresses of the struct pages.
* These ptes are completely different from the user ptes dealt
* with find_grant_ptes.
+ * Note that GNTMAP_device_map isn't needed here: The
+ * dev_bus_addr output field gets consumed only from ->map_ops,
+ * and by not requesting it when mapping we also avoid needing
+ * to mirror dev_bus_addr into ->unmap_ops (and holding an extra
+ * reference to the page in the hypervisor).
*/
+ unsigned int flags = (map->flags & ~GNTMAP_device_map) |
+ GNTMAP_host_map;
+
for (i = 0; i < map->count; i++) {
unsigned long address = (unsigned long)
pfn_to_kaddr(page_to_pfn(map->pages[i]));
BUG_ON(PageHighMem(map->pages[i]));
- gnttab_set_map_op(&map->kmap_ops[i], address,
- map->flags | GNTMAP_host_map,
+ gnttab_set_map_op(&map->kmap_ops[i], address, flags,
map->grants[i].ref,
map->grants[i].domid);
gnttab_set_unmap_op(&map->kunmap_ops[i], address,
- map->flags | GNTMAP_host_map, -1);
+ flags, -1);
}
}
@@ -320,6 +327,9 @@ static int map_grant_pages(struct grant_map *map)
continue;
}
+ if (map->flags & GNTMAP_device_map)
+ map->unmap_ops[i].dev_bus_addr = map->map_ops[i].dev_bus_addr;
+
map->unmap_ops[i].handle = map->map_ops[i].handle;
if (use_ptemod)
map->kunmap_ops[i].handle = map->kmap_ops[i].handle;