On Fri, 19 Jun 2026, Paolo Bonzini wrote:
On 6/18/26 00:44, BALATON Zoltan wrote:
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.

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.

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 disagree that removing embedding will fix any bugs

I'm trying to understand this better. The way it originally meant to work according to the memory region docs and implementation is that memory region is added to an owner as a child which takes a reference and when the owner is freed it will unparent its children which will then get unrefed and freed as well if nothing else increased their ref count.

Yes, and that's broken.

Your replies are too brief to understand what you mean so I have to keep guessing. What breakage do you mean? The idea itself is not broken and would work and can be fixed to work as intended. It's just not working currently because memory regions are not allocated in a way that ref counting could free them. That's broken in QEMU currently but the above described way is not fundamentally broken. Or do you mean something else?

The problem is that when something accesses the memory region it has to keep the owner alive as well so instead of referencing the memory region it references the owner (not directly but using memory_region_ref which does this).

A mechanism to keep the owner alive exists, and it is mutual references (so that neither owner nor MR die) + unparent of owner (which should wait for pending users to complete before returning).

The fact that this mechanism is not used, i.e. unparent of a PCIDevice does not wait for pending BAR accesses to complete, is a bug.

I don't know this part but I think ref counting is meant to be the way to track if there are pending accesses. How else would PCI code know if there are pending accesses from other unrelated parts of QEMU? I don't think PCI code could track all accesses itself which may come from a CPU or another device doing DMA. Even after registering as a BAR a memory region is just used as any other memory region so the PCI code does not know what accesses it without some tracking such as ref counts.

I think the current way of passing reference to the owner could work for a chain of owners too. All that would be needed is to add an owner field to QOM object and if that is non-NULL ref/unref is passed to the owner. I.e. just generalising what memory_region_ref/unref does. (Or do this for all prarent/child where children increase their parents' ref when they get a ref, but I'm not sure what exactly parent/child stands for in QOM so a separate owner relation may be needed as parent/child may be for qom-tree or not even well defined.)

So embedding seems unrelated to this passing refs on
memory regions to owner and could be fixed separately that my patches attempted.

Your patches add the possibility of not embedding; I don't like having two separate API, but I think we only have a disagreement on aesthetics.

OK so at least we've arrived at that there's no other problem than aesthetics. It's hard to argue about that but QOM already has two ways.
From https://www.qemu.org/docs/master/devel/qom-api.html#qom-api

object_new:
This function will initialize a new object using heap allocated memory. The returned object has a reference count of 1, and will be freed when the last reference is dropped.

object_initialize:
This function will initialize an object. The memory for the object should have already been allocated. The returned object has a reference count of 1, and will be finalized when the last reference is dropped.

So we should have corresponding API for memory_region too to support both allocated memory regions and ones managed by some other way. Currently the memory region API does not allow QOM managed memory regions so we're causing ourselves problems having to somehow manage the lifetime of these memory regions instead of just relying on the solution QOM already provides for this. Having both APIs would be consistent with QOM and allow to chose the way that fits each case better. I don't want to convert everything to object_new but I want to be able to allocate memory regions that are then managed by QOM so I can avoid the complexity of keeping track and managing them separately when this is already there and would work well for a lot of cases.

This is different for Daniel's patches, which try to fix something by not embedding, and I don't think they do. Currently, if the owner dies, the MemoryRegion dies with it while it shouldn't (which is a problem, absolutely). But these patches, while preventing the MR from dying, still leave around a dangling pointer to the owner from the MR, so there's not much gained if anything.

I'm not sure I understand all the problems but I don't think embedding solves anything other than not leaking memory regions that QOM does not free due to using object_initialize which means you're on your own managing your storage. I think a solution could be passing refs up in a chain of owners as I described above which is unrelated to embedding. This way works for a single owner with memory_region_ref/unref and could work for multiple owners while keeping the memory regions and owners separate objects. I'm not sure what you have in mind but if you say that owners would have to embed their children that alone does not solve that they are still separate objects and have to be finalized separately so we still need ref counting to know how long to keep alive owners when one of the children is accessed. Embedding does not solve that and just unnecessarily ties storage of separte objects together but we still need to fix ref counting and then we can also use that to free objects when no more references are there so we also don't need to embed them but keeping both _new and _init APIs would allow to chose either way whichever fits a given problem.

Regards.
BALATON Zoltan

Reply via email to