All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] Implement memory_region_new_* functions
@ 2025-12-23 21:49 BALATON Zoltan
  2025-12-23 21:49 ` [PATCH 1/6] memory: Add internal memory_region_set_ops helper function BALATON Zoltan
                   ` (6 more replies)
  0 siblings, 7 replies; 15+ messages in thread
From: BALATON Zoltan @ 2025-12-23 21:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

Our documentation says that memory regions are automatically freed
when the owner dies and the reference counting to do this is also
implemented. However this relies on the QOM free funtion that can only
be set by creating objects with object_new but memory API only
provides constructors that call object_initialize which clears the
free function that prevents QOM to manage the memory region lifetime.
Implement corresponding memory_region_new_* functions that do the same
as the memory_region_init_* functions but create the memory region
with object_new so the lifetime can be automatically managed by QOM as
documented.

BALATON Zoltan (6):
  memory: Add internal memory_region_set_ops helper function
  memory: Factor out common ram region initialization
  memory: Factor out more common ram region initialization
  memory: Shorten memory_region_init_rom_nomigrate
  memory: Add internal memory_region_register_ram function
  memory: Add memory_region_new* functions

 include/system/memory.h | 360 ++++++++++++++++++++++++++++++
 system/memory.c         | 484 +++++++++++++++++++++++++---------------
 2 files changed, 668 insertions(+), 176 deletions(-)

-- 
2.41.3



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/6] memory: Add internal memory_region_set_ops helper function
  2025-12-23 21:49 [PATCH 0/6] Implement memory_region_new_* functions BALATON Zoltan
@ 2025-12-23 21:49 ` BALATON Zoltan
  2025-12-23 21:49 ` [PATCH 2/6] memory: Factor out common ram region initialization BALATON Zoltan
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: BALATON Zoltan @ 2025-12-23 21:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

This is a common operation used at multiple places, add a helper
function for it.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 system/memory.c | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/system/memory.c b/system/memory.c
index 8b84661ae3..a003095632 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1559,6 +1559,15 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
     }
 }
 
+static void memory_region_set_ops(MemoryRegion *mr,
+                                  const MemoryRegionOps *ops,
+                                  void *opaque)
+{
+    mr->ops = ops ?: &unassigned_mem_ops;
+    mr->opaque = opaque;
+    mr->terminates = true;
+}
+
 void memory_region_init_io(MemoryRegion *mr,
                            Object *owner,
                            const MemoryRegionOps *ops,
@@ -1567,9 +1576,7 @@ void memory_region_init_io(MemoryRegion *mr,
                            uint64_t size)
 {
     memory_region_init(mr, owner, name, size);
-    mr->ops = ops ? ops : &unassigned_mem_ops;
-    mr->opaque = opaque;
-    mr->terminates = true;
+    memory_region_set_ops(mr, ops, opaque);
 }
 
 bool memory_region_init_ram_nomigrate(MemoryRegion *mr,
@@ -1710,10 +1717,8 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr,
 {
     memory_region_init(mr, owner, name, size);
     mr->ram = true;
-    mr->terminates = true;
     mr->ram_device = true;
-    mr->ops = &ram_device_mem_ops;
-    mr->opaque = mr;
+    memory_region_set_ops(mr, &ram_device_mem_ops, mr);
     mr->destructor = memory_region_destructor_ram;
 
     /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL.  */
@@ -1759,9 +1764,7 @@ bool memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
     Error *err = NULL;
     assert(ops);
     memory_region_init(mr, owner, name, size);
-    mr->ops = ops;
-    mr->opaque = opaque;
-    mr->terminates = true;
+    memory_region_set_ops(mr, ops, opaque);
     mr->rom_device = true;
     mr->destructor = memory_region_destructor_ram;
     mr->ram_block = qemu_ram_alloc(size, 0, mr, &err);
-- 
2.41.3



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/6] memory: Factor out common ram region initialization
  2025-12-23 21:49 [PATCH 0/6] Implement memory_region_new_* functions BALATON Zoltan
  2025-12-23 21:49 ` [PATCH 1/6] memory: Add internal memory_region_set_ops helper function BALATON Zoltan
@ 2025-12-23 21:49 ` BALATON Zoltan
  2025-12-24 15:33   ` Peter Xu
  2025-12-23 21:49 ` [PATCH 3/6] memory: Factor out more " BALATON Zoltan
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: BALATON Zoltan @ 2025-12-23 21:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

Introduce internal memory_region_do_init_ram() function to remove
duplicated code from different memory_region_init_*ram functions.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 system/memory.c | 147 +++++++++++++++++-------------------------------
 1 file changed, 53 insertions(+), 94 deletions(-)

diff --git a/system/memory.c b/system/memory.c
index a003095632..87c8e78662 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1579,29 +1579,12 @@ void memory_region_init_io(MemoryRegion *mr,
     memory_region_set_ops(mr, ops, opaque);
 }
 
-bool memory_region_init_ram_nomigrate(MemoryRegion *mr,
-                                      Object *owner,
-                                      const char *name,
-                                      uint64_t size,
-                                      Error **errp)
-{
-    return memory_region_init_ram_flags_nomigrate(mr, owner, name,
-                                                  size, 0, errp);
-}
-
-bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
-                                            Object *owner,
-                                            const char *name,
-                                            uint64_t size,
-                                            uint32_t ram_flags,
-                                            Error **errp)
+static bool memory_region_do_init_ram(MemoryRegion *mr,
+                                      Error *err, Error **errp)
 {
-    Error *err = NULL;
-    memory_region_init(mr, owner, name, size);
     mr->ram = true;
     mr->terminates = true;
     mr->destructor = memory_region_destructor_ram;
-    mr->ram_block = qemu_ram_alloc(size, ram_flags, mr, &err);
     if (err) {
         mr->size = int128_zero();
         object_unparent(OBJECT(mr));
@@ -1611,6 +1594,25 @@ bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
     return true;
 }
 
+bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr, Object *owner,
+                                            const char *name, uint64_t size,
+                                            uint32_t ram_flags, Error **errp)
+{
+    Error *err = NULL;
+
+    memory_region_init(mr, owner, name, size);
+    mr->ram_block = qemu_ram_alloc(size, ram_flags, mr, &err);
+    return memory_region_do_init_ram(mr, err, errp);
+}
+
+bool memory_region_init_ram_nomigrate(MemoryRegion *mr, Object *owner,
+                                      const char *name, uint64_t size,
+                                      Error **errp)
+{
+    return memory_region_init_ram_flags_nomigrate(mr, owner, name, size, 0,
+                                                  errp);
+}
+
 bool memory_region_init_resizeable_ram(MemoryRegion *mr,
                                        Object *owner,
                                        const char *name,
@@ -1622,108 +1624,66 @@ bool memory_region_init_resizeable_ram(MemoryRegion *mr,
                                        Error **errp)
 {
     Error *err = NULL;
+
     memory_region_init(mr, owner, name, size);
-    mr->ram = true;
-    mr->terminates = true;
-    mr->destructor = memory_region_destructor_ram;
-    mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized,
-                                              mr, &err);
-    if (err) {
-        mr->size = int128_zero();
-        object_unparent(OBJECT(mr));
-        error_propagate(errp, err);
-        return false;
-    }
-    return true;
+    mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, mr,
+                                              &err);
+    return memory_region_do_init_ram(mr, err, errp);
 }
 
 #if defined(CONFIG_POSIX) && !defined(EMSCRIPTEN)
