On Tue, 27 Jan 2026, Peter Maydell wrote:
On Sun, 25 Jan 2026 at 18:36, BALATON Zoltan <[email protected]> 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 memory_region_init functions are kept because they are
useful for memory regions embedded in other object or managed
externally and not by QOM for some reason.

If we have a problem with embedded MemoryRegions being leaked,
we need to fix that.

I have a problem with embedded memory regions (and embedded objects in general) because:

- they are making state structs unnecessarily crowded obscuring what should really be there - leaving the fields to store these memory regions in the parent classes and the QOM way of lifetime management unused
- exposes internal object implementation to the outside
which is against encapsulation and reuse of object oriented design.

Therefore, I consider embedded memory regions as a hack to solve leaks because the intended and documented way of using reference counting to manage the lifetime of these regions cannot be used due to missing API to instantiate them in a way so it works. This series tries to resolve that not add new principle or standard.

I'm very reluctant to create a whole new
set of APIs which handles MRs in a non-standard way (i.e.
"QOM object has a pointer to MR rather than embedding it")

But this is the standard and documented way if you read the life cycle section of the memory docs and the embedded regions became more used instead of resolving this problem in the way it was originaly intended. The QOM subclass does not store a pointer to these as it's not needed, they are managed by QOM so they are created and can be forgotten about without littering the state struct with fields never used in the object methods just to manage the memory that QOM could already manage. (The parent sysbus or PCI class keeps a pointer when registering them as regions and Object stores them as a child but that's already there and needed for those classes not the subclass so we can avoid duplicating it in the subclass.)

and leaves the existing ones alone. QEMU already has way too
many situations where we have multiple different APIs that can
be used to do something and incomplete transitions from the
old one to the new one.

This series does not convert everything but opens the way to do that and simplify objects by only storing things in the state that are really needed by the object and let QOM manage what it can. I'd really like to avoid having a list of unused stuff in the state struct just because I can't use something that works and documented just no API to actually use it. Cf. sii3112 state after this series:

struct SiI3112PCIState {
    PCIIDEState i;

    SiI3112Regs regs[2];
};

vs. your standard:

struct SiI3112PCIState {
    PCIIDEState i;

    MemoryRegion mmio;
    MemoryRegion bar0;
    MemoryRegion bar1;
    MemoryRegion bar2;
    MemoryRegion bar3;
    MemoryRegion bar4;
    SiI3112Regs regs[2];
};

First I thought we could use object_new then memory_region_init but it turns out that does not work because memory_region_init calls object_initialize which removes the free function installed by object_new and since there's no other way to set it other than by calling object_new a split init like in macOS (i.e. alloc+init) is also not possible so a new set of memory_region_new functions seem to be the easiest way to use it as intended and avoid changing every user of memory_region_init functions.

As mentioned in the docs and cover letter both set of functions are useful in different situations and they are otherwise the same so it would not make the API much more complex as these are basically variants of one set of functions only differing in dynamically allocating object or initialising pre-allocated object that are not managed by QOM (which is what the embedded objects do: take object out from QOM and let the subclass manage it instead of using the infrastructure that's already there for it). If you go the embedded way then the registering memory regions as children should be removed and everything converted to use embedded regions but I don't think that would be an improvement.

Regards,
BALATON Zoltan

Reply via email to