aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/ppc/spapr.c21
-rw-r--r--hw/ppc/spapr_drc.c7
2 files changed, 21 insertions, 7 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 6841bd294b..6285f7211f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1411,6 +1411,19 @@ static void find_unknown_sysbus_device(SysBusDevice *sbdev, void *opaque)
}
}
+static int spapr_reset_drcs(Object *child, void *opaque)
+{
+ sPAPRDRConnector *drc =
+ (sPAPRDRConnector *) object_dynamic_cast(child,
+ TYPE_SPAPR_DR_CONNECTOR);
+
+ if (drc) {
+ spapr_drc_reset(drc);
+ }
+
+ return 0;
+}
+
static void ppc_spapr_reset(void)
{
MachineState *machine = MACHINE(qdev_get_machine());
@@ -1434,6 +1447,14 @@ static void ppc_spapr_reset(void)
}
qemu_devices_reset();
+
+ /* DRC reset may cause a device to be unplugged. This will cause troubles
+ * if this device is used by another device (eg, a running vhost backend
+ * will crash QEMU if the DIMM holding the vring goes away). To avoid such
+ * situations, we reset DRCs after all devices have been reset.
+ */
+ object_child_foreach_recursive(object_get_root(), spapr_reset_drcs, NULL);
+
spapr_clear_pending_events(spapr);
/*
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 915e9b51c4..e3b122968e 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -455,11 +455,6 @@ void spapr_drc_reset(sPAPRDRConnector *drc)
}
}
-static void drc_reset(void *opaque)
-{
- spapr_drc_reset(SPAPR_DR_CONNECTOR(opaque));
-}
-
bool spapr_drc_needed(void *opaque)
{
sPAPRDRConnector *drc = (sPAPRDRConnector *)opaque;
@@ -518,7 +513,6 @@ static void realize(DeviceState *d, Error **errp)
}
vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc,
drc);
- qemu_register_reset(drc_reset, drc);
trace_spapr_drc_realize_complete(spapr_drc_index(drc));
}
@@ -529,7 +523,6 @@ static void unrealize(DeviceState *d, Error **errp)
gchar *name;
trace_spapr_drc_unrealize(spapr_drc_index(drc));
- qemu_unregister_reset(drc_reset, drc);
vmstate_unregister(DEVICE(drc), &vmstate_spapr_drc, drc);
root_container = container_get(object_get_root(), DRC_CONTAINER_PATH);
name = g_strdup_printf("%x", spapr_drc_index(drc));