aboutsummaryrefslogtreecommitdiff
path: root/hw/i386
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw@amazon.co.uk>2023-10-17 13:34:18 +0100
committerDavid Woodhouse <dwmw@amazon.co.uk>2023-11-06 10:03:45 +0000
commit4a5780f52095f1daf23618dc6198a2a1665ea505 (patch)
treef5b0ecccaa56144731ab0ad2d0bfca73920c3ddc /hw/i386
parent3de75ed352411899dbc9222e82fe164890c77e78 (diff)
hw/xen: fix XenStore watch delivery to guest
When fire_watch_cb() found the response buffer empty, it would call deliver_watch() to generate the XS_WATCH_EVENT message in the response buffer and send an event channel notification to the guest… without actually *copying* the response buffer into the ring. So there was nothing for the guest to see. The pending response didn't actually get processed into the ring until the guest next triggered some activity from its side. Add the missing call to put_rsp(). It might have been slightly nicer to call xen_xenstore_event() here, which would *almost* have worked. Except for the fact that it calls xen_be_evtchn_pending() to check that it really does have an event pending (and clear the eventfd for next time). And under Xen it's defined that setting that fd to O_NONBLOCK isn't guaranteed to work, so the emu implementation follows suit. This fixes Xen device hot-unplug. Cc: qemu-stable@nongnu.org Fixes: 0254c4d19df ("hw/xen: Add xenstore wire implementation and implementation stubs") Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Reviewed-by: Paul Durrant <paul@xen.org>
Diffstat (limited to 'hw/i386')
-rw-r--r--hw/i386/kvm/xen_xenstore.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/hw/i386/kvm/xen_xenstore.c b/hw/i386/kvm/xen_xenstore.c
index 660d0b72f9..8e716a7009 100644
--- a/hw/i386/kvm/xen_xenstore.c
+++ b/hw/i386/kvm/xen_xenstore.c
@@ -1357,10 +1357,12 @@ static void fire_watch_cb(void *opaque, const char *path, const char *token)
} else {
deliver_watch(s, path, token);
/*
- * If the message was queued because there was already ring activity,
- * no need to wake the guest. But if not, we need to send the evtchn.
+ * Attempt to queue the message into the actual ring, and send
+ * the event channel notification if any bytes are copied.
*/
- xen_be_evtchn_notify(s->eh, s->be_port);
+ if (s->rsp_pending && put_rsp(s) > 0) {
+ xen_be_evtchn_notify(s->eh, s->be_port);
+ }
}
}