From b8030af450b629ce8066512c6f2a69afacf8324a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 14 Oct 2019 16:22:34 +0200 Subject: [PATCH 1/3] hw/xen/xen_pt_load_rom: Remove unused includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit xen_pt_load_rom.c does not use any of these includes, remove them. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Paul Durrant Message-Id: <20191014142246.4538-9-philmd@redhat.com> Signed-off-by: Anthony PERARD --- hw/xen/xen_pt_load_rom.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c index 307a5c93e2..a50a80837e 100644 --- a/hw/xen/xen_pt_load_rom.c +++ b/hw/xen/xen_pt_load_rom.c @@ -3,12 +3,8 @@ */ #include "qemu/osdep.h" #include "qapi/error.h" -#include "hw/i386/pc.h" #include "qemu/error-report.h" -#include "ui/console.h" #include "hw/loader.h" -#include "monitor/monitor.h" -#include "qemu/range.h" #include "hw/pci/pci.h" #include "xen_pt.h" From 32d0b7be68216f130dc962533c6fc2f9ad848a8b Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Mon, 16 Dec 2019 14:34:51 +0000 Subject: [PATCH 2/3] xen-bus/block: explicitly assign event channels to an AioContext It is not safe to close an event channel from the QEMU main thread when that channel's poller is running in IOThread context. This patch adds a new xen_device_set_event_channel_context() function to explicitly assign the channel AioContext, and modifies xen_device_bind_event_channel() to initially assign the channel's poller to the QEMU main thread context. The code in xen-block's dataplane is then modified to assign the channel to IOThread context during xen_block_dataplane_start() and de-assign it during in xen_block_dataplane_stop(), such that the channel is always assigned back to main thread context before it is closed. aio_set_fd_handler() already deals with all the necessary synchronization when moving an fd between AioContext-s so no extra code is needed to manage this. Reported-by: Julien Grall Signed-off-by: Paul Durrant Reviewed-by: Anthony PERARD Message-Id: <20191216143451.19024-1-pdurrant@amazon.com> Signed-off-by: Anthony PERARD --- hw/block/dataplane/xen-block.c | 20 ++++++++++++++++++-- hw/xen/xen-bus.c | 27 +++++++++++++++++++++++---- include/hw/xen/xen-bus.h | 5 ++++- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c index 3b9caeb2fa..288a87a814 100644 --- a/hw/block/dataplane/xen-block.c +++ b/hw/block/dataplane/xen-block.c @@ -685,12 +685,24 @@ void xen_block_dataplane_stop(XenBlockDataPlane *dataplane) return; } + xendev = dataplane->xendev; + aio_context_acquire(dataplane->ctx); + if (dataplane->event_channel) { + /* Only reason for failure is a NULL channel */ + xen_device_set_event_channel_context(xendev, dataplane->event_channel, + qemu_get_aio_context(), + &error_abort); + } /* Xen doesn't have multiple users for nodes, so this can't fail */ blk_set_aio_context(dataplane->blk, qemu_get_aio_context(), &error_abort); aio_context_release(dataplane->ctx); - xendev = dataplane->xendev; + /* + * Now that the context has been moved onto the main thread, cancel + * further processing. + */ + qemu_bh_cancel(dataplane->bh); if (dataplane->event_channel) { Error *local_err = NULL; @@ -807,7 +819,7 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, } dataplane->event_channel = - xen_device_bind_event_channel(xendev, dataplane->ctx, event_channel, + xen_device_bind_event_channel(xendev, event_channel, xen_block_dataplane_event, dataplane, &local_err); if (local_err) { @@ -818,7 +830,11 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane, aio_context_acquire(dataplane->ctx); /* If other users keep the BlockBackend in the iothread, that's ok */ blk_set_aio_context(dataplane->blk, dataplane->ctx, NULL); + /* Only reason for failure is a NULL channel */ + xen_device_set_event_channel_context(xendev, dataplane->event_channel, + dataplane->ctx, &error_abort); aio_context_release(dataplane->ctx); + return; stop: diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c index 919e66162a..18237b34ea 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -1089,8 +1089,26 @@ static void xen_device_event(void *opaque) } } +void xen_device_set_event_channel_context(XenDevice *xendev, + XenEventChannel *channel, + AioContext *ctx, + Error **errp) +{ + if (!channel) { + error_setg(errp, "bad channel"); + return; + } + + if (channel->ctx) + aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true, + NULL, NULL, NULL, NULL); + + channel->ctx = ctx; + aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true, + xen_device_event, NULL, xen_device_poll, channel); +} + XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev, - AioContext *ctx, unsigned int port, XenEventHandler handler, void *opaque, Error **errp) @@ -1116,9 +1134,10 @@ XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev, channel->handler = handler; channel->opaque = opaque; - channel->ctx = ctx; - aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true, - xen_device_event, NULL, xen_device_poll, channel); + /* Only reason for failure is a NULL channel */ + xen_device_set_event_channel_context(xendev, channel, + qemu_get_aio_context(), + &error_abort); QLIST_INSERT_HEAD(&xendev->event_channels, channel, list); diff --git a/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h index 3d5532258d..c18c1372af 100644 --- a/include/hw/xen/xen-bus.h +++ b/include/hw/xen/xen-bus.h @@ -128,10 +128,13 @@ void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain, typedef bool (*XenEventHandler)(void *opaque); XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev, - AioContext *ctx, unsigned int port, XenEventHandler handler, void *opaque, Error **errp); +void xen_device_set_event_channel_context(XenDevice *xendev, + XenEventChannel *channel, + AioContext *ctx, + Error **errp); void xen_device_notify_event_channel(XenDevice *xendev, XenEventChannel *channel, Error **errp); From 5d4c954931ba62661c6a1bc16ce604a012a10007 Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Thu, 19 Dec 2019 15:43:22 +0000 Subject: [PATCH 3/3] Memory: Only call ramblock_ptr when needed in qemu_ram_writeback It is possible that a ramblock doesn't have memory that QEMU can access, this is the case with the Xen hypervisor. In order to avoid to trigger an assert, only call ramblock_ptr() when needed in qemu_ram_writeback(). This should fix migration of Xen guests that was broken with bd108a44bc29 ("migration: ram: Switch to ram block writeback"). Signed-off-by: Anthony PERARD Reviewed-by: Juan Quintela Acked-by: Paolo Bonzini Message-Id: <20191219154323.325255-1-anthony.perard@citrix.com> --- exec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index 231d6e5641..0cc500d53a 100644 --- a/exec.c +++ b/exec.c @@ -2116,14 +2116,13 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) */ void qemu_ram_writeback(RAMBlock *block, ram_addr_t start, ram_addr_t length) { - void *addr = ramblock_ptr(block, start); - /* The requested range should fit in within the block range */ g_assert((start + length) <= block->used_length); #ifdef CONFIG_LIBPMEM /* The lack of support for pmem should not block the sync */ if (ramblock_is_pmem(block)) { + void *addr = ramblock_ptr(block, start); pmem_persist(addr, length); return; } @@ -2134,6 +2133,7 @@ void qemu_ram_writeback(RAMBlock *block, ram_addr_t start, ram_addr_t length) * specified as persistent (or is not one) - use the msync. * Less optimal but still achieves the same goal */ + void *addr = ramblock_ptr(block, start); if (qemu_msync(addr, length, block->fd)) { warn_report("%s: failed to sync memory range: start: " RAM_ADDR_FMT " length: " RAM_ADDR_FMT,