qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 12/16] hostmem: Introduce "managed-size" for memory-backend-ra


From: David Hildenbrand
Subject: [PATCH v2 12/16] hostmem: Introduce "managed-size" for memory-backend-ram
Date: Wed, 12 Feb 2020 14:35:57 +0100

virtio-mem wants to make use of resizable memory regions. Allow to
create them by the user by specifying "managed-size".

Disallow setting "managed-size" with "prealloc" and "shared". The latter
might theoretically be possible, however has to be wired up internally
first.

Support for memory-backend-ram only for now. Support for other backends
(especially, hugepages), can be added later (and once e.g., virtio-mem
also supports hugepages).

When the memory region gets resized, apply the same settings just as when
allocating the memory.

Fence off the all such memory backends in all existing users. We'll
convert virtio-mem soon.

Signed-off-by: David Hildenbrand <address@hidden>
---
 backends/hostmem-ram.c   | 18 ++++++++--
 backends/hostmem.c       | 72 ++++++++++++++++++++++++++++++++++++++--
 hw/mem/pc-dimm.c         |  3 +-
 hw/misc/ivshmem.c        |  2 +-
 hw/virtio/virtio-mem.c   |  2 +-
 hw/virtio/virtio-pmem.c  |  2 +-
 include/sysemu/hostmem.h |  8 +++--
 7 files changed, 97 insertions(+), 10 deletions(-)

diff --git a/backends/hostmem-ram.c b/backends/hostmem-ram.c
index 6aab8d3a73..881276cf6b 100644
--- a/backends/hostmem-ram.c
+++ b/backends/hostmem-ram.c
@@ -29,8 +29,21 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error 
**errp)
     }
 
     name = host_memory_backend_get_name(backend);
-    memory_region_init_ram_shared_nomigrate(&backend->mr, OBJECT(backend), 
name,
-                           backend->size, backend->share, errp);
+    if (backend->managed_size) {
+        /*
+         * The size of a memory region must always be > 0 - start with 1. The
+         * managing object/device will resize accordingly.
+         */
+        g_assert(!backend->share);
+        memory_region_init_resizeable_ram(&backend->mr, OBJECT(backend), name,
+                                          1, backend->size,
+                                          host_memory_backend_resized,
+                                          errp);
+    } else {
+        memory_region_init_ram_shared_nomigrate(&backend->mr, OBJECT(backend),
+                                                name, backend->size,
+                                                backend->share, errp);
+    }
     g_free(name);
 }
 
@@ -40,6 +53,7 @@ ram_backend_class_init(ObjectClass *oc, void *data)
     HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc);
 
     bc->alloc = ram_backend_memory_alloc;
+    bc->managed_size_supported = true;
 }
 
 static const TypeInfo ram_backend_info = {
diff --git a/backends/hostmem.c b/backends/hostmem.c
index de37f1bf5d..c3c453753a 100644
--- a/backends/hostmem.c
+++ b/backends/hostmem.c
@@ -238,7 +238,10 @@ static void host_memory_backend_set_prealloc(Object *obj, 
bool value,
         return;
     }
 
-    if (value && !backend->prealloc) {
+    if (value && backend->managed_size) {
+        error_setg(errp, "'prealloc' is not compatible with 'managed-size'");
+        return;
+    } else if (value && !backend->prealloc) {
         int fd = memory_region_get_fd(&backend->mr);
         void *ptr = memory_region_get_ram_ptr(&backend->mr);
         uint64_t sz = memory_region_size(&backend->mr);
@@ -292,7 +295,8 @@ bool host_memory_backend_is_mapped(HostMemoryBackend 
*backend)
 }
 
 void host_memory_backend_validate(HostMemoryBackend *backend,
-                                  const char *property, Error **errp)
+                                  const char *property,
+                                  bool managed_size_support, Error **errp)
 {
     char *path = object_get_canonical_path_component(OBJECT(backend));
 
@@ -301,6 +305,10 @@ void host_memory_backend_validate(HostMemoryBackend 
*backend,
     } else if (host_memory_backend_is_mapped(backend)) {
         error_setg(errp, "'%s' property specifies a busy memdev: %s",
                    property, path);
+    } else if (backend->managed_size && !managed_size_support) {
+        error_setg(errp,
+                   "'%s' property does not support a memdev with a managed 
size: %s",
+                   property, path);
     }
     g_free(path);
 }
@@ -395,6 +403,24 @@ static void 
host_memory_backend_apply_settings(HostMemoryBackend *backend,
     }
 }
 
+void host_memory_backend_resized(Object *owner, const char *idstr,
+                                 uint64_t size, void *host)
+{
+    HostMemoryBackend *backend = MEMORY_BACKEND(owner);
+    Error *local_err = NULL;
+
+    /*
+     * Just apply the settings for all (resized) memory again. Note that
+     * "shared" and "prealloc" is currently not compatible with resizable 
memory
+     * regions ("managed-size"). Warn only.
+     */
+    host_memory_backend_apply_settings(backend, &local_err);
+    if (local_err) {
+         warn_report_err(local_err);
+         local_err = NULL;
+    }
+}
+
 static void
 host_memory_backend_memory_complete(UserCreatable *uc, Error **errp)
 {
@@ -441,6 +467,9 @@ static void host_memory_backend_set_share(Object *o, bool 
value, Error **errp)
     if (host_memory_backend_mr_inited(backend)) {
         error_setg(errp, "cannot change property value");
         return;
+    } else if (value && backend->managed_size) {
+        error_setg(errp, "'prealloc' is not compatible with 'managed-size'");
+        return;
     }
     backend->share = value;
 }
