diff mbox

[8/9] Add memfd based hostmem

Message ID 1460462129-17363-9-git-send-email-marcandre.lureau@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Marc-André Lureau April 12, 2016, 11:55 a.m. UTC
From: Marc-André Lureau <marcandre.lureau@redhat.com>

Add a new memory backend, similar to hostmem-file, except that it
doesn't need a file path, or hugepages directory permissions. It also
try to enforce memory sealing if available.

This backend is mainly useful for easily sharing the memory with other
processes, for example with vhost-user backend, when hugepages aren't
available (for security reasons and other limitations).

Usage:
-object memory-backend-memfd,id=mem1,size=1G

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 backends/Makefile.objs   |  1 +
 backends/hostmem-memfd.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-options.hx          | 12 +++++++
 3 files changed, 98 insertions(+)
 create mode 100644 backends/hostmem-memfd.c

Comments

Igor Mammedov April 12, 2016, 1:07 p.m. UTC | #1
On Tue, 12 Apr 2016 13:55:28 +0200
marcandre.lureau@redhat.com wrote:

> From: Marc-André Lureau <marcandre.lureau@redhat.com>
> 
> Add a new memory backend, similar to hostmem-file, except that it
> doesn't need a file path, or hugepages directory permissions. It also
> try to enforce memory sealing if available.
> 
> This backend is mainly useful for easily sharing the memory with other
> processes, for example with vhost-user backend, when hugepages aren't
> available (for security reasons and other limitations).
> 
> Usage:
> -object memory-backend-memfd,id=mem1,size=1G
Does it make sense if it's possible to reuse/extend memory-backend-file,
i.e. make 'mem-path' optional and behave like this patch
and also add 'memfd' property so that parent process could
pass its handle to QEMU as well?

> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
>  backends/Makefile.objs   |  1 +
>  backends/hostmem-memfd.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++
>  qemu-options.hx          | 12 +++++++
>  3 files changed, 98 insertions(+)
>  create mode 100644 backends/hostmem-memfd.c
> 
> diff --git a/backends/Makefile.objs b/backends/Makefile.objs
> index 31a3a89..32cfcdb 100644
> --- a/backends/Makefile.objs
> +++ b/backends/Makefile.objs
> @@ -9,3 +9,4 @@ common-obj-$(CONFIG_TPM) += tpm.o
>  
>  common-obj-y += hostmem.o hostmem-ram.o
>  common-obj-$(CONFIG_LINUX) += hostmem-file.o
> +common-obj-$(CONFIG_POSIX) += hostmem-memfd.o
> diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
> new file mode 100644
> index 0000000..e0e18d7
> --- /dev/null
> +++ b/backends/hostmem-memfd.c
> @@ -0,0 +1,85 @@
> +/*
> + * QEMU host memfd memory backend
> + *
> + * Copyright (C) 2016 Red Hat Inc
> + *
> + * Authors:
> + *   Marc-André Lureau <marcandre.lureau@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "sysemu/hostmem.h"
> +#include "sysemu/sysemu.h"
> +#include "qom/object_interfaces.h"
> +#include "qemu/memfd.h"
> +#include "qapi/error.h"
> +
> +/**
> + * @TYPE_MEMORY_BACKEND_MEMFD:
> + * name of the memory backend that uses memfd mmap
> + */
> +#define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
> +
> +#define MEMORY_BACKEND_MEMFD(obj) \
> +    OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD)
> +
> +typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd;
> +
> +struct HostMemoryBackendMemfd {
> +    HostMemoryBackend parent_obj;
> +
> +    int fd;
> +};
> +
> +static void
> +memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
> +{
> +    int fd;
> +
> +    if (!backend->size) {
> +        error_setg(errp, "can't create backend with size 0");
> +        return;
> +    }
> +#ifndef CONFIG_LINUX
> +    error_setg(errp, "memfd not supported on this host");
> +#else
> +    if (!memory_region_size(&backend->mr)) {
> +        backend->force_prealloc = mem_prealloc;
> +        fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD,
> +                               backend->size,
> +                               F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL);
> +        if (fd == -1) {
> +            error_setg(errp, "can't allocate memfd backend");
> +            return;
> +        }
> +        memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
> +            object_get_canonical_path(OBJECT(backend)),
> +            backend->size, true, fd, errp);
> +    }
> +#endif
> +}
> +
> +static void
> +memfd_backend_class_init(ObjectClass *oc, void *data)
> +{
> +    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
> +
> +    bc->alloc = memfd_backend_memory_alloc;
> +}
> +
> +static const TypeInfo memfd_backend_info = {
> +    .name = TYPE_MEMORY_BACKEND_MEMFD,
> +    .parent = TYPE_MEMORY_BACKEND,
> +    .class_init = memfd_backend_class_init,
> +    .instance_size = sizeof(HostMemoryBackendMemfd),
> +};
> +
> +static void register_types(void)
> +{
> +    type_register_static(&memfd_backend_info);
> +}
> +
> +type_init(register_types);
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 587de8f..a54af0f 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3756,6 +3756,18 @@ The @option{share} boolean option determines whether the memory
>  region is marked as private to QEMU, or shared. The latter allows
>  a co-operating external process to access the QEMU memory region.
>  
> +@item -object memory-backend-memfd,id=@var{id},size=@var{size}
> +
> +Creates an anonymous memory file backend object, which can be used to
> +share the memory with a co-operating external process. The memory is
> +created with memfd and sealing if possible, but has fallback mechanism
> +for systems that lack it.
> +
> +The @option{id} parameter is a unique ID that will be used to
> +reference this memory region when configuring the @option{-numa}
> +argument. The @option{size} option provides the size of the memory
> +region, and accepts common suffixes, eg @option{500M}.
> +
>  @item -object rng-random,id=@var{id},filename=@var{/dev/random}
>  
>  Creates a random number generator backend which obtains entropy from
Marc-André Lureau April 12, 2016, 1:32 p.m. UTC | #2
----- Original Message -----
> On Tue, 12 Apr 2016 13:55:28 +0200
> marcandre.lureau@redhat.com wrote:
> 
> > From: Marc-André Lureau <marcandre.lureau@redhat.com>
> > 
> > Add a new memory backend, similar to hostmem-file, except that it
> > doesn't need a file path, or hugepages directory permissions. It also
> > try to enforce memory sealing if available.
> > 
> > This backend is mainly useful for easily sharing the memory with other
> > processes, for example with vhost-user backend, when hugepages aren't
> > available (for security reasons and other limitations).
> > 
> > Usage:
> > -object memory-backend-memfd,id=mem1,size=1G
> Does it make sense if it's possible to reuse/extend memory-backend-file,
> i.e. make 'mem-path' optional and behave like this patch
> and also add 'memfd' property so that parent process could
> pass its handle to QEMU as well?

I don't mind, I would be a bit worried by the combination of options and the expected result though.

