aboutsummaryrefslogtreecommitdiff
path: root/hw/xen
diff options
context:
space:
mode:
authorMark Syms <mark.syms@citrix.com>2019-09-18 12:57:44 +0100
committerAnthony PERARD <anthony.perard@citrix.com>2019-09-24 12:21:29 +0100
commit6bd6b955c0b2666263700d39db153ab43c5e0c9e (patch)
tree09419547ab286e039381c1865a77196d7f3a3e5e /hw/xen
parentef916ab3ec570eac799be540e499d0123fe61899 (diff)
xen-bus: only set the xen device frontend state if it is missing
Some toolstack implementations will set the frontend xenstore keys to Initialising which will then trigger the in guest PV drivers to begin initialising and some implementations will then set their state to Closing. If this has occurred then device realize must not overwrite the frontend keys as then the handshake will stall. Signed-off-by: Mark Syms <mark.syms@citrix.com> Also avoid creating the frontend area if it already exists. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Reviewed-by: Anthony PERARD <anthony.perard@citrix.com> Message-Id: <20190918115745.39006-1-paul.durrant@citrix.com> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Diffstat (limited to 'hw/xen')
-rw-r--r--hw/xen/xen-bus.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index 55c157393d..c2ad22a42d 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -857,6 +857,13 @@ static void xen_device_frontend_changed(void *opaque)
}
}
+static bool xen_device_frontend_exists(XenDevice *xendev)
+{
+ enum xenbus_state state;
+
+ return (xen_device_frontend_scanf(xendev, "state", "%u", &state) == 1);
+}
+
static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
{
XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
@@ -865,19 +872,25 @@ static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
xendev->frontend_path = xen_device_get_frontend_path(xendev);
- perms[0].id = xendev->frontend_id;
- perms[0].perms = XS_PERM_NONE;
- perms[1].id = xenbus->backend_id;
- perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
+ /*
+ * The frontend area may have already been created by a legacy
+ * toolstack.
+ */
+ if (!xen_device_frontend_exists(xendev)) {
+ perms[0].id = xendev->frontend_id;
+ perms[0].perms = XS_PERM_NONE;
+ perms[1].id = xenbus->backend_id;
+ perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
- g_assert(xenbus->xsh);
+ g_assert(xenbus->xsh);
- xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
- ARRAY_SIZE(perms), &local_err);
- if (local_err) {
- error_propagate_prepend(errp, local_err,
- "failed to create frontend: ");
- return;
+ xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
+ ARRAY_SIZE(perms), &local_err);
+ if (local_err) {
+ error_propagate_prepend(errp, local_err,
+ "failed to create frontend: ");
+ return;
+ }
}
xendev->frontend_state_watch =
@@ -1290,12 +1303,14 @@ static void xen_device_realize(DeviceState *dev, Error **errp)
xen_device_backend_set_online(xendev, true);
xen_device_backend_set_state(xendev, XenbusStateInitWait);
- xen_device_frontend_printf(xendev, "backend", "%s",
- xendev->backend_path);
- xen_device_frontend_printf(xendev, "backend-id", "%u",
- xenbus->backend_id);
+ if (!xen_device_frontend_exists(xendev)) {
+ xen_device_frontend_printf(xendev, "backend", "%s",
+ xendev->backend_path);
+ xen_device_frontend_printf(xendev, "backend-id", "%u",
+ xenbus->backend_id);
- xen_device_frontend_set_state(xendev, XenbusStateInitialising, true);
+ xen_device_frontend_set_state(xendev, XenbusStateInitialising, true);
+ }
xendev->exit.notify = xen_device_exit;
qemu_add_exit_notifier(&xendev->exit);