Prepare for the move to dynamically allocated memory regions by
introducing memory_region_new and memory_region_new_io functions
which call through to object_new instead of object_initialize.

TBD: add "new" variants for all the other memory_region_init
variants.

Signed-off-by: Daniel P. Berrangé <[email protected]>
---
 include/system/memory.h | 76 ++++++++++++++++++++++++++++++------
 system/memory.c         | 85 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 136 insertions(+), 25 deletions(-)

diff --git a/include/system/memory.h b/include/system/memory.h
index 1417132f6d..b4c5a185c0 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -1300,19 +1300,44 @@ static inline bool 
memory_region_section_intersect_range(MemoryRegionSection *s,
 
 /**
  * memory_region_init: Initialize a memory region
- *
- * The region typically acts as a container for other memory regions.  Use
- * memory_region_add_subregion() to add subregions.
- *
  * @mr: the #MemoryRegion to be initialized
  * @owner: the object that tracks the region's reference count
  * @name: used for debugging; not visible to the user or ABI
  * @size: size of the region; any subregions beyond this size will be clipped
+ *
+ * The region typically acts as a container for other memory regions.  Use
+ * memory_region_add_subregion() to add subregions.
+ *
+ * Use of this function is now deprecated. All memory regions must be
+ * allocated using the memory_region_new() family of functions and not
+ * statically embedded in a larger struct.
  */
 void memory_region_init(MemoryRegion *mr,
                         Object *owner,
                         const char *name,
-                        uint64_t size);
+                        uint64_t size)
+    QEMU_DEPRECATED;
+
+
+/**
+ * memory_region_new: Allocate a memory region.
+ * @owner: the object that owns the memory region in the composition tree
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region; any subregions beyond this size will be clipped
+ *
+ * The region typically acts as a container for other memory regions.  Use
+ * memory_region_add_subregion() to add subregions.
+ *
+ * The returned memory region will have a single reference, which is
+ * held by the @owner object in the QOM composition tree. Thus in the
+ * absence of any further references being acquired, the memory region
+ * will be freed when @owner is freed
+ *
+ * Returns: the newly allocated memory region
+ */
+MemoryRegion *memory_region_new(Object *owner,
+                                const char *name,
+                                uint64_t size);
 
 /**
  * memory_region_ref: Add 1 to a memory region's reference count
@@ -1344,11 +1369,7 @@ void memory_region_ref(MemoryRegion *mr);
 void memory_region_unref(MemoryRegion *mr);
 
 /**
- * memory_region_init_io: Initialize an I/O memory region.
- *
- * Accesses into the region will cause the callbacks in @ops to be called.
- * if @size is nonzero, subregions will be clipped to @size.
- *
+ * memory_region_init_io: Initialize an I/O memory region
  * @mr: the #MemoryRegion to be initialized.
  * @owner: the object that tracks the region's reference count
  * @ops: a structure containing read and write callbacks to be used when
@@ -1356,13 +1377,46 @@ void memory_region_unref(MemoryRegion *mr);
  * @opaque: passed to the read and write callbacks of the @ops structure.
  * @name: used for debugging; not visible to the user or ABI
  * @size: size of the region.
+ *
+ * Accesses into the region will cause the callbacks in @ops to be called.
+ * if @size is nonzero, subregions will be clipped to @size.
+ *
+ * Use of this function is now deprecated. All memory regions must be
+ * allocated using the memory_region_new() family of functions and not
+ * statically embedded in a larger struct.
  */
 void memory_region_init_io(MemoryRegion *mr,
                            Object *owner,
                            const MemoryRegionOps *ops,
                            void *opaque,
                            const char *name,
-                           uint64_t size);
+                           uint64_t size)
+    QEMU_DEPRECATED;
+
+/**
+ * memory_region_new_io: Allocates an I/O memory region
+ * @owner: the object that tracks the region's reference count
+ * @ops: a structure containing read and write callbacks to be used when
+ *       I/O is performed on the region.
+ * @opaque: passed to the read and write callbacks of the @ops structure.
+ * @name: used for debugging; not visible to the user or ABI
+ * @size: size of the region.
+ *
+ * Accesses into the region will cause the callbacks in @ops to be called.
+ * if @size is nonzero, subregions will be clipped to @size.
+ *
+ * The returned memory region will have a single reference, which is
+ * held by the @owner object in the QOM composition tree. Thus in the
+ * absence of any further references being acquired, the memory region
+ * will be freed when @owner is freed
+ *
+ * Returns: the newly allocated memory region
+ */
+MemoryRegion *memory_region_new_io(Object *owner,
+                                   const MemoryRegionOps *ops,
+                                   void *opaque,
+                                   const char *name,
+                                   uint64_t size);
 
 /**
  * memory_region_init_ram_flags_nomigrate:  Initialize RAM memory region.
diff --git a/system/memory.c b/system/memory.c
index 739ba11da6..e8a539e37e 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1214,6 +1214,18 @@ static char *memory_region_escape_name(const char *name)
     return escaped;
 }
 
+static char *memory_region_make_child(Object **owner,
+                                      const char *name)
+{
+    g_autofree char *escaped_name = memory_region_escape_name(name);
+
+    if (!*owner) {
+        *owner = machine_get_container("unattached");
+    }
+
+    return g_strdup_printf("%s[*]", escaped_name);
+}
+
 static void memory_region_do_init(MemoryRegion *mr,
                                   Object *owner,
                                   const char *name,
@@ -1227,20 +1239,6 @@ static void memory_region_do_init(MemoryRegion *mr,
     mr->owner = owner;
     mr->dev = (DeviceState *) object_dynamic_cast(mr->owner, TYPE_DEVICE);
     mr->ram_block = NULL;
-
-    if (name) {
-        char *escaped_name = memory_region_escape_name(name);
-        char *name_array = g_strdup_printf("%s[*]", escaped_name);
-
-        if (!owner) {
-            owner = machine_get_container("unattached");
-        }
-
-        object_property_add_child(owner, name_array, OBJECT(mr));
-        object_unref(OBJECT(mr));
-        g_free(name_array);
-        g_free(escaped_name);
-    }
 }
 
 void memory_region_init(MemoryRegion *mr,
@@ -1250,6 +1248,31 @@ void memory_region_init(MemoryRegion *mr,
 {
     object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
     memory_region_do_init(mr, owner, name, size);
+    if (name) {
+        g_autofree char *childname = memory_region_make_child(&owner, name);
+        object_property_add_child(owner, childname, OBJECT(mr));
+        object_unref(OBJECT(mr));
+    }
+}
+
+MemoryRegion *memory_region_new(Object *owner,
+                                const char *name,
+                                uint64_t size)
+{
+    /*
+     * error_abort is safe, because 'childname' includes a wildcard
+     * for dynamically assigning a unique name. Thus adding the child
+     * property cannot fail
+     */
+    MemoryRegion *mr = MEMORY_REGION(object_new(TYPE_MEMORY_REGION));
+    memory_region_do_init(mr, owner, name, size);
+    if (name) {
+        g_autofree char *childname = memory_region_make_child(&owner, name);
+        object_property_add_child(owner, childname, OBJECT(mr));
+        object_unref(OBJECT(mr));
+
+    }
+    return mr;
 }
 
 static void memory_region_get_container(Object *obj, Visitor *v,
@@ -1574,10 +1597,22 @@ void memory_region_init_io(MemoryRegion *mr, Object 
*owner,
                            const char *name, uint64_t size)
 {
     g_assert(!ops || !(ops->impl.unaligned && !ops->valid.unaligned));
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init(mr, owner, name, size);
+    QEMU_DEPRECATIONS_ON;
     memory_region_set_ops(mr, ops, opaque);
 }
 
+MemoryRegion *memory_region_new_io(Object *owner,
+                                   const MemoryRegionOps *ops, void *opaque,
+                                   const char *name, uint64_t size)
+{
+    g_assert(!ops || !(ops->impl.unaligned && !ops->valid.unaligned));
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+    memory_region_set_ops(mr, ops, opaque);
+    return mr;
+}
+
 static bool memory_region_set_ram_block(MemoryRegion *mr, RAMBlock *rb)
 {
     mr->terminates = true;
@@ -1597,7 +1632,9 @@ bool memory_region_init_ram_flags_nomigrate(MemoryRegion 
*mr, Object *owner,
 {
     RAMBlock *rb;
 
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init(mr, owner, name, size);
+    QEMU_DEPRECATIONS_ON;
     mr->ram = true;
     rb = qemu_ram_alloc(size, ram_flags, mr, errp);
     return memory_region_set_ram_block(mr, rb);
@@ -1615,7 +1652,9 @@ bool memory_region_init_resizeable_ram(MemoryRegion *mr,
 {
     RAMBlock *rb;
 
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init(mr, owner, name, size);
+    QEMU_DEPRECATIONS_ON;
     mr->ram = true;
     rb = qemu_ram_alloc_resizeable(size, max_size, resized, mr, errp);
     return memory_region_set_ram_block(mr, rb);
@@ -1630,7 +1669,9 @@ bool memory_region_init_ram_from_file(MemoryRegion *mr, 
Object *owner,
 {
     RAMBlock *rb;
 
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init(mr, owner, name, size);
+    QEMU_DEPRECATIONS_ON;
     mr->ram = true;
     mr->readonly = !!(ram_flags & RAM_READONLY);
     mr->align = align;
@@ -1645,7 +1686,9 @@ bool memory_region_init_ram_from_fd(MemoryRegion *mr, 
Object *owner,
 {
     RAMBlock *rb;
 
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init(mr, owner, name, size);
+    QEMU_DEPRECATIONS_ON;
     mr->ram = true;
     mr->readonly = !!(ram_flags & RAM_READONLY);
     rb = qemu_ram_alloc_from_fd(size, size, NULL, mr, ram_flags, fd, offset,
@@ -1667,7 +1710,9 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, Object 
*owner,
                                 const char *name, uint64_t size,
                                 void *ptr)
 {
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init(mr, owner, name, size);
+    QEMU_DEPRECATIONS_ON;
     mr->ram = true;
     memory_region_set_ram_ptr(mr, size, ptr);
 }
@@ -1676,7 +1721,9 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, 
Object *owner,
                                        const char *name, uint64_t size,
                                        void *ptr)
 {
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init_io(mr, owner, &ram_device_mem_ops, mr, name, size);
+    QEMU_DEPRECATIONS_ON;
     mr->ram = true;
     mr->ram_device = true;
     memory_region_set_ram_ptr(mr, size, ptr);
@@ -1686,7 +1733,9 @@ void memory_region_init_alias(MemoryRegion *mr, Object 
*owner,
                               const char *name, MemoryRegion *orig,
                               hwaddr offset, uint64_t size)
 {
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init(mr, owner, name, size);
+    QEMU_DEPRECATIONS_ON;
     mr->alias = orig;
     mr->alias_offset = offset;
 }
@@ -1704,6 +1753,12 @@ void memory_region_init_iommu(void *_iommu_mr,
     object_initialize(_iommu_mr, instance_size, mrtypename);
     mr = MEMORY_REGION(_iommu_mr);
     memory_region_do_init(mr, owner, name, size);
+    if (name) {
+        g_autofree char *childname = memory_region_make_child(&owner, name);
+        object_property_add_child(owner, childname, OBJECT(mr));
+        object_unref(OBJECT(mr));
+    }
+
     iommu_mr = IOMMU_MEMORY_REGION(mr);
     mr->terminates = true;  /* then re-forwards */
     QLIST_INIT(&iommu_mr->iommu_notify);
@@ -3703,7 +3758,9 @@ bool memory_region_init_rom_device(MemoryRegion *mr, 
Object *owner,
     RAMBlock *rb;
 
     assert(ops);
+    QEMU_DEPRECATIONS_OFF;
     memory_region_init_io(mr, owner, ops, opaque, name, size);
+    QEMU_DEPRECATIONS_ON;
     rb = qemu_ram_alloc(size, 0, mr, errp);
     if (memory_region_set_ram_block(mr, rb)) {
         mr->rom_device = true;
-- 
2.54.0


Reply via email to