From patchwork Fri Mar 18 09:13:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Baptiste Reynal X-Patchwork-Id: 8617401 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id D9F36C0553 for ; Fri, 18 Mar 2016 09:16:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D085C2034B for ; Fri, 18 Mar 2016 09:16:14 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9E54620382 for ; Fri, 18 Mar 2016 09:16:13 +0000 (UTC) Received: from localhost ([::1]:42382 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agqVw-0006Qw-Ss for patchwork-qemu-devel@patchwork.kernel.org; Fri, 18 Mar 2016 05:16:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42346) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agqU0-0003fF-KK for qemu-devel@nongnu.org; Fri, 18 Mar 2016 05:14:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1agqTx-0003vL-32 for qemu-devel@nongnu.org; Fri, 18 Mar 2016 05:14:12 -0400 Received: from mail-wm0-x233.google.com ([2a00:1450:400c:c09::233]:38705) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1agqTw-0003vH-Of for qemu-devel@nongnu.org; Fri, 18 Mar 2016 05:14:09 -0400 Received: by mail-wm0-x233.google.com with SMTP id l68so27724665wml.1 for ; Fri, 18 Mar 2016 02:14:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=virtualopensystems-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=oPxe8EKNKLnI9bTQANl1loQUoA5hzHJvdH5SbAC/Svc=; b=anT3kYl4d+y3mvXMoYNdRHpU1kZRxf0v0AdnkGsqLHKT1MHvuB7iwJOhxa1Z/ZU5Nc KeGRkWPuMis5ncOpYaVBMKz8wJ5YU2Hm9dhTKbRlIvXQpxILxu0UnunlQJ+lFqshtHP0 84VTmp9wC2uQeM1HF/BQD/CiskIDGPvuNKOUA2xpCNR4nt75UkDoyoPMQEu3matPNM1S uBCWCkKEgnPQci8Kl1lyra5xLfLOF1RbBSoamwVmS6rmPlydaEQzAqy54VDIf0emBlsf jdv0tyUcO4oUSmZqmR5JGQ6c82eY8BeO4GpAP3ulwd0RNRSGIfQPZYkwZeFDCk5yeG+s chvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=oPxe8EKNKLnI9bTQANl1loQUoA5hzHJvdH5SbAC/Svc=; b=Ydsaje/ecK7C0aJvVLOhf6CHy2OlQzLtWZCjMi07T0NT0ks4AG19+nglRThAyqvbHA r9QaDMb4J22AfDKmgQJSYeyyf0at80UqQqrbW1tiIRyvZAQINtpoB5NkOOgUXQEfEp1l bLUrb1xnuOg9RMYBVEURlpqYAN3aHTZh3m23+BWubQUBVvsf1FF5/UQCgJ6TrH5R5H2t a5nXcNOpdAH2xTusRYmNgI7CnFpIAfCHJfHff4EREMUVlvSv+tzpcjtJZDbcMxH3sQ14 C12QeGul5Flck9K7osJColB6BjbLB7XqR4AHlt6xBeFYx3BN0HUEfK/H53ADKS5ejBWh 8sNg== X-Gm-Message-State: AD7BkJLzC96Bp4cCvs4o1iwxOM2nPsLkTGJ6DfjUwG0SvBANBlUOCuD4l5oc+8WnWtSisQ== X-Received: by 10.194.175.33 with SMTP id bx1mr14866372wjc.104.1458292448266; Fri, 18 Mar 2016 02:14:08 -0700 (PDT) Received: from localhost (LMontsouris-657-1-4-224.w90-63.abo.wanadoo.fr. [90.63.239.224]) by smtp.gmail.com with ESMTPSA id z127sm33802798wme.5.2016.03.18.02.14.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 18 Mar 2016 02:14:07 -0700 (PDT) From: Baptiste Reynal To: qemu-devel@nongnu.org Date: Fri, 18 Mar 2016 10:13:53 +0100 Message-Id: <1458292438-13909-2-git-send-email-b.reynal@virtualopensystems.com> X-Mailer: git-send-email 2.7.3 In-Reply-To: <1458292438-13909-1-git-send-email-b.reynal@virtualopensystems.com> References: <1458292438-13909-1-git-send-email-b.reynal@virtualopensystems.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2a00:1450:400c:c09::233 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 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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=,size=, chardev=,master=on Instantiation on the slave: -object memory-backend-shared,id=,size=, chardev=,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 --- 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 + * + * 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 + * + * 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 +#include +#include +#include + +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