mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'mem-staging-pull-request' of https://gitlab.com/peterx/qemu into staging
Memory pull for 10.2 - Peter's fix on flatview_access_allowed() - Peter's fix on MR circular ref # -----BEGIN PGP SIGNATURE----- # # iIgEABYKADAWIQS5GE3CDMRX2s990ak7X8zN86vXBgUCaMg4oxIccGV0ZXJ4QHJl # ZGhhdC5jb20ACgkQO1/MzfOr1wYeLAD+LQ44LdRTjbdlAbDjSNnCorfEBFUmNysK # St4ut4Z9ZzAA+gK8DO12zc41Oi51NaBdD+X0s94DCV4UFl4Cz1D8HoIF # =hAUJ # -----END PGP SIGNATURE----- # gpg: Signature made Mon 15 Sep 2025 09:02:43 AM PDT # gpg: using EDDSA key B9184DC20CC457DACF7DD1A93B5FCCCDF3ABD706 # gpg: issuer "peterx@redhat.com" # gpg: Good signature from "Peter Xu <xzpeter@gmail.com>" [unknown] # gpg: aka "Peter Xu <peterx@redhat.com>" [unknown] # gpg: WARNING: The key's User ID is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: B918 4DC2 0CC4 57DA CF7D D1A9 3B5F CCCD F3AB D706 * tag 'mem-staging-pull-request' of https://gitlab.com/peterx/qemu: memory: Fix leaks due to owner-shared MRs circular references memory: Fix addr/len for flatview_access_allowed() Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -158,8 +158,11 @@ 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.
|
||||
Destruction of a memory region happens automatically when the owner object
|
||||
dies. When there are multiple memory regions under the same owner object,
|
||||
the memory API will guarantee all memory regions will be properly detached
|
||||
and finalized one by one. The order in which memory regions will be
|
||||
finalized is not guaranteed.
|
||||
|
||||
If however the memory region is part of a dynamically allocated data
|
||||
structure, you should call object_unparent() to destroy the memory region
|
||||
|
||||
+37
-9
@@ -1796,16 +1796,37 @@ static void memory_region_finalize(Object *obj)
|
||||
{
|
||||
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||
|
||||
assert(!mr->container);
|
||||
|
||||
/* We know the region is not visible in any address space (it
|
||||
* does not have a container and cannot be a root either because
|
||||
* it has no references, so we can blindly clear mr->enabled.
|
||||
* memory_region_set_enabled instead could trigger a transaction
|
||||
* and cause an infinite loop.
|
||||
/*
|
||||
* Each memory region (that can be freed) must have an owner, and it
|
||||
* always has the same lifecycle of its owner. It means when reaching
|
||||
* here, the memory region's owner's refcount is zero.
|
||||
*
|
||||
* Here it is possible that the MR has:
|
||||
*
|
||||
* (1) mr->container set, which means this MR is a subregion of a
|
||||
* container MR. In this case they must share the same owner as the
|
||||
* container (otherwise the container should have kept a refcount
|
||||
* of this MR's owner).
|
||||
*
|
||||
* (2) mr->subregions non-empty, which means this MR is a container of
|
||||
* one or more other MRs (which might have the the owner as this
|
||||
* MR, or a different owner).
|
||||
*
|
||||
* We know the MR, or any MR that is attached to this one as either
|
||||
* container or children, is not visible in any address space, because
|
||||
* otherwise the address space should have taken at least one refcount
|
||||
* of this MR's owner. So we can blindly clear mr->enabled.
|
||||
*
|
||||
* memory_region_set_enabled instead could trigger a transaction and
|
||||
* cause an infinite loop.
|
||||
*/
|
||||
mr->enabled = false;
|
||||
memory_region_transaction_begin();
|
||||
if (mr->container) {
|
||||
/* Must share the owner; see above comments */
|
||||
assert(mr->container->owner == mr->owner);
|
||||
memory_region_del_subregion(mr->container, mr);
|
||||
}
|
||||
while (!QTAILQ_EMPTY(&mr->subregions)) {
|
||||
MemoryRegion *subregion = QTAILQ_FIRST(&mr->subregions);
|
||||
memory_region_del_subregion(mr, subregion);
|
||||
@@ -2640,7 +2661,10 @@ static void memory_region_update_container_subregions(MemoryRegion *subregion)
|
||||
|
||||
memory_region_transaction_begin();
|
||||
|
||||
memory_region_ref(subregion);
|
||||
if (mr->owner != subregion->owner) {
|
||||
memory_region_ref(subregion);
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
|
||||
if (subregion->priority >= other->priority) {
|
||||
QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
|
||||
@@ -2698,7 +2722,11 @@ void memory_region_del_subregion(MemoryRegion *mr,
|
||||
assert(alias->mapped_via_alias >= 0);
|
||||
}
|
||||
QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
|
||||
memory_region_unref(subregion);
|
||||
|
||||
if (mr->owner != subregion->owner) {
|
||||
memory_region_unref(subregion);
|
||||
}
|
||||
|
||||
memory_region_update_pending |= mr->enabled && subregion->enabled;
|
||||
memory_region_transaction_commit();
|
||||
}
|
||||
|
||||
+2
-2
@@ -3027,7 +3027,7 @@ static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
|
||||
|
||||
l = len;
|
||||
mr = flatview_translate(fv, addr, &mr_addr, &l, true, attrs);
|
||||
if (!flatview_access_allowed(mr, attrs, addr, len)) {
|
||||
if (!flatview_access_allowed(mr, attrs, mr_addr, l)) {
|
||||
return MEMTX_ACCESS_ERROR;
|
||||
}
|
||||
return flatview_write_continue(fv, addr, attrs, buf, len,
|
||||
@@ -3118,7 +3118,7 @@ static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
|
||||
|
||||
l = len;
|
||||
mr = flatview_translate(fv, addr, &mr_addr, &l, false, attrs);
|
||||
if (!flatview_access_allowed(mr, attrs, addr, len)) {
|
||||
if (!flatview_access_allowed(mr, attrs, mr_addr, l)) {
|
||||
return MEMTX_ACCESS_ERROR;
|
||||
}
|
||||
return flatview_read_continue(fv, addr, attrs, buf, len,
|
||||
|
||||
Reference in New Issue
Block a user