@@ -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
new file mode 100644
@@ -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);
new file mode 100644
@@ -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