-bool memory_region_init_ram_from_file(MemoryRegion *mr,
-                                      Object *owner,
-                                      const char *name,
-                                      uint64_t size,
-                                      uint64_t align,
-                                      uint32_t ram_flags,
-                                      const char *path,
-                                      ram_addr_t offset,
+bool memory_region_init_ram_from_file(MemoryRegion *mr, Object *owner,
+                                      const char *name, uint64_t size,
+                                      uint64_t align, uint32_t ram_flags,
+                                      const char *path, ram_addr_t offset,
                                       Error **errp)
 {
     Error *err = NULL;
+
     memory_region_init(mr, owner, name, size);
-    mr->ram = true;
     mr->readonly = !!(ram_flags & RAM_READONLY);
-    mr->terminates = true;
-    mr->destructor = memory_region_destructor_ram;
     mr->align = align;
-    mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path,
-                                             offset, &err);
-    if (err) {
-        mr->size = int128_zero();
-        object_unparent(OBJECT(mr));
-        error_propagate(errp, err);
-        return false;
-    }
-    return true;
+    mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, offset,
+                                             &err);
+    return memory_region_do_init_ram(mr, err, errp);
 }
 
-bool memory_region_init_ram_from_fd(MemoryRegion *mr,
-                                    Object *owner,
-                                    const char *name,
-                                    uint64_t size,
-                                    uint32_t ram_flags,
-                                    int fd,
-                                    ram_addr_t offset,
-                                    Error **errp)
+bool memory_region_init_ram_from_fd(MemoryRegion *mr, Object *owner,
+                                    const char *name, uint64_t size,
+                                    uint32_t ram_flags, int fd,
+                                    ram_addr_t offset, Error **errp)
 {
     Error *err = NULL;
+
     memory_region_init(mr, owner, name, size);
-    mr->ram = true;
     mr->readonly = !!(ram_flags & RAM_READONLY);
-    mr->terminates = true;
-    mr->destructor = memory_region_destructor_ram;
     mr->ram_block = qemu_ram_alloc_from_fd(size, size, NULL, mr, ram_flags, fd,
                                            offset, false, &err);
-    if (err) {
-        mr->size = int128_zero();
-        object_unparent(OBJECT(mr));
-        error_propagate(errp, err);
-        return false;
-    }
-    return true;
+    return memory_region_do_init_ram(mr, err, errp);
 }
 #endif
 
-void memory_region_init_ram_ptr(MemoryRegion *mr,
-                                Object *owner,
-                                const char *name,
-                                uint64_t size,
-                                void *ptr)
+void memory_region_init_ram_ptr(MemoryRegion *mr, Object *owner,
+                                const char *name, uint64_t size, void *ptr)
 {
     memory_region_init(mr, owner, name, size);
-    mr->ram = true;
-    mr->terminates = true;
-    mr->destructor = memory_region_destructor_ram;
-
     /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL.  */
     assert(ptr != NULL);
     mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort);
+    memory_region_do_init_ram(mr, NULL, NULL);
 }
 
