All of lore.kernel.org
 help / color / mirror / Atom feed
From: Baptiste Reynal <b.reynal@virtualopensystems.com>
To: qemu-devel@nongnu.org
Cc: b.reynal@virtualopensystems.com, Jani.Kokkonen@huawei.com,
	tech@virtualopensystems.com, Claudio.Fontana@huawei.com
Subject: [Qemu-devel] [RFC v2 1/6] backend: shared memory backend
Date: Fri, 18 Mar 2016 10:13:53 +0100	[thread overview]
Message-ID: <1458292438-13909-2-git-send-email-b.reynal@virtualopensystems.com> (raw)
In-Reply-To: <1458292438-13909-1-git-send-email-b.reynal@virtualopensystems.com>

This patch introduces a shared memory backend, allowing to share memory
between a master and many slaves.

The memory is implemented using hugetlbfs, and relies on the
multi-socket backend to share informations (size and offset for the
slaves).

Instantiation on the master:
-object memory-backend-shared,id=<id>,size=<memory_sizeK,M,G>,
	chardev=<multi-socket_id>,master=on

Instantiation on the slave:
-object memory-backend-shared,id=<id>,size=<slave_memory_sizeK,M,G>,
	chardev=<multi-socket_id>,master=off

Memory size on the slave can be smaller than on master. The master will
send to the slave the size and the offset of the memory segment it can
allocate in the total shared memory.

Signed-off-by: Baptiste Reynal <b.reynal@virtualopensystems.com>
---
 backends/Makefile.objs          |   2 +-
 backends/hostmem-shared.c       | 192 ++++++++++++++++++++++++++++++++++++++++
 include/sysemu/hostmem-shared.h |  66 ++++++++++++++
 3 files changed, 259 insertions(+), 1 deletion(-)
 create mode 100644 backends/hostmem-shared.c
 create mode 100644 include/sysemu/hostmem-shared.h

diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 689eac3..de76906 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -8,6 +8,6 @@ baum.o-cflags := $(SDL_CFLAGS)
 common-obj-$(CONFIG_TPM) += tpm.o
 
 common-obj-y += hostmem.o hostmem-ram.o
-common-obj-$(CONFIG_LINUX) += hostmem-file.o
+common-obj-$(CONFIG_LINUX) += hostmem-file.o hostmem-shared.o
 
 common-obj-y += multi-socket.o
