aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc/spapr_drc.c
diff options
context:
space:
mode:
authorGreg Kurz <groug@kaod.org>2020-12-18 11:33:56 +0100
committerDavid Gibson <david@gibson.dropbear.id.au>2021-01-06 11:09:59 +1100
commit930ef3b5c212bf8056bd265cc43ed9fff2e31b08 (patch)
tree52ed376346c2d060357ab7de169ed56100772a5f /hw/ppc/spapr_drc.c
parentcd725bd7489e52445a15dd2f0ad1aa746dfa91fc (diff)
downloadqemu-930ef3b5c212bf8056bd265cc43ed9fff2e31b08.zip
qemu-930ef3b5c212bf8056bd265cc43ed9fff2e31b08.tar.gz
qemu-930ef3b5c212bf8056bd265cc43ed9fff2e31b08.tar.bz2
spapr: Fix reset of transient DR connectors
Documentation of object_property_iter_init() clearly stipulates that "it is forbidden to modify the property list while iterating". But this is exactly what we do when resetting transient DR connectors during CAS. The call to spapr_drc_reset() can finalize the hot-unplug sequence of a PHB or a PCI bridge, both of which will then in turn destroy their PCI DRCs. This could potentially invalidate the iterator. It is pure luck that this haven't caused any issues so far. Change spapr_drc_reset() to return true if it caused a device to be removed. Restart from scratch in this case. This can potentially increase the overall DRC reset time, especially with a high maxmem which generates a lot of LMB DRCs. But this kind of setup is rare, and so is the use case of rebooting a guest while doing hot-unplug. Signed-off-by: Greg Kurz <groug@kaod.org> Message-Id: <20201218103400.689660-3-groug@kaod.org> Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com> Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/ppc/spapr_drc.c')
-rw-r--r--hw/ppc/spapr_drc.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 8d62f55..5b5e2ac 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -417,9 +417,10 @@ void spapr_drc_detach(SpaprDrc *drc)
spapr_drc_release(drc);
}
-void spapr_drc_reset(SpaprDrc *drc)
+bool spapr_drc_reset(SpaprDrc *drc)
{
SpaprDrcClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+ bool unplug_completed = false;
trace_spapr_drc_reset(spapr_drc_index(drc));
@@ -428,6 +429,7 @@ void spapr_drc_reset(SpaprDrc *drc)
*/
if (drc->unplug_requested) {
spapr_drc_release(drc);
+ unplug_completed = true;
}
if (drc->dev) {
@@ -444,6 +446,8 @@ void spapr_drc_reset(SpaprDrc *drc)
drc->ccs_offset = -1;
drc->ccs_depth = -1;
}
+
+ return unplug_completed;
}
static bool spapr_drc_unplug_requested_needed(void *opaque)