> > 
> > Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> > ---
> >  backends/Makefile.objs   |  1 +
> >  backends/hostmem-memfd.c | 85
> >  ++++++++++++++++++++++++++++++++++++++++++++++++
> >  qemu-options.hx          | 12 +++++++
> >  3 files changed, 98 insertions(+)
> >  create mode 100644 backends/hostmem-memfd.c
> > 
> > diff --git a/backends/Makefile.objs b/backends/Makefile.objs
> > index 31a3a89..32cfcdb 100644
> > --- a/backends/Makefile.objs
> > +++ b/backends/Makefile.objs
> > @@ -9,3 +9,4 @@ common-obj-$(CONFIG_TPM) += tpm.o
> >  
> >  common-obj-y += hostmem.o hostmem-ram.o
> >  common-obj-$(CONFIG_LINUX) += hostmem-file.o
> > +common-obj-$(CONFIG_POSIX) += hostmem-memfd.o
> > diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
> > new file mode 100644
> > index 0000000..e0e18d7
> > --- /dev/null
> > +++ b/backends/hostmem-memfd.c
> > @@ -0,0 +1,85 @@
> > +/*
> > + * QEMU host memfd memory backend
> > + *
> > + * Copyright (C) 2016 Red Hat Inc
> > + *
> > + * Authors:
> > + *   Marc-André Lureau <marcandre.lureau@redhat.com>
> > + *
> > + * This work is licensed under the terms of the GNU GPL, version 2 or
> > later.
> > + * See the COPYING file in the top-level directory.
> > + */
> > +#include "qemu/osdep.h"
> > +#include "qemu-common.h"
> > +#include "sysemu/hostmem.h"
> > +#include "sysemu/sysemu.h"
> > +#include "qom/object_interfaces.h"
> > +#include "qemu/memfd.h"
> > +#include "qapi/error.h"
> > +
> > +/**
> > + * @TYPE_MEMORY_BACKEND_MEMFD:
> > + * name of the memory backend that uses memfd mmap
> > + */
> > +#define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
> > +
> > +#define MEMORY_BACKEND_MEMFD(obj) \
> > +    OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD)
> > +
> > +typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd;
> > +
> > +struct HostMemoryBackendMemfd {
> > +    HostMemoryBackend parent_obj;
> > +
> > +    int fd;
> > +};
> > +
> > +static void
> > +memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
> > +{
> > +    int fd;
> > +
> > +    if (!backend->size) {
> > +        error_setg(errp, "can't create backend with size 0");
> > +        return;
> > +    }
> > +#ifndef CONFIG_LINUX
> > +    error_setg(errp, "memfd not supported on this host");
> > +#else
> > +    if (!memory_region_size(&backend->mr)) {
> > +        backend->force_prealloc = mem_prealloc;
> > +        fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD,
> > +                               backend->size,
> > +                               F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL);
> > +        if (fd == -1) {
> > +            error_setg(errp, "can't allocate memfd backend");
> > +            return;
> > +        }
> > +        memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
> > +            object_get_canonical_path(OBJECT(backend)),
> > +            backend->size, true, fd, errp);
> > +    }
> > +#endif
> > +}
> > +
> > +static void
> > +memfd_backend_class_init(ObjectClass *oc, void *data)
> > +{
> > +    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
> > +
> > +    bc->alloc = memfd_backend_memory_alloc;
> > +}
> > +
> > +static const TypeInfo memfd_backend_info = {
> > +    .name = TYPE_MEMORY_BACKEND_MEMFD,
> > +    .parent = TYPE_MEMORY_BACKEND,
> > +    .class_init = memfd_backend_class_init,
> > +    .instance_size = sizeof(HostMemoryBackendMemfd),
> > +};
> > +
> > +static void register_types(void)
> > +{
> > +    type_register_static(&memfd_backend_info);
> > +}
> > +
> > +type_init(register_types);
> > diff --git a/qemu-options.hx b/qemu-options.hx
> > index 587de8f..a54af0f 100644
> > --- a/qemu-options.hx
> > +++ b/qemu-options.hx
> > @@ -3756,6 +3756,18 @@ The @option{share} boolean option determines whether
> > the memory
> >  region is marked as private to QEMU, or shared. The latter allows
> >  a co-operating external process to access the QEMU memory region.
> >  
> > +@item -object memory-backend-memfd,id=@var{id},size=@var{size}
> > +
> > +Creates an anonymous memory file backend object, which can be used to
> > +share the memory with a co-operating external process. The memory is
> > +created with memfd and sealing if possible, but has fallback mechanism
> > +for systems that lack it.
> > +
> > +The @option{id} parameter is a unique ID that will be used to
> > +reference this memory region when configuring the @option{-numa}
> > +argument. The @option{size} option provides the size of the memory
> > +region, and accepts common suffixes, eg @option{500M}.
> > +
> >  @item -object rng-random,id=@var{id},filename=@var{/dev/random}
> >  
> >  Creates a random number generator backend which obtains entropy from
> 
>
diff mbox