diff --git a/backends/hostmem-shared.c b/backends/hostmem-shared.c
new file mode 100644
index 0000000..b45a87b
--- /dev/null
+++ b/backends/hostmem-shared.c
@@ -0,0 +1,192 @@
+/*
+ * QEMU Host Memory Backend for hugetlbfs
+ *
+ * Copyright (C) 2015 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "sysemu/hostmem-shared.h"
+
+static void shm_map(HostMemoryBackendShared *shm, size_t size, off_t offset)
+{
+    void *shared_ram;
+    HostMemoryBackend *backend = MEMORY_BACKEND(shm);
+
+    shared_ram = mmap(0, size, PROT_READ | PROT_WRITE,
+            MAP_SHARED, shm->fd, offset);
+    close(shm->fd);
+
+    if (shared_ram == MAP_FAILED) {
+        perror("Map failed");
+    }
+
+    memory_region_init_ram_ptr(&shm->shared_region, OBJECT(backend),
+            "shared_mem", size, shared_ram);
+
+    memory_region_add_subregion(&backend->mr,
+            0, &shm->shared_region);
+
+    vmstate_register_ram_global(&shm->shared_region);
+
+    event_notifier_set(shm->levent);
+}
+
+/* Callback function if a fd is received over the socket */
+static void set_shared_memory(MSClient *c, const char *message, void *opaque)
+{
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(opaque);
+
+    int fd = 0;
+    multi_socket_get_fds_from(c, &fd);
+
+    if (fd <= 0) {
+        printf("Error receiving fd: %d", fd);
+        exit(-1);
+    }
+
+    shm->fd = fd;
+}
+
+static void shm_send_fd(MSClient *client, void *opaque)
+{
+    int fd;
+    const char *message = "send_fd";
+    HostMemoryBackend *hm = MEMORY_BACKEND(opaque);
+
+    fd = memory_region_get_fd(&hm->mr);
+
+    multi_socket_send_fds_to(client, &fd, 1, message, strlen(message) + 1);
+}
+
+static void
+shared_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
+{
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(backend);
+
+    if (!backend->size) {
+        error_setg(errp, "can't create backend with size 0");
+        return;
+    }
+
+    if (!memory_region_size(&backend->mr)) {
+        if (shm->master) {
+            backend->force_prealloc = mem_prealloc;
+            memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
+                    object_get_canonical_path(OBJECT(backend)),
+                    backend->size, true,
+                    shm->mem_path, errp);
+            multi_socket_add_reg_handler(shm->ms, shm_send_fd, shm);
+        } else {
+            backend->force_prealloc = mem_prealloc;
+
+            /*
+             * Initialize only the main fields
+             * the rest is initialized when the fd is received
+            */
+            memory_region_init(&backend->mr, OBJECT(backend),
+                    object_get_canonical_path(OBJECT(backend)),
+                    backend->size);
+
+            multi_socket_add_handler(shm->ms, "send_fd",
+                    set_shared_memory, shm);
+        }
+    }
+}
+
+static void
+shared_memory_backend_complete(UserCreatable *uc, Error **errp)
+{
+    HostMemoryBackend *hm = MEMORY_BACKEND(uc);
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(uc);
+    HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(uc);
+    HostMemoryBackendSharedClass *bsc = MEMORY_BACKEND_SHARED_GET_CLASS(uc);
+
+    if (shm->master) {
+        bsc->parent_complete(uc, errp);
+    } else {
+        bc->alloc(hm, errp);
+    }
+}
+
+static void shared_backend_class_init(ObjectClass *oc, void *data)
+{
+    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+    HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
+    HostMemoryBackendSharedClass *bsc = MEMORY_BACKEND_SHARED_CLASS(oc);
+
+    bc->alloc = shared_backend_memory_alloc;
+    bsc->parent_complete = ucc->complete;
+    bsc->map = shm_map;
+    ucc->complete = shared_memory_backend_complete;
+}
+
+static char *get_mem_path(Object *o, Error **errp)
+{
+    HostMemoryBackendShared *backend = MEMORY_BACKEND_SHARED(o);
+
+    return g_strdup(backend->mem_path);
+}
+
+static void set_mem_path(Object *o, const char *str, Error **errp)
+{
+    HostMemoryBackend *backend = MEMORY_BACKEND(o);
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(o);
+
+    if (memory_region_size(&backend->mr)) {
+        error_setg(errp, "cannot change property value");
+        return;
+    }
+    g_free(shm->mem_path);
+
+    shm->mem_path = g_strdup(str);
+}
+
+static bool get_master(Object *o, Error **errp)
+{
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(o);
+
+    return shm->master;
+}
+
+static void set_master(Object *o, bool value, Error **errp)
+{
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(o);
+
+    shm->master = value;
+}
+
+static void shared_backend_instance_init(Object *o)
+{
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(o);
+
+    object_property_add_bool(o, "master", get_master,
+                        set_master, NULL);
+    object_property_add_str(o, "mem-path", get_mem_path,
+                            set_mem_path, NULL);
+    object_property_add_link(o, "socket", TYPE_MULTI_SOCKET_BACKEND,
+            (Object **)&shm->ms,
+            object_property_allow_set_link,
+            OBJ_PROP_LINK_UNREF_ON_RELEASE,
+            &error_abort);
+}
+
+static const TypeInfo shared_backend_info = {
+    .name = TYPE_MEMORY_BACKEND_SHARED,
+    .parent = TYPE_MEMORY_BACKEND,
+    .class_init = shared_backend_class_init,
+    .class_size = sizeof(HostMemoryBackendSharedClass),
+    .instance_init = shared_backend_instance_init,
+    .instance_size = sizeof(HostMemoryBackendShared),
+};
+
+static void register_types(void)
+{
+    type_register_static(&shared_backend_info);
+}
+
+type_init(register_types);
diff --git a/include/sysemu/hostmem-shared.h b/include/sysemu/hostmem-shared.h
new file mode 100644
index 0000000..7db3b37
--- /dev/null
+++ b/include/sysemu/hostmem-shared.h
@@ -0,0 +1,66 @@
+/*
+ * QEMU Host Memory Backend for hugetlbfs
+ *
+ * Copyright (C) 2015 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal <b.reynal@virtualopensystems.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_HM_H
+#define QEMU_HM_H
+
+#include "qemu-common.h"
+#include "sysemu/hostmem.h"
+#include "sysemu/sysemu.h"
+#include "qemu/multi-socket.h"
+#include "qom/object_interfaces.h"
+#include "qapi-visit.h"
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <fcntl.h>
+
+typedef struct HostMemoryBackendShared HostMemoryBackendShared;
+typedef struct HostMemoryBackendSharedClass HostMemoryBackendSharedClass;
+
+struct HostMemoryBackendShared {
+    HostMemoryBackend parent_obj;
+
+    bool master;
+
+    char *mem_path;
+
+    int event;
+    int fd;
+
+    EventNotifier *levent;
+
+    MSBackend *ms;
+    MemoryRegion shared_region;
+};
+
+struct HostMemoryBackendSharedClass {
+    HostMemoryBackendClass parent_class;
+
+    void (*parent_complete)(UserCreatable *uc, Error **errp);
+    void (*map)(HostMemoryBackendShared *shm, size_t size, off_t offset);
+};
+
+#define TYPE_MEMORY_BACKEND_SHARED "memory-backend-shared"
+
+#define MEMORY_BACKEND_SHARED(obj) \
+    OBJECT_CHECK(HostMemoryBackendShared, (obj), TYPE_MEMORY_BACKEND_SHARED)
+#define MEMORY_BACKEND_SHARED_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(HostMemoryBackendSharedClass, (obj), \
+            TYPE_MEMORY_BACKEND_SHARED)
+#define MEMORY_BACKEND_SHARED_CLASS(klass) \
+    OBJECT_CLASS_CHECK(HostMemoryBackendSharedClass, (klass), \
+            TYPE_MEMORY_BACKEND_SHARED)
+#define IS_MEMORY_BACKEND_SHARED(obj) \
+    object_dynamic_cast(OBJECT(obj), TYPE_MEMORY_BACKEND_SHARED)
+
+#endif
-- 
2.7.3

  reply	other threads:[~2016-03-18  9:14 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-18  9:13 [Qemu-devel] [RFC v2 0/6] QEMU shared-memory backend Baptiste Reynal
2016-03-18  9:13 ` Baptiste Reynal [this message]
2016-03-18  9:13 ` [Qemu-devel] [RFC v2 2/6] migration: add shared migration type Baptiste Reynal
2016-03-18  9:13 ` [Qemu-devel] [RFC v2 3/6] hw/misc: sdm signal shboot Baptiste Reynal
2016-03-18  9:13 ` [Qemu-devel] [RFC v2 4/6] qemu: slave machine flag Baptiste Reynal
2016-03-18  9:13 ` [Qemu-devel] [RFC v2 5/6] hw/arm: boot Baptiste Reynal
2016-03-18  9:13 ` [Qemu-devel] [RFC v2 6/6] qemu: numa Baptiste Reynal
2016-03-22 14:14 ` [Qemu-devel] [RFC v2 0/6] QEMU shared-memory backend Markus Armbruster
2016-03-22 14:54   ` Baptiste Reynal
2016-04-07 16:27     ` Markus Armbruster
2016-04-08 12:52       ` Baptiste Reynal
2016-04-08 13:59         ` Markus Armbruster
2016-03-31  9:14 ` Stefan Hajnoczi
2016-04-05 12:00   ` Baptiste Reynal
2016-04-06  8:57     ` Stefan Hajnoczi
2016-04-06 13:47       ` Igor Mammedov
2016-04-08 12:46         ` Baptiste Reynal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1458292438-13909-2-git-send-email-b.reynal@virtualopensystems.com \
    --to=b.reynal@virtualopensystems.com \
    --cc=Claudio.Fontana@huawei.com \
    --cc=Jani.Kokkonen@huawei.com \
    --cc=qemu-devel@nongnu.org \
    --cc=tech@virtualopensystems.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.