summaryrefslogtreecommitdiff
path: root/hw/s390x
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2015-06-13 08:46:54 +0200
committerCornelia Huck <cornelia.huck@de.ibm.com>2015-09-07 16:10:43 +0200
commit732bdd383ee06be2655b1a849a628ff03b0000b8 (patch)
tree0326fc4a3804a1904b5f9f387e81c1d1733ae208 /hw/s390x
parent35925a7a73e7df4118cb11667095bd2d8fc4e091 (diff)
downloadqemu-732bdd383ee06be2655b1a849a628ff03b0000b8.tar.gz
qemu-732bdd383ee06be2655b1a849a628ff03b0000b8.tar.bz2
qemu-732bdd383ee06be2655b1a849a628ff03b0000b8.zip
s390/sclp: temporarily fix unassignment/reassignment of memory subregions
Commit 374f2981d1f1 ("memory: protect current_map by RCU") broke unassignment of standby memory on s390x. Looks like that the new parallelism allows races with our (semi broken) memory hotplug code. The flatview_unref() can now be executed after our unparenting. Therefore memory_region_unref() tries to unreference the MemoryRegion itself instead of the parent. In theory, MemoryRegions are now bound to separate devices that control their lifetime. We don't have this yet, so we really want to control their lifetime manually. This patch fixes it temporarily, until we have a proper rework. The only drawback is that they won't pop up in "info qom-tree", but that's better than qemu crashes. We have to release the reference to a memory region after a memory_region_find, as it automatically takes a reference. As we're now able to reassign memory, the MemoryRegion is in fact deleted (otherwise vmstate_register_ram() would complain). Reviewed-by: Matthew Rosato <mjrosato@linux.vnet.ibm.com> Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Diffstat (limited to 'hw/s390x')
-rw-r--r--hw/s390x/sclp.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index b3a6c5e5a4..ff29e63994 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -217,6 +217,7 @@ static void assign_storage(SCCB *sccb)
(assign_addr >= mhd->padded_ram_size)) {
/* Re-use existing memory region if found */
mr = memory_region_find(sysmem, assign_addr, 1).mr;
+ memory_region_unref(mr);
if (!mr) {
MemoryRegion *standby_ram = g_new(MemoryRegion, 1);
@@ -242,6 +243,11 @@ static void assign_storage(SCCB *sccb)
}
memory_region_init_ram(standby_ram, NULL, id, this_subregion_size, &error_abort);
+ /* This is a hack to make memory hotunplug work again. Once we have
+ * subdevices, we have to unparent them when unassigning memory,
+ * instead of doing it via the ref count of the MemoryRegion. */
+ object_ref(OBJECT(standby_ram));
+ object_unparent(OBJECT(standby_ram));
vmstate_register_ram_global(standby_ram);
memory_region_add_subregion(sysmem, offset, standby_ram);
}
@@ -269,6 +275,7 @@ static void unassign_storage(SCCB *sccb)
/* find the specified memory region and destroy it */
mr = memory_region_find(sysmem, unassign_addr, 1).mr;
+ memory_region_unref(mr);
if (mr) {
int i;
int is_removable = 1;
@@ -287,8 +294,7 @@ static void unassign_storage(SCCB *sccb)
}
if (is_removable) {
memory_region_del_subregion(sysmem, mr);
- object_unparent(OBJECT(mr));
- g_free(mr);
+ object_unref(OBJECT(mr));
}
}
}