On Wed, 17 Jun 2026, Paolo Bonzini wrote:
On 6/16/26 17:55, Daniel P. Berrangé wrote:
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]>
Zoltan already proposed this, but I really think it's a bad idea.
MemoryRegionOps callback will certainly access fields in the parent. Having a
separate object gives you no benefit because you still have the same
use-after-free if the MemoryRegion outlives the device. Likewise for buses.
For buses, the fact that the parent and child live at the same time is
explicitly tracked with mutual refcount and unparent. If it's not, we have
the hack that Akihiko mentioned
(https://lists.gnu.org/archive/html/qemu-devel/2026-06/msg03459.html):
However, this is insufficient to avoid calling object_ref() for all
embedded objects. For example, consider an embedded Device that has a
MemoryRegion. When referencing a MemoryRegion for guest memory access,
QEMU automatically references the owning Device to keep the MemoryRegion
alive. However, that reference is ineffective if the Device itself is
embedded, because object_ref() does not keep the containing storage
alive.
If the device itself is embedded, then all the invariants must hold
recursively:
- the device must be kept alive by mutual references between the device
itself and its parent;
- unparent for the device should wait for all guest memory accesses to be
either completed or cancelled.
So, the problem is that "QEMU automatically references the owning Device to
keep the MemoryRegion alive" is a hack that should die. I added it, mea
culpa.
The model is that if it makes sense to have B outlive A, you use new. If it
doesn't, you use init. For MemoryRegions or anything that has callbacks, it
makes no sense to outlive the implementor of the callbacks. There are
exceptions if the number of objects is dynamic but they're very rare.
I agree that there's extra complexity added by embedding; but I disagree that
removing embedding will fix any bugs, and because it will hide a relationship
between objects, I believe the complexity is not accidental.
The problem is that memory regions cannot be ref counted because they are
piggybacking on their owner's ref count instead of using their own. So
while memory regions are QOM objects and the code is there to ref count
and free them with their owners this can't be used and we hack around that
by referencing the owner instead. If there's a dependency on the parent
then maybe the memory region should take a ref of the parent so it does
not go away until the memory region is freed or the owner relation needs
to be taken into account instead of using the parent ref count and
forbidding to make memory regions proper QOM objects which is very
confusing and leads to all sorts of other hacks.
And it also forces me to embed a bunch of memory regions in device states
that are otherwise not needed and already stored as PCI BARs or sysbus
regions so I should not need them in my device state. This added
complexity was my motivation but it turned out to be a larger issue and I
think restoring the ability to ref count memory regions and clean up the
hacks of keeping the parent alive with every object using its own ref
counts would be cleaner than keeping to the current way.
Regards,
BALATON Zoltan