qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Christian Pinto <c.pinto@virtualopensystems.com>
To: qemu-devel@nongnu.org
Cc: Baptiste Reynal <b.reynal@virtualopensystems.com>,
	Jani.Kokkonen@huawei.com, tech@virtualopensystems.com,
	Claudio.Fontana@huawei.com,
	Christian Pinto <c.pinto@virtualopensystems.com>
Subject: [Qemu-devel] [RFC PATCH 2/8] backend: shared memory backend
Date: Tue, 29 Sep 2015 15:57:33 +0200	[thread overview]
Message-ID: <1443535059-26010-3-git-send-email-c.pinto@virtualopensystems.com> (raw)
In-Reply-To: <1443535059-26010-1-git-send-email-c.pinto@virtualopensystems.com>

From: Baptiste Reynal <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       | 194 ++++++++++++++++++++++++++++++++++++++++
 include/sysemu/hostmem-shared.h |  61 +++++++++++++
 3 files changed, 256 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..a96ccdf
--- /dev/null
+++ b/backends/hostmem-shared.c
@@ -0,0 +1,194 @@
+/*
+ * 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 shared_backend_init_shm(HostMemoryBackendShared *shm, int shmd,
+        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, shmd, offset);
+    close(shmd);
+
+    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);
+}
+
+/* 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);
+    uint32_t *infos = (uint32_t *) message;
+
+    int fd = 0;
+    multi_socket_get_fds_from(c, &fd);
+
+    if (fd <= 0) {
+        printf("Error receiving fd: %d", fd);
+        exit(-1);
+    }
+
+    shared_backend_init_shm(shm, fd, infos[0], infos[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;
+    }
+
+    shm->ms = (MSBackend *) object_resolve_path_type(shm->chardev,
+            TYPE_MULTI_SOCKET_BACKEND, NULL);
+    if (shm->ms == NULL) {
+        printf("Error: Cannot find socket %s\n", shm->chardev);
+        exit(-1);
+    }
+
+    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);
+        } 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;
+    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;
+    }
+    if (shm->mem_path) {
+        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 char *get_chardev(Object *o, Error **errp)
+{
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(o);
+
+    return g_strdup(shm->chardev);
+}
+
+static void set_chardev(Object *o, const char *str, Error **errp)
+{
+    HostMemoryBackendShared *shm = MEMORY_BACKEND_SHARED(o);
+
+    if (shm->chardev) {
+        g_free(shm->chardev);
+    }
+    shm->chardev = g_strdup(str);
+}
+
+static void shared_backend_instance_init(Object *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_str(o, "chardev", get_chardev,
+                            set_chardev, NULL);
+}
+
+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..f3f8e4e
--- /dev/null
+++ b/include/sysemu/hostmem-shared.h
@@ -0,0 +1,61 @@
+/*
+ * 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 {
+    HostMemoryBackend parent_obj;
+
+    bool master;
+
+    char *mem_path;
+    char *chardev;
+
+    int event;
+    EventNotifier *levent;
+
+    MSBackend *ms;
+    MemoryRegion shared_region;
+} HostMemoryBackendShared;
+
+typedef struct HostMemoryBackendSharedClass {
+    HostMemoryBackendClass parent_class;
+
+    void (*parent_complete)(UserCreatable *uc, Error **errp);
+} HostMemoryBackendSharedClass;
+
+#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
-- 
1.9.1

  parent reply	other threads:[~2015-09-29 14:00 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-29 13:57 [Qemu-devel] [RFC PATCH 0/8] Towards an Heterogeneous QEMU Christian Pinto
2015-09-29 13:57 ` [Qemu-devel] [RFC PATCH 1/8] backend: multi-socket Christian Pinto
2015-09-29 13:57 ` Christian Pinto [this message]
2015-09-29 13:57 ` [Qemu-devel] [RFC PATCH 3/8] migration: add shared migration type Christian Pinto
2015-09-29 13:57 ` [Qemu-devel] [RFC PATCH 4/8] hw/misc: IDM Device Christian Pinto
2015-09-29 13:57 ` [Qemu-devel] [RFC PATCH 5/8] hw/arm: sysbus-fdt Christian Pinto
2015-09-29 13:57 ` [Qemu-devel] [RFC PATCH 6/8] qemu: slave machine flag Christian Pinto
2015-09-29 13:57 ` [Qemu-devel] [RFC PATCH 7/8] hw/arm: boot Christian Pinto
2015-09-29 13:57 ` [Qemu-devel] [RFC PATCH 8/8] qemu: numa Christian Pinto
2015-10-01 16:26 ` [Qemu-devel] [RFC PATCH 0/8] Towards an Heterogeneous QEMU Peter Crosthwaite
2015-10-05 15:50   ` Christian Pinto
2015-10-07 15:48     ` Peter Crosthwaite
2015-10-22  9:21       ` Christian Pinto
2015-10-25 21:38         ` Peter Crosthwaite
2015-10-26 17:12           ` mar.krzeminski
2015-10-26 17:42             ` Peter Crosthwaite
2015-10-27 10:30           ` Christian Pinto
2015-11-13  7:02             ` Peter Crosthwaite
2015-12-12 10:19               ` Christian Pinto

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=1443535059-26010-3-git-send-email-c.pinto@virtualopensystems.com \
    --to=c.pinto@virtualopensystems.com \
    --cc=Claudio.Fontana@huawei.com \
    --cc=Jani.Kokkonen@huawei.com \
    --cc=b.reynal@virtualopensystems.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).