@@ -462,6 +491,39 @@ host_memory_backend_set_use_canonical_path(Object *obj, 
bool value,
     backend->use_canonical_path = value;
 }
 
+static bool
+ram_backend_get_managed_size(Object *obj, Error **errp)
+{
+    return MEMORY_BACKEND(obj)->managed_size;
+}
+
+static void
+ram_backend_set_managed_size(Object *obj, bool value, Error **errp)
+{
+    HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+    HostMemoryBackendClass *bc = MEMORY_BACKEND_GET_CLASS(obj);
+
+    if (host_memory_backend_mr_inited(backend)) {
+        error_setg(errp, "cannot change property @managed_size'");
+        return;
+    } else if (value && !bc->managed_size_supported) {
+        error_setg(errp,
+                   "'managed-size' is not supported yet for %s",
+                   object_get_typename(obj));
+        return;
+    } else if (value && (backend->force_prealloc || backend->prealloc)) {
+        error_setg(errp,
+                   "'managed-size' is not compatible with preallocated 
memory");
+        return;
+    } else if (value && backend->share) {
+        error_setg(errp,
+                   "'managed-size' is not compatible with shared memory");
+        return;
+    }
+
+    backend->managed_size = value;
+}
+
 static void
 host_memory_backend_class_init(ObjectClass *oc, void *data)
 {
@@ -511,6 +573,12 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
     object_class_property_add_bool(oc, "x-use-canonical-path-for-ramblock-id",
         host_memory_backend_get_use_canonical_path,
         host_memory_backend_set_use_canonical_path, &error_abort);
+    object_class_property_add_bool(oc, "managed-size",
+                                   ram_backend_get_managed_size,
+                                   ram_backend_set_managed_size, &error_abort);
+    object_class_property_set_description(oc, "managed-size",
+        "The owner manages the actual size, 'size' is an upper limit",
+                                          &error_abort);
 }
 
 static const TypeInfo host_memory_backend_info = {
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 9ee634ee89..5021cb347d 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -176,7 +176,8 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
     int nb_numa_nodes = ms->numa_state->num_nodes;
     Error *err = NULL;
 
-    host_memory_backend_validate(dimm->hostmem, PC_DIMM_MEMDEV_PROP, &err);
+    host_memory_backend_validate(dimm->hostmem, PC_DIMM_MEMDEV_PROP, false,
+                                 &err);
     if (err) {
         error_propagate(errp, err);
         return;
diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c
index 39bffceadf..69d16c2dca 100644
--- a/hw/misc/ivshmem.c
+++ b/hw/misc/ivshmem.c
@@ -1037,7 +1037,7 @@ static void ivshmem_plain_realize(PCIDevice *dev, Error 
**errp)
     IVShmemState *s = IVSHMEM_COMMON(dev);
     Error *err = NULL;
 
-    host_memory_backend_validate(s->hostmem, "memdev", &err);
+    host_memory_backend_validate(s->hostmem, "memdev", false, &err);
     if (err) {
         error_propagate(errp, err);
         return;
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index 4b7b4cf950..093b6eb0bb 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -415,7 +415,7 @@ static void virtio_mem_device_realize(DeviceState *dev, 
Error **errp)
 
     /* verify the memdev */
     host_memory_backend_validate(vm->memdev, VIRTIO_MEM_MEMDEV_PROP,
-                                 &local_err);
+                                 false, &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
         return;
diff --git a/hw/virtio/virtio-pmem.c b/hw/virtio/virtio-pmem.c
index 85cb337ed5..51f01e52fd 100644
--- a/hw/virtio/virtio-pmem.c
+++ b/hw/virtio/virtio-pmem.c
@@ -107,7 +107,7 @@ static void virtio_pmem_realize(DeviceState *dev, Error 
**errp)
     VirtIOPMEM *pmem = VIRTIO_PMEM(dev);
     Error *err = NULL;
 
-    host_memory_backend_validate(pmem->memdev, "memdev", &err);
+    host_memory_backend_validate(pmem->memdev, "memdev", false, &err);
     if (err) {
         error_propagate(errp, err);
         return;
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
index d4dbf108ca..f5ef7016bc 100644
--- a/include/sysemu/hostmem.h
+++ b/include/sysemu/hostmem.h
@@ -37,6 +37,7 @@ struct HostMemoryBackendClass {
     ObjectClass parent_class;
 
     void (*alloc)(HostMemoryBackend *backend, Error **errp);
+    bool managed_size_supported;
 };
 
 /**
@@ -53,7 +54,7 @@ struct HostMemoryBackend {
     /* protected */
     uint64_t size;
     bool merge, dump, use_canonical_path;
-    bool prealloc, force_prealloc, is_mapped, share;
+    bool prealloc, force_prealloc, is_mapped, share, managed_size;
     DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
     HostMemPolicy policy;
 
@@ -61,12 +62,15 @@ struct HostMemoryBackend {
 };
 
 bool host_memory_backend_mr_inited(HostMemoryBackend *backend);
+void host_memory_backend_resized(Object *owner, const char *idstr,
+                                 uint64_t size, void *host);
 MemoryRegion *host_memory_backend_get_memory(HostMemoryBackend *backend);
 
 void host_memory_backend_set_mapped(HostMemoryBackend *backend, bool mapped);
 bool host_memory_backend_is_mapped(HostMemoryBackend *backend);
 void host_memory_backend_validate(HostMemoryBackend *backend,
-                                  const char *property, Error **errp);
+                                  const char *property,
+                                  bool managed_size_support, Error **errp);
 size_t host_memory_backend_pagesize(HostMemoryBackend *memdev);
 char *host_memory_backend_get_name(HostMemoryBackend *backend);
 
-- 
2.24.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]