-void memory_region_init_ram_device_ptr(MemoryRegion *mr,
-                                       Object *owner,
-                                       const char *name,
-                                       uint64_t size,
+void memory_region_init_ram_device_ptr(MemoryRegion *mr, Object *owner,
+                                       const char *name, uint64_t size,
                                        void *ptr)
 {
     memory_region_init(mr, owner, name, size);
-    mr->ram = true;
-    mr->ram_device = true;
     memory_region_set_ops(mr, &ram_device_mem_ops, mr);
-    mr->destructor = memory_region_destructor_ram;
-
     /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL.  */
     assert(ptr != NULL);
     mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort);
+    memory_region_do_init_ram(mr, NULL, NULL);
+    mr->ram_device = true;
 }
 
 void memory_region_init_alias(MemoryRegion *mr,
@@ -1762,19 +1722,18 @@ bool memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
                                              Error **errp)
 {
     Error *err = NULL;
+    bool ret;
+
     assert(ops);
     memory_region_init(mr, owner, name, size);
     memory_region_set_ops(mr, ops, opaque);
-    mr->rom_device = true;
-    mr->destructor = memory_region_destructor_ram;
     mr->ram_block = qemu_ram_alloc(size, 0, mr, &err);
-    if (err) {
-        mr->size = int128_zero();
-        object_unparent(OBJECT(mr));
-        error_propagate(errp, err);
-        return false;
+    ret = memory_region_do_init_ram(mr, err, errp);
+    if (ret) {
+        mr->ram = false;
+        mr->rom_device = true;
     }
-    return true;
+    return ret;
 }
 
 void memory_region_init_iommu(void *_iommu_mr,
-- 
2.41.3



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/6] memory: Factor out more common ram region initialization
  2025-12-23 21:49 [PATCH 0/6] Implement memory_region_new_* functions BALATON Zoltan
  2025-12-23 21:49 ` [PATCH 1/6] memory: Add internal memory_region_set_ops helper function BALATON Zoltan
  2025-12-23 21:49 ` [PATCH 2/6] memory: Factor out common ram region initialization BALATON Zoltan
@ 2025-12-23 21:49 ` BALATON Zoltan
  2025-12-26 11:31   ` Philippe Mathieu-Daudé
  2025-12-23 21:50 ` [PATCH 4/6] memory: Shorten memory_region_init_rom_nomigrate BALATON Zoltan
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: BALATON Zoltan @ 2025-12-23 21:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

Introduce internal memory_region_do_init_ram_ptr() function to remove
duplicated code from different memory_region_init_ram_*ptr functions.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 system/memory.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/system/memory.c b/system/memory.c
index 87c8e78662..3d538fb9af 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1663,26 +1663,29 @@ bool memory_region_init_ram_from_fd(MemoryRegion *mr, Object *owner,
 }
 #endif
 
-void memory_region_init_ram_ptr(MemoryRegion *mr, Object *owner,
-                                const char *name, uint64_t size, void *ptr)
+static void memory_region_do_init_ram_ptr(MemoryRegion *mr, uint64_t size,
+                                          void *ptr)
 {
-    memory_region_init(mr, owner, name, size);
     /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL.  */
     assert(ptr != NULL);
     mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort);
     memory_region_do_init_ram(mr, NULL, NULL);
 }
 
+void memory_region_init_ram_ptr(MemoryRegion *mr, Object *owner,
+                                const char *name, uint64_t size, void *ptr)
+{
+    memory_region_init(mr, owner, name, size);
+    memory_region_do_init_ram_ptr(mr, size, ptr);
+}
+
 void memory_region_init_ram_device_ptr(MemoryRegion *mr, Object *owner,
                                        const char *name, uint64_t size,
                                        void *ptr)
 {
     memory_region_init(mr, owner, name, size);
     memory_region_set_ops(mr, &ram_device_mem_ops, mr);
-    /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL.  */
-    assert(ptr != NULL);
-    mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort);
-    memory_region_do_init_ram(mr, NULL, NULL);
+    memory_region_do_init_ram_ptr(mr, size, ptr);
     mr->ram_device = true;
 }
 
-- 
2.41.3



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/6] memory: Shorten memory_region_init_rom_nomigrate
  2025-12-23 21:49 [PATCH 0/6] Implement memory_region_new_* functions BALATON Zoltan
                   ` (2 preceding siblings ...)
  2025-12-23 21:49 ` [PATCH 3/6] memory: Factor out more " BALATON Zoltan
@ 2025-12-23 21:50 ` BALATON Zoltan
  2025-12-23 21:50 ` [PATCH 5/6] memory: Add internal memory_region_register_ram function BALATON Zoltan
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 15+ messages in thread
From: BALATON Zoltan @ 2025-12-23 21:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

Use the shortcut memory_region_init_ram_nomigrate as we have no flags
to pass and remove some extra line breaks to make the function occupy
less lines. Also shorten some other function prototypes.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 system/memory.c | 30 ++++++++++--------------------
 1 file changed, 10 insertions(+), 20 deletions(-)

diff --git a/system/memory.c b/system/memory.c
index 3d538fb9af..bff9677f7a 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1568,12 +1568,9 @@ static void memory_region_set_ops(MemoryRegion *mr,
     mr->terminates = true;
 }
 
-void memory_region_init_io(MemoryRegion *mr,
-                           Object *owner,
-                           const MemoryRegionOps *ops,
-                           void *opaque,
-                           const char *name,
-                           uint64_t size)
+void memory_region_init_io(MemoryRegion *mr, Object *owner,
+                           const MemoryRegionOps *ops, void *opaque,
+                           const char *name, uint64_t size)
 {
     memory_region_init(mr, owner, name, size);
     memory_region_set_ops(mr, ops, opaque);
@@ -1689,30 +1686,23 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, Object *owner,
     mr->ram_device = true;
 }
 
-void memory_region_init_alias(MemoryRegion *mr,
-                              Object *owner,
-                              const char *name,
-                              MemoryRegion *orig,
-                              hwaddr offset,
-                              uint64_t size)
+void memory_region_init_alias(MemoryRegion *mr, Object *owner,
+                              const char *name, MemoryRegion *orig,
+                              hwaddr offset, uint64_t size)
 {
     memory_region_init(mr, owner, name, size);
     mr->alias = orig;
     mr->alias_offset = offset;
 }
 
-bool memory_region_init_rom_nomigrate(MemoryRegion *mr,
-                                      Object *owner,
-                                      const char *name,
-                                      uint64_t size,
+bool memory_region_init_rom_nomigrate(MemoryRegion *mr, Object *owner,
+                                      const char *name, uint64_t size,
                                       Error **errp)
 {
-    if (!memory_region_init_ram_flags_nomigrate(mr, owner, name,
-                                                size, 0, errp)) {
-         return false;
+    if (!memory_region_init_ram_nomigrate(mr, owner, name, size, errp)) {
+        return false;
     }
     mr->readonly = true;
-
     return true;
 }
 
-- 
2.41.3



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/6] memory: Add internal memory_region_register_ram function
  2025-12-23 21:49 [PATCH 0/6] Implement memory_region_new_* functions BALATON Zoltan
                   ` (3 preceding siblings ...)
  2025-12-23 21:50 ` [PATCH 4/6] memory: Shorten memory_region_init_rom_nomigrate BALATON Zoltan
@ 2025-12-23 21:50 ` BALATON Zoltan
  2025-12-26 11:32   ` Philippe Mathieu-Daudé
  2025-12-23 21:50 ` [PATCH 6/6] memory: Add memory_region_new* functions BALATON Zoltan
  2025-12-24  5:21 ` [PATCH 0/6] Implement memory_region_new_* functions Akihiko Odaki
  6 siblings, 1 reply; 15+ messages in thread
From: BALATON Zoltan @ 2025-12-23 21:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

Factor out common operation from memory_region_init_{ram,rom}
functions to register the region for migration. This avoids
duplicating the long comment in several functions.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 system/memory.c | 75 +++++++++++++------------------------------------
 1 file changed, 20 insertions(+), 55 deletions(-)

diff --git a/system/memory.c b/system/memory.c
index bff9677f7a..74244be130 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -3678,17 +3678,10 @@ void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled)
     }
 }
 
-bool memory_region_init_ram(MemoryRegion *mr,
-                            Object *owner,
-                            const char *name,
-                            uint64_t size,
-                            Error **errp)
+static void memory_region_register_ram(MemoryRegion *mr, Object *owner)
 {
     DeviceState *owner_dev;
 
-    if (!memory_region_init_ram_nomigrate(mr, owner, name, size, errp)) {
-        return false;
-    }
     /* This will assert if owner is neither NULL nor a DeviceState.
      * We only want the owner here for the purposes of defining a
      * unique name for migration. TODO: Ideally we should implement
@@ -3697,80 +3690,52 @@ bool memory_region_init_ram(MemoryRegion *mr,
      */
     owner_dev = DEVICE(owner);
     vmstate_register_ram(mr, owner_dev);
+}
 
+bool memory_region_init_ram(MemoryRegion *mr, Object *owner,
+                            const char *name, uint64_t size,
+                            Error **errp)
+{
+    if (!memory_region_init_ram_nomigrate(mr, owner, name, size, errp)) {
+        return false;
+    }
+    memory_region_register_ram(mr, owner);
     return true;
 }
 
-bool memory_region_init_ram_guest_memfd(MemoryRegion *mr,
-                                        Object *owner,
-                                        const char *name,
-                                        uint64_t size,
+bool memory_region_init_ram_guest_memfd(MemoryRegion *mr, Object *owner,
+                                        const char *name, uint64_t size,
                                         Error **errp)
 {
-    DeviceState *owner_dev;
-
     if (!memory_region_init_ram_flags_nomigrate(mr, owner, name, size,
                                                 RAM_GUEST_MEMFD, errp)) {
         return false;
     }
-    /* This will assert if owner is neither NULL nor a DeviceState.
-     * We only want the owner here for the purposes of defining a
-     * unique name for migration. TODO: Ideally we should implement
-     * a naming scheme for Objects which are not DeviceStates, in
-     * which case we can relax this restriction.
-     */
-    owner_dev = DEVICE(owner);
-    vmstate_register_ram(mr, owner_dev);
-
+    memory_region_register_ram(mr, owner);
     return true;
 }
 
-bool memory_region_init_rom(MemoryRegion *mr,
-                            Object *owner,
-                            const char *name,
-                            uint64_t size,
+bool memory_region_init_rom(MemoryRegion *mr, Object *owner,
+                            const char *name, uint64_t size,
                             Error **errp)
 {
-    DeviceState *owner_dev;
-
     if (!memory_region_init_rom_nomigrate(mr, owner, name, size, errp)) {
         return false;
     }
-    /* This will assert if owner is neither NULL nor a DeviceState.
-     * We only want the owner here for the purposes of defining a
-     * unique name for migration. TODO: Ideally we should implement
-     * a naming scheme for Objects which are not DeviceStates, in
-     * which case we can relax this restriction.
-     */
-    owner_dev = DEVICE(owner);
-    vmstate_register_ram(mr, owner_dev);
-
+    memory_region_register_ram(mr, owner);
     return true;
 }
 
-bool memory_region_init_rom_device(MemoryRegion *mr,
-                                   Object *owner,
-                                   const MemoryRegionOps *ops,
-                                   void *opaque,
-                                   const char *name,
-                                   uint64_t size,
+bool memory_region_init_rom_device(MemoryRegion *mr, Object *owner,
+                                   const MemoryRegionOps *ops, void *opaque,
+                                   const char *name, uint64_t size,
                                    Error **errp)
 {
-    DeviceState *owner_dev;
-
     if (!memory_region_init_rom_device_nomigrate(mr, owner, ops, opaque,
                                                  name, size, errp)) {
         return false;
     }
-    /* This will assert if owner is neither NULL nor a DeviceState.
-     * We only want the owner here for the purposes of defining a
-     * unique name for migration. TODO: Ideally we should implement
-     * a naming scheme for Objects which are not DeviceStates, in
-     * which case we can relax this restriction.
-     */
-    owner_dev = DEVICE(owner);
-    vmstate_register_ram(mr, owner_dev);
-
+    memory_region_register_ram(mr, owner);
     return true;
 }
 
-- 
2.41.3



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/6] memory: Add memory_region_new* functions
  2025-12-23 21:49 [PATCH 0/6] Implement memory_region_new_* functions BALATON Zoltan
                   ` (4 preceding siblings ...)
  2025-12-23 21:50 ` [PATCH 5/6] memory: Add internal memory_region_register_ram function BALATON Zoltan
@ 2025-12-23 21:50 ` BALATON Zoltan
  2025-12-24  5:21 ` [PATCH 0/6] Implement memory_region_new_* functions Akihiko Odaki
  6 siblings, 0 replies; 15+ messages in thread
From: BALATON Zoltan @ 2025-12-23 21:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

These are counterparts of similar memory_region_init* functions but
differ in that these allocate the memory region with object_new so the
memory region will be managed by QOM and freed with the owner. This
behaviour was already documented and the reference tracking is
implemented but it could not be used without these functions because
memory_region_init* functions call object_initialize that resets the
free function of the object so it would not be freed.

Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
---
 include/system/memory.h | 360 ++++++++++++++++++++++++++++++++++++++++
 system/memory.c         | 212 +++++++++++++++++++++++
 2 files changed, 572 insertions(+)

diff --git a/include/system/memory.h b/include/system/memory.h
index 3bd5ffa5e0..5bdaa52355 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -1763,6 +1763,366 @@ bool memory_region_init_rom_device(MemoryRegion *mr,
                                    uint64_t size,
                                    Error **errp);
 
+/**
+ * memory_region_new: Allocate and initialize a memory region
+ *
+ * This is like memory_region_init() but allocates the #MemoryRegion and
+ * attaches it to the owner to free it when the owner is freed.
+ *
+ * @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
+ *
+ * Return: Pointer to the allocated #MemoryRegion.
+ */
+MemoryRegion *memory_region_new(Object *owner,
+                                const char *name, uint64_t size);
+
+/**
+ * memory_region_new_io: Allocate and initialize an I/O memory region.
+ *
+ * This is like memory_region_init_io() but allocates the #MemoryRegion and
+ * attaches it to the owner to free it when the owner is freed.
+ *
+ * @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.
+ *
+ * Return: Pointer to the allocated #MemoryRegion.
+ */
+MemoryRegion *memory_region_new_io(Object *owner,
+                                   const MemoryRegionOps *ops, void *opaque,
+                                   const char *name, uint64_t size);
+
+/**
+ * memory_region_new_ram_nomigrate:  Allocate and initialize RAM memory region.
+ *
+ * This is like memory_region_init_ram_nomigrate() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: size of the region.
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Note that this function does not do anything to cause the data in the
+ * RAM memory region to be migrated; that is the responsibility of the caller.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_ram_nomigrate(Object *owner,
+                                              const char *name, uint64_t size,
+                                              Error **errp);
+
+/**
+ * memory_region_new_ram_flags_nomigrate:  Allocata and initialize RAM memory
+ *                                         region with flags.
+ *
+ * This is like memory_region_init_ram_flags_nomigrate() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: size of the region.
+ * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_NORESERVE,
+ *             RAM_GUEST_MEMFD.
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Note that this function does not do anything to cause the data in the
+ * RAM memory region to be migrated; that is the responsibility of the caller.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_ram_flags_nomigrate(Object *owner,
+                                                    const char *name,
+                                                    uint64_t size,
+                                                    uint32_t ram_flags,
+                                                    Error **errp);
+
+/**
+ * memory_region_new_resizeable_ram:  Allocate and initialize memory region
+ *                                    with resizable RAM.
+ *
+ * This is like memory_region_init_resizable_ram() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: used size of the region.
+ * @max_size: max size of the region.
+ * @resized: callback to notify owner about used size change.
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Note that this function does not do anything to cause the data in the
+ * RAM memory region to be migrated; that is the responsibility of the caller.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_resizeable_ram(Object *owner,
+                                               const char *name,
+                                               uint64_t size,
+                                               uint64_t max_size,
+                                               void (*resized)(const char*,
+                                                               uint64_t length,
+                                                               void *host),
+                                               Error **errp);
+
+/**
+ * memory_region_new_ram_from_file:  Allocate and initialize RAM memory region
+ *                                   with a mmap-ed backend.
+ *
+ * This is like memory_region_init_ram_from_file() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: size of the region.
+ * @align: alignment of the region base address; if 0, the default alignment
+ *         (getpagesize()) will be used.
+ * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
+ *             RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
+ *             RAM_READONLY_FD, RAM_GUEST_MEMFD
+ * @path: the path in which to allocate the RAM.
+ * @offset: offset within the file referenced by path
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Note that this function does not do anything to cause the data in the
+ * RAM memory region to be migrated; that is the responsibility of the caller.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_ram_from_file(Object *owner,
+                                              const char *name,
+                                              uint64_t size,
+                                              uint64_t align,
+                                              uint32_t ram_flags,
+                                              const char *path,
+                                              ram_addr_t offset,
+                                              Error **errp);
+
+/**
+ * memory_region_new_ram_from_fd:  Allocate and initialize RAM memory region
+ *                                 with a mmap-ed backend.
+ *
+ * This is like memory_region_init_ram_from_fd() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: the name of the region.
+ * @size: size of the region.
+ * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
+ *             RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
+ *             RAM_READONLY_FD, RAM_GUEST_MEMFD
+ * @fd: the fd to mmap.
+ * @offset: offset within the file referenced by fd
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Note that this function does not do anything to cause the data in the
+ * RAM memory region to be migrated; that is the responsibility of the caller.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_ram_from_fd(Object *owner,
+                                            const char *name, uint64_t size,
+                                            uint32_t ram_flags, int fd,
+                                            ram_addr_t offset, Error **errp);
+
+/**
+ * memory_region_new_ram_ptr:  Allocate and initialize RAM memory region from a
+ *                             user-provided pointer.
+ *
+ * This is like memory_region_init_ram_ptr() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: size of the region.
+ * @ptr: memory to be mapped; must contain at least @size bytes.
+ *
+ * Note that this function does not do anything to cause the data in the
+ * RAM memory region to be migrated; that is the responsibility of the caller.
+ *
+ * Return: Pointer to the allocated #MemoryRegion
+ */
+MemoryRegion *memory_region_new_ram_ptr(Object *owner, const char *name,
+                                        uint64_t size, void *ptr);
+
+/**
+ * memory_region_new_ram_device_ptr:  Allocate and initialize RAM device memory
+ *                                    region from a user-provided pointer.
+ *
+ * This is like memory_region_init_ram_device_ptr() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: the name of the region.
+ * @size: size of the region.
+ * @ptr: memory to be mapped; must contain at least @size bytes.
+ *
+ * Note that this function does not do anything to cause the data in the
+ * RAM memory region to be migrated; that is the responsibility of the caller.
+ * (For RAM device memory regions, migrating the contents rarely makes sense.)
+ *
+ * Return: Pointer to the allocated #MemoryRegion
+ */
+MemoryRegion *memory_region_new_ram_device_ptr(Object *owner, const char *name,
+                                               uint64_t size, void *ptr);
+
+/**
+ * memory_region_new_alias:  Allocate and initialize a memory region that
+ *                           aliases all or a part of another memory region.
+ *
+ * This is like memory_region_init_alias() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: used for debugging; not visible to the user or ABI
+ * @orig: the region to be referenced; @mr will be equivalent to
+ *        @orig between @offset and @offset + @size - 1.
+ * @offset: start of the section in @orig to be referenced.
+ * @size: size of the region.
+ *
+ * Return: Pointer to the allocated #MemoryRegion
+ */
+MemoryRegion *memory_region_new_alias(Object *owner,
+                                      const char *name, MemoryRegion *orig,
+                                      hwaddr offset, uint64_t size);
+
+/**
+ * memory_region_new_rom_nomigrate:  Allocate and initialize a ROM memory
+ *                                   region.
+ *
+ * This is like memory_region_init_rom_nomigrate() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: size of the region.
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_rom_nomigrate(Object *owner,
+                                              const char *name, uint64_t size,
+                                              Error **errp);
+
+/**
+ * memory_region_new_rom_device_nomigrate:  Allocate and initialize a ROM
+ *                                          device memory region.
+ *
+ * This is like memory_region_init_rom_device_nomigrate() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @ops: callbacks for write access handling (must not be NULL).
+ * @opaque: passed to the read and write callbacks of the @ops structure.
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: size of the region.
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Note that this function does not do anything to cause the data in the
+ * RAM side of the memory region to be migrated; that is the responsibility
+ * of the caller.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_rom_device_nomigrate(Object *owner,
+                                                     const MemoryRegionOps *ops,
+                                                     void *opaque,
+                                                     const char *name,
+                                                     uint64_t size,
+                                                     Error **errp);
+/**
+ * memory_region_new_ram - Allocate and initialize RAM memory region.
+ *
+ * This is like memory_region_init_ram() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * @owner: the object that tracks the region's reference count (must be
+ *         TYPE_DEVICE or a subclass of TYPE_DEVICE, or NULL)
+ * @name: name of the memory region
+ * @size: size of the region in bytes
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * TODO: Currently we restrict @owner to being either NULL (for
+ * global RAM regions with no owner) or devices, so that we can
+ * give the RAM block a unique name for migration purposes.
+ * We should lift this restriction and allow arbitrary Objects.
+ * If you pass a non-NULL non-device @owner then we will assert.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_ram(Object *owner,
+                                    const char *name, uint64_t size,
+                                    Error **errp);
+
+MemoryRegion *memory_region_new_ram_guest_memfd(Object *owner,
+                                                const char *name,
+                                                uint64_t size,
+                                                Error **errp);
+
+/**
+ * memory_region_new_rom: Allocate and initialize a ROM memory region.
+ *
+ * This is like memory_region_init_rom() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * TODO: Currently we restrict @owner to being either NULL (for
+ * global RAM regions with no owner) or devices, so that we can
+ * give the RAM block a unique name for migration purposes.
+ * We should lift this restriction and allow arbitrary Objects.
+ * If you pass a non-NULL non-device @owner then we will assert.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: size of the region.
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_rom(Object *owner,
+                                    const char *name, uint64_t size,
+                                    Error **errp);
+
+/**
+ * memory_region_new_rom_device:  Allocate and initialize a ROM device memory
+ *                                region.
+ *
+ * This is like memory_region_init_rom_device() but allocates the
+ * #MemoryRegion and attaches is to the owner to free when the owner is freed.
+ *
+ * TODO: Currently we restrict @owner to being either NULL (for
+ * global RAM regions with no owner) or devices, so that we can
+ * give the RAM block a unique name for migration purposes.
+ * We should lift this restriction and allow arbitrary Objects.
+ * If you pass a non-NULL non-device @owner then we will assert.
+ *
+ * @owner: the object that tracks the region's reference count
+ * @ops: callbacks for write access handling (must not be NULL).
+ * @opaque: passed to the read and write callbacks of the @ops structure.
+ * @name: Region name, becomes part of RAMBlock name used in migration stream
+ *        must be unique within any device
+ * @size: size of the region.
+ * @errp: pointer to Error*, to store an error if it happens.
+ *
+ * Return: Pointer to the allocated #MemoryRegion or NULL on error.
+ */
+MemoryRegion *memory_region_new_rom_device(Object *owner,
+                                           const MemoryRegionOps *ops,
+                                           void *opaque,
+                                           const char *name, uint64_t size,
+                                           Error **errp);
 
 /**
  * memory_region_owner: get a memory region's owner.
diff --git a/system/memory.c b/system/memory.c
index 74244be130..c5fe65db03 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1251,6 +1251,15 @@ void memory_region_init(MemoryRegion *mr,
     memory_region_do_init(mr, owner, name, size);
 }
 
+MemoryRegion *memory_region_new(Object *owner, const char *name, uint64_t size)
+{
+    MemoryRegion *mr = MEMORY_REGION(object_new(TYPE_MEMORY_REGION));
+
+    assert(name); /* mr is attached to owner by name */
+    memory_region_do_init(mr, owner, name, size);
+    return mr;
+}
+
 static void memory_region_get_container(Object *obj, Visitor *v,
                                         const char *name, void *opaque,
                                         Error **errp)
@@ -1576,6 +1585,16 @@ void memory_region_init_io(MemoryRegion *mr, Object *owner,
     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)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+
+    memory_region_set_ops(mr, ops, opaque);
+    return mr;
+}
+
 static bool memory_region_do_init_ram(MemoryRegion *mr,
                                       Error *err, Error **errp)
 {
@@ -1610,6 +1629,26 @@ bool memory_region_init_ram_nomigrate(MemoryRegion *mr, Object *owner,
                                                   errp);
 }
 
+MemoryRegion *memory_region_new_ram_flags_nomigrate(Object *owner,
+                                                    const char *name,
+                                                    uint64_t size,
+                                                    uint32_t ram_flags,
+                                                    Error **errp)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+    Error *err = NULL;
+
+    mr->ram_block = qemu_ram_alloc(size, ram_flags, mr, &err);
+    return memory_region_do_init_ram(mr, err, errp) ? mr : NULL;
+}
+
+MemoryRegion *memory_region_new_ram_nomigrate(Object *owner,
+                                              const char *name, uint64_t size,
+                                              Error **errp)
+{
+    return memory_region_new_ram_flags_nomigrate(owner, name, size, 0, errp);
+}
+
 bool memory_region_init_resizeable_ram(MemoryRegion *mr,
                                        Object *owner,
                                        const char *name,
@@ -1628,6 +1667,23 @@ bool memory_region_init_resizeable_ram(MemoryRegion *mr,
     return memory_region_do_init_ram(mr, err, errp);
 }
 
+MemoryRegion *memory_region_new_resizeable_ram(Object *owner,
+                                               const char *name,
+                                               uint64_t size,
+                                               uint64_t max_size,
+                                               void (*resized)(const char*,
+                                                               uint64_t length,
+                                                               void *host),
+                                               Error **errp)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+    Error *err = NULL;
+
+    mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, mr,
+                                              &err);
+    return memory_region_do_init_ram(mr, err, errp) ? mr : NULL;
+}
+
 #if defined(CONFIG_POSIX) && !defined(EMSCRIPTEN)
 bool memory_region_init_ram_from_file(MemoryRegion *mr, Object *owner,
                                       const char *name, uint64_t size,
@@ -1645,6 +1701,25 @@ bool memory_region_init_ram_from_file(MemoryRegion *mr, Object *owner,
     return memory_region_do_init_ram(mr, err, errp);
 }
 
+MemoryRegion *memory_region_new_ram_from_file(Object *owner,
+                                              const char *name,
+                                              uint64_t size,
+                                              uint64_t align,
+                                              uint32_t ram_flags,
+                                              const char *path,
+                                              ram_addr_t offset,
+                                              Error **errp)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+    Error *err = NULL;
+
+    mr->readonly = !!(ram_flags & RAM_READONLY);
+    mr->align = align;
+    mr->ram_block = qemu_ram_alloc_from_file(size, mr, ram_flags, path, offset,
+                                             &err);
+    return memory_region_do_init_ram(mr, err, errp) ? mr : NULL;
+}
+
 bool memory_region_init_ram_from_fd(MemoryRegion *mr, Object *owner,
                                     const char *name, uint64_t size,
                                     uint32_t ram_flags, int fd,
@@ -1658,6 +1733,20 @@ bool memory_region_init_ram_from_fd(MemoryRegion *mr, Object *owner,
                                            offset, false, &err);
     return memory_region_do_init_ram(mr, err, errp);
 }
+
+MemoryRegion *memory_region_new_ram_from_fd(Object *owner,
+                                            const char *name, uint64_t size,
+                                            uint32_t ram_flags, int fd,
+                                            ram_addr_t offset, Error **errp)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+    Error *err = NULL;
+
+    mr->readonly = !!(ram_flags & RAM_READONLY);
+    mr->ram_block = qemu_ram_alloc_from_fd(size, size, NULL, mr, ram_flags, fd,
+                                           offset, false, &err);
+    return memory_region_do_init_ram(mr, err, errp) ? mr : NULL;
+}
 #endif
 
 static void memory_region_do_init_ram_ptr(MemoryRegion *mr, uint64_t size,
@@ -1676,6 +1765,15 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, Object *owner,
     memory_region_do_init_ram_ptr(mr, size, ptr);
 }
 
+MemoryRegion *memory_region_new_ram_ptr(Object *owner, const char *name,
+                                        uint64_t size, void *ptr)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+
+    memory_region_do_init_ram_ptr(mr, size, ptr);
+    return mr;
+}
+
 void memory_region_init_ram_device_ptr(MemoryRegion *mr, Object *owner,
                                        const char *name, uint64_t size,
                                        void *ptr)
@@ -1686,6 +1784,17 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, Object *owner,
     mr->ram_device = true;
 }
 
+MemoryRegion *memory_region_new_ram_device_ptr(Object *owner, const char *name,
+                                               uint64_t size, void *ptr)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+
+    memory_region_set_ops(mr, &ram_device_mem_ops, mr);
+    memory_region_do_init_ram_ptr(mr, size, ptr);
+    mr->ram_device = true;
+    return mr;
+}
+
 void memory_region_init_alias(MemoryRegion *mr, Object *owner,
                               const char *name, MemoryRegion *orig,
                               hwaddr offset, uint64_t size)
@@ -1695,6 +1804,17 @@ void memory_region_init_alias(MemoryRegion *mr, Object *owner,
     mr->alias_offset = offset;
 }
 
+MemoryRegion *memory_region_new_alias(Object *owner,
+                                      const char *name, MemoryRegion *orig,
+                                      hwaddr offset, uint64_t size)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+
+    mr->alias = orig;
+    mr->alias_offset = offset;
+    return mr;
+}
+
 bool memory_region_init_rom_nomigrate(MemoryRegion *mr, Object *owner,
                                       const char *name, uint64_t size,
                                       Error **errp)
@@ -1706,6 +1826,20 @@ bool memory_region_init_rom_nomigrate(MemoryRegion *mr, Object *owner,
     return true;
 }
 
+MemoryRegion *memory_region_new_rom_nomigrate(Object *owner,
+                                              const char *name, uint64_t size,
+                                              Error **errp)
+{
+    MemoryRegion *mr;
+
+    mr = memory_region_new_ram_nomigrate(owner, name, size, errp);
+    if (!mr) {
+        return NULL;
+    }
+    mr->readonly = true;
+    return mr;
+}
+
 bool memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
                                              Object *owner,
                                              const MemoryRegionOps *ops,
@@ -1729,6 +1863,27 @@ bool memory_region_init_rom_device_nomigrate(MemoryRegion *mr,
     return ret;
 }
 
+MemoryRegion *memory_region_new_rom_device_nomigrate(Object *owner,
+                                                     const MemoryRegionOps *ops,
+                                                     void *opaque,
+                                                     const char *name,
+                                                     uint64_t size,
+                                                     Error **errp)
+{
+    MemoryRegion *mr = memory_region_new(owner, name, size);
+    Error *err = NULL;
+
+    assert(ops);
+    memory_region_set_ops(mr, ops, opaque);
+    mr->ram_block = qemu_ram_alloc(size, 0, mr, &err);
+    if (memory_region_do_init_ram(mr, err, errp)) {
+        mr->ram = false;
+        mr->rom_device = true;
+        return mr;
+    }
+    return NULL;
+}
+
 void memory_region_init_iommu(void *_iommu_mr,
                               size_t instance_size,
                               const char *mrtypename,
@@ -3703,6 +3858,19 @@ bool memory_region_init_ram(MemoryRegion *mr, Object *owner,
     return true;
 }
 
+MemoryRegion *memory_region_new_ram(Object *owner,
+                                    const char *name, uint64_t size,
+                                    Error **errp)
+{
+    MemoryRegion *mr;
+
+    mr = memory_region_new_ram_nomigrate(owner, name, size, errp);
+    if (mr) {
+        memory_region_register_ram(mr, owner);
+    }
+    return mr;
+}
+
 bool memory_region_init_ram_guest_memfd(MemoryRegion *mr, Object *owner,
                                         const char *name, uint64_t size,
                                         Error **errp)
@@ -3715,6 +3883,21 @@ bool memory_region_init_ram_guest_memfd(MemoryRegion *mr, Object *owner,
     return true;
 }
 
+MemoryRegion *memory_region_new_ram_guest_memfd(Object *owner,
+                                                const char *name,
+                                                uint64_t size,
+                                                Error **errp)
+{
+    MemoryRegion *mr;
+
+    mr = memory_region_new_ram_flags_nomigrate(owner, name, size,
+                                               RAM_GUEST_MEMFD, errp);
+    if (mr) {
+        memory_region_register_ram(mr, owner);
+    }
+    return mr;
+}
+
 bool memory_region_init_rom(MemoryRegion *mr, Object *owner,
                             const char *name, uint64_t size,
                             Error **errp)
@@ -3726,6 +3909,19 @@ bool memory_region_init_rom(MemoryRegion *mr, Object *owner,
     return true;
 }
 
+MemoryRegion *memory_region_new_rom(Object *owner,
+                                    const char *name, uint64_t size,
+                                    Error **errp)
+{
+    MemoryRegion *mr;
+
+    mr = memory_region_new_rom_nomigrate(owner, name, size, errp);
+    if (mr) {
+        memory_region_register_ram(mr, owner);
+    }
+    return mr;
+}
+
 bool memory_region_init_rom_device(MemoryRegion *mr, Object *owner,
                                    const MemoryRegionOps *ops, void *opaque,
                                    const char *name, uint64_t size,
@@ -3739,6 +3935,22 @@ bool memory_region_init_rom_device(MemoryRegion *mr, Object *owner,
     return true;
 }
 
+MemoryRegion *memory_region_new_rom_device(Object *owner,
+                                           const MemoryRegionOps *ops,
+                                           void *opaque,
+                                           const char *name, uint64_t size,
+                                           Error **errp)
+{
+    MemoryRegion *mr;
+
+    mr = memory_region_new_rom_device_nomigrate(owner, ops, opaque, name, size,
+                                                errp);
+    if (mr) {
+        memory_region_register_ram(mr, owner);
+    }
+    return mr;
+}
+
 /*
  * Support system builds with CONFIG_FUZZ using a weak symbol and a stub for
  * the fuzz_dma_read_cb callback
-- 
2.41.3



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/6] Implement memory_region_new_* functions
  2025-12-23 21:49 [PATCH 0/6] Implement memory_region_new_* functions BALATON Zoltan
                   ` (5 preceding siblings ...)
  2025-12-23 21:50 ` [PATCH 6/6] memory: Add memory_region_new* functions BALATON Zoltan
@ 2025-12-24  5:21 ` Akihiko Odaki
  2025-12-24 13:47   ` BALATON Zoltan
  6 siblings, 1 reply; 15+ messages in thread
From: Akihiko Odaki @ 2025-12-24  5:21 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Peter Xu, Paolo Bonzini, Michael S. Tsirkin, philmd

On 2025/12/24 6:49, BALATON Zoltan wrote:
> Our documentation says that memory regions are automatically freed
> when the owner dies and the reference counting to do this is also
> implemented. However this relies on the QOM free funtion that can only
> be set by creating objects with object_new but memory API only
> provides constructors that call object_initialize which clears the
> free function that prevents QOM to manage the memory region lifetime.
> Implement corresponding memory_region_new_* functions that do the same
> as the memory_region_init_* functions but create the memory region
> with object_new so the lifetime can be automatically managed by QOM as
> documented.

The documentation explains the existing functions so the discrepancy 
between them you see should be fixed by updating them, not adding new ones.

Regards,
Akihiko Odaki


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/6] Implement memory_region_new_* functions
  2025-12-24  5:21 ` [PATCH 0/6] Implement memory_region_new_* functions Akihiko Odaki
@ 2025-12-24 13:47   ` BALATON Zoltan
  2025-12-24 15:36     ` Peter Xu
  2025-12-25  5:22     ` Akihiko Odaki
  0 siblings, 2 replies; 15+ messages in thread
From: BALATON Zoltan @ 2025-12-24 13:47 UTC (permalink / raw)
  To: Akihiko Odaki
  Cc: qemu-devel, Peter Xu, Paolo Bonzini, Michael S. Tsirkin, philmd

On Wed, 24 Dec 2025, Akihiko Odaki wrote:
> On 2025/12/24 6:49, BALATON Zoltan wrote:
>> Our documentation says that memory regions are automatically freed
>> when the owner dies and the reference counting to do this is also
>> implemented. However this relies on the QOM free funtion that can only
>> be set by creating objects with object_new but memory API only
>> provides constructors that call object_initialize which clears the
>> free function that prevents QOM to manage the memory region lifetime.
>> Implement corresponding memory_region_new_* functions that do the same
>> as the memory_region_init_* functions but create the memory region
>> with object_new so the lifetime can be automatically managed by QOM as
>> documented.
>
> The documentation explains the existing functions so the discrepancy between 
> them you see should be fixed by updating them, not adding new ones.

Do you mean replacing memory_region_init_* with these memory_region_new_* 
functions? The memory_region_init_* is still useful for embedded memory 
regions that are managed by some other way which is also mentioned in the 
documentation as an alternative so I think both of them are useful for 
different cases. If you mean we need to update docs to refer to 
memory_region_new instead of memory_region_init at some places then I 
think you're right, the docs may also need to be updated or clarified.

Regards,
BALATON Zoltan


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/6] memory: Factor out common ram region initialization
  2025-12-23 21:49 ` [PATCH 2/6] memory: Factor out common ram region initialization BALATON Zoltan
@ 2025-12-24 15:33   ` Peter Xu
  2026-01-25 20:19     ` BALATON Zoltan
  0 siblings, 1 reply; 15+ messages in thread
From: Peter Xu @ 2025-12-24 15:33 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

On Tue, Dec 23, 2025 at 10:49:58PM +0100, BALATON Zoltan wrote:
> -bool memory_region_init_ram_nomigrate(MemoryRegion *mr,
> -                                      Object *owner,
> -                                      const char *name,
> -                                      uint64_t size,
> -                                      Error **errp)
> -{
> -    return memory_region_init_ram_flags_nomigrate(mr, owner, name,
> -                                                  size, 0, errp);
> -}
> -
> -bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
> -                                            Object *owner,
> -                                            const char *name,
> -                                            uint64_t size,
> -                                            uint32_t ram_flags,
> -                                            Error **errp)
> +static bool memory_region_do_init_ram(MemoryRegion *mr,
> +                                      Error *err, Error **errp)
>  {
> -    Error *err = NULL;
> -    memory_region_init(mr, owner, name, size);
>      mr->ram = true;
>      mr->terminates = true;
>      mr->destructor = memory_region_destructor_ram;
> -    mr->ram_block = qemu_ram_alloc(size, ram_flags, mr, &err);

If this is moved out, the err below will never be set.  Maybe this helper
then doesn't need errp at all.

>      if (err) {
>          mr->size = int128_zero();
>          object_unparent(OBJECT(mr));
> @@ -1611,6 +1594,25 @@ bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
>      return true;
>  }

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/6] Implement memory_region_new_* functions
  2025-12-24 13:47   ` BALATON Zoltan
@ 2025-12-24 15:36     ` Peter Xu
  2025-12-25  5:22     ` Akihiko Odaki
  1 sibling, 0 replies; 15+ messages in thread
From: Peter Xu @ 2025-12-24 15:36 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: Akihiko Odaki, qemu-devel, Paolo Bonzini, Michael S. Tsirkin,
	philmd

On Wed, Dec 24, 2025 at 02:47:20PM +0100, BALATON Zoltan wrote:
> On Wed, 24 Dec 2025, Akihiko Odaki wrote:
> > On 2025/12/24 6:49, BALATON Zoltan wrote:
> > > Our documentation says that memory regions are automatically freed
> > > when the owner dies and the reference counting to do this is also
> > > implemented. However this relies on the QOM free funtion that can only
> > > be set by creating objects with object_new but memory API only
> > > provides constructors that call object_initialize which clears the
> > > free function that prevents QOM to manage the memory region lifetime.
> > > Implement corresponding memory_region_new_* functions that do the same
> > > as the memory_region_init_* functions but create the memory region
> > > with object_new so the lifetime can be automatically managed by QOM as
> > > documented.
> > 
> > The documentation explains the existing functions so the discrepancy
> > between them you see should be fixed by updating them, not adding new
> > ones.
> 
> Do you mean replacing memory_region_init_* with these memory_region_new_*
> functions? The memory_region_init_* is still useful for embedded memory
> regions that are managed by some other way which is also mentioned in the
> documentation as an alternative so I think both of them are useful for
> different cases. If you mean we need to update docs to refer to
> memory_region_new instead of memory_region_init at some places then I think
> you're right, the docs may also need to be updated or clarified.

To me, it's less convincing to add new APIs without a solid user.

IMHO we can go either (1) leave patch 6 for later, making this series a
cleanup first, or, (2) add users for every new functions introduced, so at
least we know why each of the new functions are introduced and necessary.

Thanks,

-- 
Peter Xu



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 0/6] Implement memory_region_new_* functions
  2025-12-24 13:47   ` BALATON Zoltan
  2025-12-24 15:36     ` Peter Xu
@ 2025-12-25  5:22     ` Akihiko Odaki
  1 sibling, 0 replies; 15+ messages in thread