Patch

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 31a3a89..32cfcdb 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -9,3 +9,4 @@  common-obj-$(CONFIG_TPM) += tpm.o
 
 common-obj-y += hostmem.o hostmem-ram.o
 common-obj-$(CONFIG_LINUX) += hostmem-file.o
+common-obj-$(CONFIG_POSIX) += hostmem-memfd.o
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
new file mode 100644
index 0000000..e0e18d7
--- /dev/null
+++ b/backends/hostmem-memfd.c
@@ -0,0 +1,85 @@ 
+/*
+ * QEMU host memfd memory backend
+ *
+ * Copyright (C) 2016 Red Hat Inc
+ *
+ * Authors:
+ *   Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "sysemu/hostmem.h"
+#include "sysemu/sysemu.h"
+#include "qom/object_interfaces.h"
+#include "qemu/memfd.h"
+#include "qapi/error.h"
+
+/**
+ * @TYPE_MEMORY_BACKEND_MEMFD:
+ * name of the memory backend that uses memfd mmap
+ */
+#define TYPE_MEMORY_BACKEND_MEMFD "memory-backend-memfd"
+
+#define MEMORY_BACKEND_MEMFD(obj) \
+    OBJECT_CHECK(HostMemoryBackendMemfd, (obj), TYPE_MEMORY_BACKEND_MEMFD)
+
+typedef struct HostMemoryBackendMemfd HostMemoryBackendMemfd;
+
+struct HostMemoryBackendMemfd {
+    HostMemoryBackend parent_obj;
+
+    int fd;
+};
+
+static void
+memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
+{
+    int fd;
+
+    if (!backend->size) {
+        error_setg(errp, "can't create backend with size 0");
+        return;
+    }
+#ifndef CONFIG_LINUX
+    error_setg(errp, "memfd not supported on this host");
+#else
+    if (!memory_region_size(&backend->mr)) {
+        backend->force_prealloc = mem_prealloc;
+        fd = qemu_memfd_create(TYPE_MEMORY_BACKEND_MEMFD,
+                               backend->size,
+                               F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL);
+        if (fd == -1) {
+            error_setg(errp, "can't allocate memfd backend");
+            return;
+        }
+        memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
+            object_get_canonical_path(OBJECT(backend)),
+            backend->size, true, fd, errp);
+    }
+#endif
+}
+
+static void
+memfd_backend_class_init(ObjectClass *oc, void *data)
+{
+    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
+
+    bc->alloc = memfd_backend_memory_alloc;
+}
+
+static const TypeInfo memfd_backend_info = {
+    .name = TYPE_MEMORY_BACKEND_MEMFD,
+    .parent = TYPE_MEMORY_BACKEND,
+    .class_init = memfd_backend_class_init,
+    .instance_size = sizeof(HostMemoryBackendMemfd),
+};
+
+static void register_types(void)
+{
+    type_register_static(&memfd_backend_info);
+}
+
+type_init(register_types);
diff --git a/qemu-options.hx b/qemu-options.hx
index 587de8f..a54af0f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3756,6 +3756,18 @@  The @option{share} boolean option determines whether the memory
 region is marked as private to QEMU, or shared. The latter allows
 a co-operating external process to access the QEMU memory region.
 
+@item -object memory-backend-memfd,id=@var{id},size=@var{size}
+
+Creates an anonymous memory file backend object, which can be used to
+share the memory with a co-operating external process. The memory is
+created with memfd and sealing if possible, but has fallback mechanism
+for systems that lack it.
+
+The @option{id} parameter is a unique ID that will be used to
+reference this memory region when configuring the @option{-numa}
+argument. The @option{size} option provides the size of the memory
+region, and accepts common suffixes, eg @option{500M}.
+
 @item -object rng-random,id=@var{id},filename=@var{/dev/random}
 
 Creates a random number generator backend which obtains entropy from