Commit 9e2369c0 authored by Roger Pau Monne's avatar Roger Pau Monne Committed by Juergen Gross
Browse files

xen: add helpers to allocate unpopulated memory



To be used in order to create foreign mappings. This is based on the
ZONE_DEVICE facility which is used by persistent memory devices in
order to create struct pages and kernel virtual mappings for the IOMEM
areas of such devices. Note that on kernels without support for
ZONE_DEVICE Xen will fallback to use ballooned pages in order to
create foreign mappings.

The newly added helpers use the same parameters as the existing
{alloc/free}_xenballooned_pages functions, which allows for in-place
replacement of the callers. Once a memory region has been added to be
used as scratch mapping space it will no longer be released, and pages
returned are kept in a linked list. This allows to have a buffer of
pages and prevents resorting to frequent additions and removals of
regions.

If enabled (because ZONE_DEVICE is supported) the usage of the new
functionality untangles Xen balloon and RAM hotplug from the usage of
unpopulated physical memory ranges to map foreign pages, which is the
correct thing to do in order to avoid mappings of foreign pages depend
on memory hotplug.

Note the driver is currently not enabled on Arm platforms because it
would interfere with the identity mapping required on some platforms.

Signed-off-by: default avatarRoger Pau Monné <roger.pau@citrix.com>
Reviewed-by: default avatarJuergen Gross <jgross@suse.com>
Link: https://lore.kernel.org/r/20200901083326.21264-4-roger.pau@citrix.com


Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
parent 4533d3ae
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <drm/drm_probe_helper.h>

#include <xen/balloon.h>
#include <xen/xen.h>

#include "xen_drm_front.h"
#include "xen_drm_front_gem.h"
@@ -99,7 +100,7 @@ static struct xen_gem_object *gem_create(struct drm_device *dev, size_t size)
		 * allocate ballooned pages which will be used to map
		 * grant references provided by the backend
		 */
		ret = alloc_xenballooned_pages(xen_obj->num_pages,
		ret = xen_alloc_unpopulated_pages(xen_obj->num_pages,
					          xen_obj->pages);
		if (ret < 0) {
			DRM_ERROR("Cannot allocate %zu ballooned pages: %d\n",
@@ -152,7 +153,7 @@ void xen_drm_front_gem_free_object_unlocked(struct drm_gem_object *gem_obj)
	} else {
		if (xen_obj->pages) {
			if (xen_obj->be_alloc) {
				free_xenballooned_pages(xen_obj->num_pages,
				xen_free_unpopulated_pages(xen_obj->num_pages,
							   xen_obj->pages);
				gem_free_pages_array(xen_obj);
			} else {
+10 −0
Original line number Diff line number Diff line
@@ -324,4 +324,14 @@ config XEN_HAVE_VPMU
config XEN_FRONT_PGDIR_SHBUF
	tristate

config XEN_UNPOPULATED_ALLOC
	bool "Use unpopulated memory ranges for guest mappings"
	depends on X86 && ZONE_DEVICE
	default XEN_BACKEND || XEN_GNTDEV || XEN_DOM0
	help
	  Use unpopulated memory ranges in order to create mappings for guest
	  memory regions, including grant maps and foreign pages. This avoids
	  having to balloon out RAM regions in order to obtain physical memory
	  space to create such mappings.

endmenu
+1 −0
Original line number Diff line number Diff line
@@ -42,3 +42,4 @@ xen-gntdev-$(CONFIG_XEN_GNTDEV_DMABUF) += gntdev-dmabuf.o
xen-gntalloc-y				:= gntalloc.o
xen-privcmd-y				:= privcmd.o privcmd-buf.o
obj-$(CONFIG_XEN_FRONT_PGDIR_SHBUF)	+= xen-front-pgdir-shbuf.o
obj-$(CONFIG_XEN_UNPOPULATED_ALLOC)	+= unpopulated-alloc.o
+2 −2
Original line number Diff line number Diff line
@@ -654,7 +654,7 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)
}
EXPORT_SYMBOL(free_xenballooned_pages);

#ifdef CONFIG_XEN_PV
#if defined(CONFIG_XEN_PV) && !defined(CONFIG_XEN_UNPOPULATED_ALLOC)
static void __init balloon_add_region(unsigned long start_pfn,
				      unsigned long pages)
{
@@ -708,7 +708,7 @@ static int __init balloon_init(void)
	register_sysctl_table(xen_root);
#endif

#ifdef CONFIG_XEN_PV
#if defined(CONFIG_XEN_PV) && !defined(CONFIG_XEN_UNPOPULATED_ALLOC)
	{
		int i;

+2 −2
Original line number Diff line number Diff line
@@ -801,7 +801,7 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)
{
	int ret;

	ret = alloc_xenballooned_pages(nr_pages, pages);
	ret = xen_alloc_unpopulated_pages(nr_pages, pages);
	if (ret < 0)
		return ret;

@@ -836,7 +836,7 @@ EXPORT_SYMBOL_GPL(gnttab_pages_clear_private);
void gnttab_free_pages(int nr_pages, struct page **pages)
{
	gnttab_pages_clear_private(nr_pages, pages);
	free_xenballooned_pages(nr_pages, pages);
	xen_free_unpopulated_pages(nr_pages, pages);
}
EXPORT_SYMBOL_GPL(gnttab_free_pages);

Loading