Message ID | 1460462129-17363-9-git-send-email-marcandre.lureau@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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
----- 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 --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