mirror of
https://github.com/yuzu-emu/unicorn
synced 2024-11-24 13:48:14 +00:00
docs: clarify memory region lifecycle
Now that objects actually obey the rules, document them. Backports commit 8b5c216025c312ab01542c4595393e0fdcbed015 from qemu
This commit is contained in:
parent
3fbda890df
commit
2348a02a8d
1 changed files with 57 additions and 9 deletions
|
@ -73,17 +73,65 @@ stability.
|
||||||
Region lifecycle
|
Region lifecycle
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
A region is created by one of the constructor functions (memory_region_init*())
|
A region is created by one of the memory_region_init*() functions and
|
||||||
and attached to an object. It is then destroyed by object_unparent() or simply
|
attached to an object, which acts as its owner or parent. QEMU ensures
|
||||||
when the parent object dies.
|
that the owner object remains alive as long as the region is visible to
|
||||||
|
the guest, or as long as the region is in use by a virtual CPU or another
|
||||||
|
device. For example, the owner object will not die between an
|
||||||
|
address_space_map operation and the corresponding address_space_unmap.
|
||||||
|
|
||||||
In between, a region can be added to an address space
|
After creation, a region can be added to an address space or a
|
||||||
by using memory_region_add_subregion() and removed using
|
container with memory_region_add_subregion(), and removed using
|
||||||
memory_region_del_subregion(). Destroying the region implicitly
|
memory_region_del_subregion().
|
||||||
removes the region from the address space.
|
|
||||||
|
|
||||||
Region attributes may be changed at any point; they take effect once
|
Various region attributes (read-only, dirty logging, coalesced mmio,
|
||||||
the region becomes exposed to the guest.
|
ioeventfd) can be changed during the region lifecycle. They take effect
|
||||||
|
as soon as the region is made visible. This can be immediately, later,
|
||||||
|
or never.
|
||||||
|
|
||||||
|
Destruction of a memory region happens automatically when the owner
|
||||||
|
object dies.
|
||||||
|
|
||||||
|
If however the memory region is part of a dynamically allocated data
|
||||||
|
structure, you should call object_unparent() to destroy the memory region
|
||||||
|
before the data structure is freed. For an example see VFIOMSIXInfo
|
||||||
|
and VFIOQuirk in hw/vfio/pci.c.
|
||||||
|
|
||||||
|
You must not destroy a memory region as long as it may be in use by a
|
||||||
|
device or CPU. In order to do this, as a general rule do not create or
|
||||||
|
destroy memory regions dynamically during a device's lifetime, and only
|
||||||
|
call object_unparent() in the memory region owner's instance_finalize
|
||||||
|
callback. The dynamically allocated data structure that contains the
|
||||||
|
memory region then should obviously be freed in the instance_finalize
|
||||||
|
callback as well.
|
||||||
|
|
||||||
|
If you break this rule, the following situation can happen:
|
||||||
|
|
||||||
|
- the memory region's owner had a reference taken via memory_region_ref
|
||||||
|
(for example by address_space_map)
|
||||||
|
|
||||||
|
- the region is unparented, and has no owner anymore
|
||||||
|
|
||||||
|
- when address_space_unmap is called, the reference to the memory region's
|
||||||
|
owner is leaked.
|
||||||
|
|
||||||
|
|
||||||
|
There is an exception to the above rule: it is okay to call
|
||||||
|
object_unparent at any time for an alias or a container region. It is
|
||||||
|
therefore also okay to create or destroy alias and container regions
|
||||||
|
dynamically during a device's lifetime.
|
||||||
|
|
||||||
|
This exceptional usage is valid because aliases and containers only help
|
||||||
|
QEMU building the guest's memory map; they are never accessed directly.
|
||||||
|
memory_region_ref and memory_region_unref are never called on aliases
|
||||||
|
or containers, and the above situation then cannot happen. Exploiting
|
||||||
|
this exception is rarely necessary, and therefore it is discouraged,
|
||||||
|
but nevertheless it is used in a few places.
|
||||||
|
|
||||||
|
For regions that "have no owner" (NULL is passed at creation time), the
|
||||||
|
machine object is actually used as the owner. Since instance_finalize is
|
||||||
|
never called for the machine object, you must never call object_unparent
|
||||||
|
on regions that have no owner, unless they are aliases or containers.
|
||||||
|
|
||||||
Overlapping regions and priority
|
Overlapping regions and priority
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
Loading…
Reference in a new issue