From: Akihiko Odaki @ 2025-12-25  5:22 UTC (permalink / raw)
  To: BALATON Zoltan
  Cc: qemu-devel, Peter Xu, Paolo Bonzini, Michael S. Tsirkin, philmd

On 2025/12/24 22:47, BALATON Zoltan wrote:
> On Wed, 24 Dec 2025, Akihiko Odaki wrote:
>> On 2025/12/24 6:49, BALATON Zoltan wrote:
>>> Our documentation says that memory regions are automatically freed
>>> when the owner dies and the reference counting to do this is also
>>> implemented. However this relies on the QOM free funtion that can only
>>> be set by creating objects with object_new but memory API only
>>> provides constructors that call object_initialize which clears the
>>> free function that prevents QOM to manage the memory region lifetime.
>>> Implement corresponding memory_region_new_* functions that do the same
>>> as the memory_region_init_* functions but create the memory region
>>> with object_new so the lifetime can be automatically managed by QOM as
>>> documented.
>>
>> The documentation explains the existing functions so the discrepancy 
>> between them you see should be fixed by updating them, not adding new 
>> ones.
> 
> Do you mean replacing memory_region_init_* with these 
> memory_region_new_* functions? The memory_region_init_* is still useful 
> for embedded memory regions that are managed by some other way which is 
> also mentioned in the documentation as an alternative so I think both of 
> them are useful for different cases. If you mean we need to update docs 
> to refer to memory_region_new instead of memory_region_init at some 
> places then I think you're right, the docs may also need to be updated 
> or clarified.

