aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-07-01 13:03:51 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-07-01 13:03:51 +0100
commitab67678a59e31d30b0f8587cdc245f93c2e56fef (patch)
treeebf1089bdc110370e7f976b283ea2e61bb7039b1 /hw
parent7fec76a02267598a4e437ddfdaeaeb6de09b92f3 (diff)
parenta3434a2d56aee3018f4a0f55c7e0f0cda11f3d9e (diff)
downloadqemu-ab67678a59e31d30b0f8587cdc245f93c2e56fef.zip
qemu-ab67678a59e31d30b0f8587cdc245f93c2e56fef.tar.gz
qemu-ab67678a59e31d30b0f8587cdc245f93c2e56fef.tar.bz2
Merge remote-tracking branch 'remotes/aperard/tags/pull-xen-20190624' into staging
Xen queue * Fix build * xen-block: support feature-large-sector-size * xen-block: Support IOThread polling for PV shared rings * Avoid usage of a VLA * Cleanup Xen headers usage # gpg: Signature made Mon 24 Jun 2019 16:30:32 BST # gpg: using RSA key F80C006308E22CFD8A92E7980CF5572FD7FB55AF # gpg: issuer "anthony.perard@citrix.com" # gpg: Good signature from "Anthony PERARD <anthony.perard@gmail.com>" [marginal] # gpg: aka "Anthony PERARD <anthony.perard@citrix.com>" [marginal] # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 5379 2F71 024C 600F 778A 7161 D8D5 7199 DF83 42C8 # Subkey fingerprint: F80C 0063 08E2 2CFD 8A92 E798 0CF5 572F D7FB 55AF * remotes/aperard/tags/pull-xen-20190624: xen: Import other xen/io/*.h Revert xen/io/ring.h of "Clean up a few header guard symbols" xen: Drop includes of xen/hvm/params.h xen: Avoid VLA xen-bus / xen-block: add support for event channel polling xen-bus: allow AioContext to be specified for each event channel xen-bus: use a separate fd for each event channel xen-block: support feature-large-sector-size Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/xen-9pfs.h4
-rw-r--r--hw/block/dataplane/xen-block.c44
-rw-r--r--hw/block/dataplane/xen-block.h3
-rw-r--r--hw/block/xen-block.c38
-rw-r--r--hw/block/xen_blkif.h5
-rw-r--r--hw/char/xen_console.c2
-rw-r--r--hw/display/xenfb.c7
-rw-r--r--hw/i386/xen/xen-hvm.c16
-rw-r--r--hw/i386/xen/xen-mapcache.c2
-rw-r--r--hw/net/xen_nic.c2
-rw-r--r--hw/usb/xen-usb.c3
-rw-r--r--hw/xen/xen-bus.c92
-rw-r--r--hw/xen/xen-legacy-backend.c2
13 files changed, 123 insertions, 97 deletions
diff --git a/hw/9pfs/xen-9pfs.h b/hw/9pfs/xen-9pfs.h
index fbdee3d..241e221 100644
--- a/hw/9pfs/xen-9pfs.h
+++ b/hw/9pfs/xen-9pfs.h
@@ -13,8 +13,8 @@
#ifndef HW_9PFS_XEN_9PFS_H
#define HW_9PFS_XEN_9PFS_H
-#include <xen/io/protocols.h>
-#include "hw/xen/io/ring.h"
+#include "hw/xen/interface/io/protocols.h"
+#include "hw/xen/interface/io/ring.h"
/*
* Do not merge into xen-9p-backend.c: clang doesn't allow unused static
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index f7ad452..0f200c5 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -58,6 +58,7 @@ struct XenBlockDataPlane {
int requests_inflight;
unsigned int max_requests;
BlockBackend *blk;
+ unsigned int sector_size;
QEMUBH *bh;
IOThread *iothread;
AioContext *ctx;
@@ -167,7 +168,7 @@ static int xen_block_parse_request(XenBlockRequest *request)
goto err;
}
- request->start = request->req.sector_number * XEN_BLKIF_SECTOR_SIZE;
+ request->start = request->req.sector_number * dataplane->sector_size;
for (i = 0; i < request->req.nr_segments; i++) {
if (i == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
error_report("error: nr_segments too big");
@@ -177,14 +178,14 @@ static int xen_block_parse_request(XenBlockRequest *request)
error_report("error: first > last sector");
goto err;
}
- if (request->req.seg[i].last_sect * XEN_BLKIF_SECTOR_SIZE >=
+ if (request->req.seg[i].last_sect * dataplane->sector_size >=
XC_PAGE_SIZE) {
error_report("error: page crossing");
goto err;
}
len = (request->req.seg[i].last_sect -
- request->req.seg[i].first_sect + 1) * XEN_BLKIF_SECTOR_SIZE;
+ request->req.seg[i].first_sect + 1) * dataplane->sector_size;
request->size += len;
}
if (request->start + request->size > blk_getlength(dataplane->blk)) {
@@ -218,17 +219,17 @@ static int xen_block_copy_request(XenBlockRequest *request)
if (to_domain) {
segs[i].dest.foreign.ref = request->req.seg[i].gref;
segs[i].dest.foreign.offset = request->req.seg[i].first_sect *
- XEN_BLKIF_SECTOR_SIZE;
+ dataplane->sector_size;
segs[i].source.virt = virt;
} else {
segs[i].source.foreign.ref = request->req.seg[i].gref;
segs[i].source.foreign.offset = request->req.seg[i].first_sect *
- XEN_BLKIF_SECTOR_SIZE;
+ dataplane->sector_size;
segs[i].dest.virt = virt;
}
segs[i].len = (request->req.seg[i].last_sect -
request->req.seg[i].first_sect + 1) *
- XEN_BLKIF_SECTOR_SIZE;
+ dataplane->sector_size;
virt += segs[i].len;
}
@@ -317,7 +318,9 @@ static void xen_block_complete_aio(void *opaque, int ret)
}
xen_block_release_request(request);
- qemu_bh_schedule(dataplane->bh);
+ if (dataplane->more_work) {
+ qemu_bh_schedule(dataplane->bh);
+ }
done:
aio_context_release(dataplane->ctx);
@@ -336,12 +339,12 @@ static bool xen_block_split_discard(XenBlockRequest *request,
/* Wrap around, or overflowing byte limit? */
if (sec_start + sec_count < sec_count ||
- sec_start + sec_count > INT64_MAX / XEN_BLKIF_SECTOR_SIZE) {
+ sec_start + sec_count > INT64_MAX / dataplane->sector_size) {
return false;
}
- byte_offset = sec_start * XEN_BLKIF_SECTOR_SIZE;
- byte_remaining = sec_count * XEN_BLKIF_SECTOR_SIZE;
+ byte_offset = sec_start * dataplane->sector_size;
+ byte_remaining = sec_count * dataplane->sector_size;
do {
byte_chunk = byte_remaining > BDRV_REQUEST_MAX_BYTES ?
@@ -514,12 +517,13 @@ static int xen_block_get_request(XenBlockDataPlane *dataplane,
*/
#define IO_PLUG_THRESHOLD 1
-static void xen_block_handle_requests(XenBlockDataPlane *dataplane)
+static bool xen_block_handle_requests(XenBlockDataPlane *dataplane)
{
RING_IDX rc, rp;
XenBlockRequest *request;
int inflight_atstart = dataplane->requests_inflight;
int batched = 0;
+ bool done_something = false;
dataplane->more_work = 0;
@@ -551,6 +555,7 @@ static void xen_block_handle_requests(XenBlockDataPlane *dataplane)
}
xen_block_get_request(dataplane, request, rc);
dataplane->rings.common.req_cons = ++rc;
+ done_something = true;
/* parse them */
if (xen_block_parse_request(request) != 0) {
@@ -602,10 +607,7 @@ static void xen_block_handle_requests(XenBlockDataPlane *dataplane)
blk_io_unplug(dataplane->blk);
}
- if (dataplane->more_work &&
- dataplane->requests_inflight < dataplane->max_requests) {
- qemu_bh_schedule(dataplane->bh);
- }
+ return done_something;
}
static void xen_block_dataplane_bh(void *opaque)
@@ -617,21 +619,23 @@ static void xen_block_dataplane_bh(void *opaque)
aio_context_release(dataplane->ctx);
}
-static void xen_block_dataplane_event(void *opaque)
+static bool xen_block_dataplane_event(void *opaque)
{
XenBlockDataPlane *dataplane = opaque;
- qemu_bh_schedule(dataplane->bh);
+ return xen_block_handle_requests(dataplane);
}
XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev,
- BlockConf *conf,
+ BlockBackend *blk,
+ unsigned int sector_size,
IOThread *iothread)
{
XenBlockDataPlane *dataplane = g_new0(XenBlockDataPlane, 1);
dataplane->xendev = xendev;
- dataplane->blk = conf->blk;
+ dataplane->blk = blk;
+ dataplane->sector_size = sector_size;
QLIST_INIT(&dataplane->inflight);
QLIST_INIT(&dataplane->freelist);
@@ -803,7 +807,7 @@ void xen_block_dataplane_start(XenBlockDataPlane *dataplane,
}
dataplane->event_channel =
- xen_device_bind_event_channel(xendev, event_channel,
+ xen_device_bind_event_channel(xendev, dataplane->ctx, event_channel,
xen_block_dataplane_event, dataplane,
&local_err);
if (local_err) {
diff --git a/hw/block/dataplane/xen-block.h b/hw/block/dataplane/xen-block.h
index d6fa6d2..76dcd51 100644
--- a/hw/block/dataplane/xen-block.h
+++ b/hw/block/dataplane/xen-block.h
@@ -15,7 +15,8 @@
typedef struct XenBlockDataPlane XenBlockDataPlane;
XenBlockDataPlane *xen_block_dataplane_create(XenDevice *xendev,
- BlockConf *conf,
+ BlockBackend *blk,
+ unsigned int sector_size,
IOThread *iothread);
void xen_block_dataplane_destroy(XenBlockDataPlane *dataplane);
void xen_block_dataplane_start(XenBlockDataPlane *dataplane,
diff --git a/hw/block/xen-block.c b/hw/block/xen-block.c
index 4de537a..8f224ef 100644
--- a/hw/block/xen-block.c
+++ b/hw/block/xen-block.c
@@ -52,11 +52,25 @@ static void xen_block_connect(XenDevice *xendev, Error **errp)
XenBlockDevice *blockdev = XEN_BLOCK_DEVICE(xendev);
const char *type = object_get_typename(OBJECT(blockdev));
XenBlockVdev *vdev = &blockdev->props.vdev;
+ BlockConf *conf = &blockdev->props.conf;
+ unsigned int feature_large_sector_size;
unsigned int order, nr_ring_ref, *ring_ref, event_channel, protocol;
char *str;
trace_xen_block_connect(type, vdev->disk, vdev->partition);
+ if (xen_device_frontend_scanf(xendev, "feature-large-sector-size", "%u",
+ &feature_large_sector_size) != 1) {
+ feature_large_sector_size = 0;
+ }
+
+ if (feature_large_sector_size != 1 &&
+ conf->logical_block_size != XEN_BLKIF_SECTOR_SIZE) {
+ error_setg(errp, "logical_block_size != %u not supported by frontend",
+ XEN_BLKIF_SECTOR_SIZE);
+ return;
+ }
+
if (xen_device_frontend_scanf(xendev, "ring-page-order", "%u",
&order) != 1) {
nr_ring_ref = 1;
@@ -150,7 +164,7 @@ static void xen_block_set_size(XenBlockDevice *blockdev)
const char *type = object_get_typename(OBJECT(blockdev));
XenBlockVdev *vdev = &blockdev->props.vdev;
BlockConf *conf = &blockdev->props.conf;
- int64_t sectors = blk_getlength(conf->blk) / XEN_BLKIF_SECTOR_SIZE;
+ int64_t sectors = blk_getlength(conf->blk) / conf->logical_block_size;
XenDevice *xendev = XEN_DEVICE(blockdev);
trace_xen_block_size(type, vdev->disk, vdev->partition, sectors);
@@ -185,6 +199,7 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
const char *type = object_get_typename(OBJECT(blockdev));
XenBlockVdev *vdev = &blockdev->props.vdev;
BlockConf *conf = &blockdev->props.conf;
+ BlockBackend *blk = conf->blk;
Error *local_err = NULL;
if (vdev->type == XEN_BLOCK_VDEV_TYPE_INVALID) {
@@ -206,8 +221,8 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
* The blkif protocol does not deal with removable media, so it must
* always be present, even for CDRom devices.
*/
- assert(conf->blk);
- if (!blk_is_inserted(conf->blk)) {
+ assert(blk);
+ if (!blk_is_inserted(blk)) {
error_setg(errp, "device needs media, but drive is empty");
return;
}
@@ -224,26 +239,20 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
blkconf_blocksizes(conf);
- if (conf->logical_block_size != XEN_BLKIF_SECTOR_SIZE) {
- error_setg(errp, "logical_block_size != %u not supported",
- XEN_BLKIF_SECTOR_SIZE);
- return;
- }
-
if (conf->logical_block_size > conf->physical_block_size) {
error_setg(
errp, "logical_block_size > physical_block_size not supported");
return;
}
- blk_set_dev_ops(conf->blk, &xen_block_dev_ops, blockdev);
- blk_set_guest_block_size(conf->blk, conf->logical_block_size);
+ blk_set_dev_ops(blk, &xen_block_dev_ops, blockdev);
+ blk_set_guest_block_size(blk, conf->logical_block_size);
if (conf->discard_granularity == -1) {
conf->discard_granularity = conf->physical_block_size;
}
- if (blk_get_flags(conf->blk) & BDRV_O_UNMAP) {
+ if (blk_get_flags(blk) & BDRV_O_UNMAP) {
xen_device_backend_printf(xendev, "feature-discard", "%u", 1);
xen_device_backend_printf(xendev, "discard-granularity", "%u",
conf->discard_granularity);
@@ -260,12 +269,13 @@ static void xen_block_realize(XenDevice *xendev, Error **errp)
blockdev->device_type);
xen_device_backend_printf(xendev, "sector-size", "%u",
- XEN_BLKIF_SECTOR_SIZE);
+ conf->logical_block_size);
xen_block_set_size(blockdev);
blockdev->dataplane =
- xen_block_dataplane_create(xendev, conf, blockdev->props.iothread);
+ xen_block_dataplane_create(xendev, blk, conf->logical_block_size,
+ blockdev->props.iothread);
}
static void xen_block_frontend_changed(XenDevice *xendev,
diff --git a/hw/block/xen_blkif.h b/hw/block/xen_blkif.h
index a353693..9973352 100644
--- a/hw/block/xen_blkif.h
+++ b/hw/block/xen_blkif.h
@@ -1,9 +1,8 @@
#ifndef XEN_BLKIF_H
#define XEN_BLKIF_H
-#include "hw/xen/io/ring.h"
-#include <xen/io/blkif.h>
-#include <xen/io/protocols.h>
+#include "hw/xen/interface/io/blkif.h"
+#include "hw/xen/interface/io/protocols.h"
/*
* Not a real protocol. Used to generate ring structs which contain
diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c
index 91f34ef..47e1092 100644
--- a/hw/char/xen_console.c
+++ b/hw/char/xen_console.c
@@ -28,7 +28,7 @@
#include "chardev/char-fe.h"
#include "hw/xen/xen-legacy-backend.h"
-#include <xen/io/console.h>
+#include "hw/xen/interface/io/console.h"
struct buffer {
uint8_t *data;
diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c
index 6202f11..3c79913 100644
--- a/hw/display/xenfb.c
+++ b/hw/display/xenfb.c
@@ -32,10 +32,9 @@
#include "ui/console.h"
#include "hw/xen/xen-legacy-backend.h"
-#include <xen/event_channel.h>
-#include <xen/io/fbif.h>
-#include <xen/io/kbdif.h>
-#include <xen/io/protocols.h>
+#include "hw/xen/interface/io/fbif.h"
+#include "hw/xen/interface/io/kbdif.h"
+#include "hw/xen/interface/io/protocols.h"
#include "trace.h"
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 2939122..469f126 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -27,7 +27,6 @@
#include "exec/address-spaces.h"
#include <xen/hvm/ioreq.h>
-#include <xen/hvm/params.h>
#include <xen/hvm/e820.h>
//#define DEBUG_XEN_HVM
@@ -120,6 +119,8 @@ typedef struct XenIOState {
DeviceListener device_listener;
hwaddr free_phys_offset;
const XenPhysmap *log_for_dirtybit;
+ /* Buffer used by xen_sync_dirty_bitmap */
+ unsigned long *dirty_bitmap;
Notifier exit;
Notifier suspend;
@@ -465,6 +466,8 @@ static int xen_remove_from_physmap(XenIOState *state,
QLIST_REMOVE(physmap, list);
if (state->log_for_dirtybit == physmap) {
state->log_for_dirtybit = NULL;
+ g_free(state->dirty_bitmap);
+ state->dirty_bitmap = NULL;
}
g_free(physmap);
@@ -615,7 +618,7 @@ static void xen_sync_dirty_bitmap(XenIOState *state,
{
hwaddr npages = size >> TARGET_PAGE_BITS;
const int width = sizeof(unsigned long) * 8;
- unsigned long bitmap[DIV_ROUND_UP(npages, width)];
+ size_t bitmap_size = DIV_ROUND_UP(npages, width);
int rc, i, j;
const XenPhysmap *physmap = NULL;
@@ -627,13 +630,14 @@ static void xen_sync_dirty_bitmap(XenIOState *state,
if (state->log_for_dirtybit == NULL) {
state->log_for_dirtybit = physmap;
+ state->dirty_bitmap = g_new(unsigned long, bitmap_size);
} else if (state->log_for_dirtybit != physmap) {
/* Only one range for dirty bitmap can be tracked. */
return;
}
rc = xen_track_dirty_vram(xen_domid, start_addr >> TARGET_PAGE_BITS,
- npages, bitmap);
+ npages, state->dirty_bitmap);
if (rc < 0) {
#ifndef ENODATA
#define ENODATA ENOENT
@@ -647,8 +651,8 @@ static void xen_sync_dirty_bitmap(XenIOState *state,
return;
}
- for (i = 0; i < ARRAY_SIZE(bitmap); i++) {
- unsigned long map = bitmap[i];
+ for (i = 0; i < bitmap_size; i++) {
+ unsigned long map = state->dirty_bitmap[i];
while (map != 0) {
j = ctzl(map);
map &= ~(1ul << j);
@@ -678,6 +682,8 @@ static void xen_log_stop(MemoryListener *listener, MemoryRegionSection *section,
if (old & ~new & (1 << DIRTY_MEMORY_VGA)) {
state->log_for_dirtybit = NULL;
+ g_free(state->dirty_bitmap);
+ state->dirty_bitmap = NULL;
/* Disable dirty bit tracking */
xen_track_dirty_vram(xen_domid, 0, 0, NULL);
}
diff --git a/hw/i386/xen/xen-mapcache.c b/hw/i386/xen/xen-mapcache.c
index 254759f..dc73c86 100644
--- a/hw/i386/xen/xen-mapcache.c
+++ b/hw/i386/xen/xen-mapcache.c
@@ -17,8 +17,6 @@
#include "hw/xen/xen-legacy-backend.h"
#include "qemu/bitmap.h"
-#include <xen/hvm/params.h>
-
#include "sysemu/xen-mapcache.h"
#include "trace.h"
diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c
index 37cda8e..ffb3b58 100644
--- a/hw/net/xen_nic.c
+++ b/hw/net/xen_nic.c
@@ -30,7 +30,7 @@
#include "net/util.h"
#include "hw/xen/xen-legacy-backend.h"
-#include <xen/io/netif.h>
+#include "hw/xen/interface/io/netif.h"
/* ------------------------------------------------------------- */
diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
index b20d0cf..dfbb418 100644
--- a/hw/usb/xen-usb.c
+++ b/hw/usb/xen-usb.c
@@ -32,8 +32,7 @@
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
-#include "hw/xen/io/ring.h"
-#include <xen/io/usbif.h>
+#include "hw/xen/interface/io/usbif.h"
/*
* Check for required support of usbif.h: USBIF_SHORT_NOT_OK was the last
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index a4416d0..7503eea 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -924,23 +924,35 @@ done:
}
struct XenEventChannel {
+ QLIST_ENTRY(XenEventChannel) list;
+ AioContext *ctx;
+ xenevtchn_handle *xeh;
evtchn_port_t local_port;
XenEventHandler handler;
void *opaque;
- Notifier notifier;
};
-static void event_notify(Notifier *n, void *data)
+static bool xen_device_poll(void *opaque)
+{
+ XenEventChannel *channel = opaque;
+
+ return channel->handler(channel->opaque);
+}
+
+static void xen_device_event(void *opaque)
{
- XenEventChannel *channel = container_of(n, XenEventChannel, notifier);
- unsigned long port = (unsigned long)data;
+ XenEventChannel *channel = opaque;
+ unsigned long port = xenevtchn_pending(channel->xeh);
if (port == channel->local_port) {
- channel->handler(channel->opaque);
+ xen_device_poll(channel);
+
+ xenevtchn_unmask(channel->xeh, port);
}
}
XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
+ AioContext *ctx,
unsigned int port,
XenEventHandler handler,
void *opaque, Error **errp)
@@ -948,24 +960,40 @@ XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
XenEventChannel *channel = g_new0(XenEventChannel, 1);
xenevtchn_port_or_error_t local_port;
- local_port = xenevtchn_bind_interdomain(xendev->xeh,
+ channel->xeh = xenevtchn_open(NULL, 0);
+ if (!channel->xeh) {
+ error_setg_errno(errp, errno, "failed xenevtchn_open");
+ goto fail;
+ }
+
+ local_port = xenevtchn_bind_interdomain(channel->xeh,
xendev->frontend_id,
port);
if (local_port < 0) {
error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
-
- g_free(channel);
- return NULL;
+ goto fail;
}
channel->local_port = local_port;
channel->handler = handler;
channel->opaque = opaque;
- channel->notifier.notify = event_notify;
- notifier_list_add(&xendev->event_notifiers, &channel->notifier);
+ channel->ctx = ctx;
+ aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
+ xen_device_event, NULL, xen_device_poll, channel);
+
+ QLIST_INSERT_HEAD(&xendev->event_channels, channel, list);
return channel;
+
+fail:
+ if (channel->xeh) {
+ xenevtchn_close(channel->xeh);
+ }
+
+ g_free(channel);
+
+ return NULL;
}
void xen_device_notify_event_channel(XenDevice *xendev,
@@ -977,7 +1005,7 @@ void xen_device_notify_event_channel(XenDevice *xendev,
return;
}
- if (xenevtchn_notify(xendev->xeh, channel->local_port) < 0) {
+ if (xenevtchn_notify(channel->xeh, channel->local_port) < 0) {
error_setg_errno(errp, errno, "xenevtchn_notify failed");
}
}
@@ -991,12 +1019,16 @@ void xen_device_unbind_event_channel(XenDevice *xendev,
return;
}
- notifier_remove(&channel->notifier);
+ QLIST_REMOVE(channel, list);
+
+ aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
+ NULL, NULL, NULL, NULL);
- if (xenevtchn_unbind(xendev->xeh, channel->local_port) < 0) {
+ if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) {
error_setg_errno(errp, errno, "xenevtchn_unbind failed");
}
+ xenevtchn_close(channel->xeh);
g_free(channel);
}
@@ -1005,6 +1037,7 @@ static void xen_device_unrealize(DeviceState *dev, Error **errp)
XenDevice *xendev = XEN_DEVICE(dev);
XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
const char *type = object_get_typename(OBJECT(xendev));
+ XenEventChannel *channel, *next;
if (!xendev->name) {
return;
@@ -1021,15 +1054,14 @@ static void xen_device_unrealize(DeviceState *dev, Error **errp)
xendev_class->unrealize(xendev, errp);
}
+ /* Make sure all event channels are cleaned up */
+ QLIST_FOREACH_SAFE(channel, &xendev->event_channels, list, next) {
+ xen_device_unbind_event_channel(xendev, channel, NULL);
+ }
+
xen_device_frontend_destroy(xendev);
xen_device_backend_destroy(xendev);
- if (xendev->xeh) {
- qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), NULL, NULL, NULL);
- xenevtchn_close(xendev->xeh);
- xendev->xeh = NULL;
- }
-
if (xendev->xgth) {
xengnttab_close(xendev->xgth);
xendev->xgth = NULL;
@@ -1046,16 +1078,6 @@ static void xen_device_exit(Notifier *n, void *data)
xen_device_unrealize(DEVICE(xendev), &error_abort);
}
-static void xen_device_event(void *opaque)
-{
- XenDevice *xendev = opaque;
- unsigned long port = xenevtchn_pending(xendev->xeh);
-
- notifier_list_notify(&xendev->event_notifiers, (void *)port);
-
- xenevtchn_unmask(xendev->xeh, port);
-}
-
static void xen_device_realize(DeviceState *dev, Error **errp)
{
XenDevice *xendev = XEN_DEVICE(dev);
@@ -1096,16 +1118,6 @@ static void xen_device_realize(DeviceState *dev, Error **errp)
xendev->feature_grant_copy =
(xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
- xendev->xeh = xenevtchn_open(NULL, 0);
- if (!xendev->xeh) {
- error_setg_errno(errp, errno, "failed xenevtchn_open");
- goto unrealize;
- }
-
- notifier_list_init(&xendev->event_notifiers);
- qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), xen_device_event, NULL,
- xendev);
-
xen_device_backend_create(xendev, &local_err);
if (local_err) {
error_propagate(errp, local_err);
diff --git a/hw/xen/xen-legacy-backend.c b/hw/xen/xen-legacy-backend.c
index 36fd1e9..3715c94 100644
--- a/hw/xen/xen-legacy-backend.c
+++ b/hw/xen/xen-legacy-backend.c
@@ -34,8 +34,6 @@
#include "hw/xen/xen_pvdev.h"
#include "monitor/qdev.h"
-#include <xen/grant_table.h>
-
DeviceState *xen_sysdev;
BusState *xen_sysbus;