I'd like to see a correspondence between the stated problem and the 
solution. If the intention is to solve the mismatched documentation and 
implementation, I think there are only two possible options:

1) Update the documentation and/or the implementation.
2) Delete them.

But this patch series does neither of them. Replacing 
memory_region_init_* with memory_region_new_* does solve as it will do 
2) in the process. An alternative solution that implements 1) or 2) is 
necessary if it's not ideal.

Regards,
Akihiko Odaki


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/6] memory: Factor out more common ram region initialization
  2025-12-23 21:49 ` [PATCH 3/6] memory: Factor out more " BALATON Zoltan
@ 2025-12-26 11:31   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 15+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-12-26 11:31 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin

On 23/12/25 22:49, BALATON Zoltan wrote:
> Introduce internal memory_region_do_init_ram_ptr() function to remove
> duplicated code from different memory_region_init_ram_*ptr functions.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>   system/memory.c | 17 ++++++++++-------
>   1 file changed, 10 insertions(+), 7 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 5/6] memory: Add internal memory_region_register_ram function
  2025-12-23 21:50 ` [PATCH 5/6] memory: Add internal memory_region_register_ram function BALATON Zoltan
@ 2025-12-26 11:32   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 15+ messages in thread
From: Philippe Mathieu-Daudé @ 2025-12-26 11:32 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel
  Cc: Peter Xu, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin

On 23/12/25 22:50, BALATON Zoltan wrote:
> Factor out common operation from memory_region_init_{ram,rom}
> functions to register the region for migration. This avoids
> duplicating the long comment in several functions.
> 
> Signed-off-by: BALATON Zoltan <balaton@eik.bme.hu>
> ---
>   system/memory.c | 75 +++++++++++++------------------------------------
>   1 file changed, 20 insertions(+), 55 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/6] memory: Factor out common ram region initialization
  2025-12-24 15:33   ` Peter Xu
@ 2026-01-25 20:19     ` BALATON Zoltan
  0 siblings, 0 replies; 15+ messages in thread
From: BALATON Zoltan @ 2026-01-25 20:19 UTC (permalink / raw)
  To: Peter Xu
  Cc: qemu-devel, Akihiko Odaki, Paolo Bonzini, Michael S. Tsirkin,
	philmd

On Wed, 24 Dec 2025, Peter Xu wrote:
> On Tue, Dec 23, 2025 at 10:49:58PM +0100, BALATON Zoltan wrote:
>> -bool memory_region_init_ram_nomigrate(MemoryRegion *mr,
>> -                                      Object *owner,
>> -                                      const char *name,
>> -                                      uint64_t size,
>> -                                      Error **errp)
>> -{
>> -    return memory_region_init_ram_flags_nomigrate(mr, owner, name,
>> -                                                  size, 0, errp);
>> -}
>> -
>> -bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
>> -                                            Object *owner,
>> -                                            const char *name,
>> -                                            uint64_t size,
>> -                                            uint32_t ram_flags,
>> -                                            Error **errp)
>> +static bool memory_region_do_init_ram(MemoryRegion *mr,
>> +                                      Error *err, Error **errp)
>>  {
>> -    Error *err = NULL;
>> -    memory_region_init(mr, owner, name, size);
>>      mr->ram = true;
>>      mr->terminates = true;
>>      mr->destructor = memory_region_destructor_ram;
>> -    mr->ram_block = qemu_ram_alloc(size, ram_flags, mr, &err);
>
> If this is moved out, the err below will never be set.  Maybe this helper
> then doesn't need errp at all.

err is an input parameter to this function as it consolidates common error 
handling so it does not have to be repeated at every caller.

Regards,
BALATON Zoltan

>>      if (err) {
>>          mr->size = int128_zero();
>>          object_unparent(OBJECT(mr));
>> @@ -1611,6 +1594,25 @@ bool memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
>>      return true;
>>  }
>
>


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2026-01-25 20:20 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-23 21:49 [PATCH 0/6] Implement memory_region_new_* functions BALATON Zoltan
2025-12-23 21:49 ` [PATCH 1/6] memory: Add internal memory_region_set_ops helper function BALATON Zoltan
2025-12-23 21:49 ` [PATCH 2/6] memory: Factor out common ram region initialization BALATON Zoltan
2025-12-24 15:33   ` Peter Xu
2026-01-25 20:19     ` BALATON Zoltan
2025-12-23 21:49 ` [PATCH 3/6] memory: Factor out more " BALATON Zoltan
2025-12-26 11:31   ` Philippe Mathieu-Daudé
2025-12-23 21:50 ` [PATCH 4/6] memory: Shorten memory_region_init_rom_nomigrate BALATON Zoltan
2025-12-23 21:50 ` [PATCH 5/6] memory: Add internal memory_region_register_ram function BALATON Zoltan
2025-12-26 11:32   ` Philippe Mathieu-Daudé
2025-12-23 21:50 ` [PATCH 6/6] memory: Add memory_region_new* functions BALATON Zoltan
2025-12-24  5:21 ` [PATCH 0/6] Implement memory_region_new_* functions Akihiko Odaki
2025-12-24 13:47   ` BALATON Zoltan
2025-12-24 15:36     ` Peter Xu
2025-12-25  5:22     ` Akihiko Odaki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.