mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 18:23:57 -06:00
xen-bus: use a separate fd for each event channel
To better support use of IOThread-s it will be necessary to be able to set the AioContext for each XenEventChannel and hence it is necessary to open a separate handle to libxenevtchan for each channel. This patch stops using NotifierList for event channel callbacks, replacing that construct by a list of complete XenEventChannel structures. Each of these now has a xenevtchn_handle pointer in place of the single pointer previously held in the XenDevice structure. The individual handles are opened/closed in xen_device_bind/unbind_event_channel(), replacing the single open/close in xen_device_realize/unrealize(). NOTE: This patch does not add an AioContext parameter to xen_device_bind_event_channel(). That will be done in a subsequent patch. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Reviewed-by: Anthony PERARD <anthony.perard@citrix.com> Message-Id: <20190408151617.13025-2-paul.durrant@citrix.com> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
This commit is contained in:
parent
5feeb718d7
commit
c0b336ea19
2 changed files with 42 additions and 43 deletions
|
@ -924,19 +924,22 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct XenEventChannel {
|
struct XenEventChannel {
|
||||||
|
QLIST_ENTRY(XenEventChannel) list;
|
||||||
|
xenevtchn_handle *xeh;
|
||||||
evtchn_port_t local_port;
|
evtchn_port_t local_port;
|
||||||
XenEventHandler handler;
|
XenEventHandler handler;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
Notifier notifier;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void event_notify(Notifier *n, void *data)
|
static void xen_device_event(void *opaque)
|
||||||
{
|
{
|
||||||
XenEventChannel *channel = container_of(n, XenEventChannel, notifier);
|
XenEventChannel *channel = opaque;
|
||||||
unsigned long port = (unsigned long)data;
|
unsigned long port = xenevtchn_pending(channel->xeh);
|
||||||
|
|
||||||
if (port == channel->local_port) {
|
if (port == channel->local_port) {
|
||||||
channel->handler(channel->opaque);
|
channel->handler(channel->opaque);
|
||||||
|
|
||||||
|
xenevtchn_unmask(channel->xeh, port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -948,24 +951,39 @@ XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
|
||||||
XenEventChannel *channel = g_new0(XenEventChannel, 1);
|
XenEventChannel *channel = g_new0(XenEventChannel, 1);
|
||||||
xenevtchn_port_or_error_t local_port;
|
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,
|
xendev->frontend_id,
|
||||||
port);
|
port);
|
||||||
if (local_port < 0) {
|
if (local_port < 0) {
|
||||||
error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
|
error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
|
||||||
|
goto fail;
|
||||||
g_free(channel);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
channel->local_port = local_port;
|
channel->local_port = local_port;
|
||||||
channel->handler = handler;
|
channel->handler = handler;
|
||||||
channel->opaque = opaque;
|
channel->opaque = opaque;
|
||||||
channel->notifier.notify = event_notify;
|
|
||||||
|
|
||||||
notifier_list_add(&xendev->event_notifiers, &channel->notifier);
|
qemu_set_fd_handler(xenevtchn_fd(channel->xeh), xen_device_event, NULL,
|
||||||
|
channel);
|
||||||
|
|
||||||
|
QLIST_INSERT_HEAD(&xendev->event_channels, channel, list);
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (channel->xeh) {
|
||||||
|
xenevtchn_close(channel->xeh);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(channel);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xen_device_notify_event_channel(XenDevice *xendev,
|
void xen_device_notify_event_channel(XenDevice *xendev,
|
||||||
|
@ -977,7 +995,7 @@ void xen_device_notify_event_channel(XenDevice *xendev,
|
||||||
return;
|
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");
|
error_setg_errno(errp, errno, "xenevtchn_notify failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -991,12 +1009,15 @@ void xen_device_unbind_event_channel(XenDevice *xendev,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
notifier_remove(&channel->notifier);
|
QLIST_REMOVE(channel, list);
|
||||||
|
|
||||||
if (xenevtchn_unbind(xendev->xeh, channel->local_port) < 0) {
|
qemu_set_fd_handler(xenevtchn_fd(channel->xeh), NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) {
|
||||||
error_setg_errno(errp, errno, "xenevtchn_unbind failed");
|
error_setg_errno(errp, errno, "xenevtchn_unbind failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xenevtchn_close(channel->xeh);
|
||||||
g_free(channel);
|
g_free(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,6 +1026,7 @@ static void xen_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
XenDevice *xendev = XEN_DEVICE(dev);
|
XenDevice *xendev = XEN_DEVICE(dev);
|
||||||
XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
|
XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
|
||||||
const char *type = object_get_typename(OBJECT(xendev));
|
const char *type = object_get_typename(OBJECT(xendev));
|
||||||
|
XenEventChannel *channel, *next;
|
||||||
|
|
||||||
if (!xendev->name) {
|
if (!xendev->name) {
|
||||||
return;
|
return;
|
||||||
|
@ -1021,15 +1043,14 @@ static void xen_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
xendev_class->unrealize(xendev, 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_frontend_destroy(xendev);
|
||||||
xen_device_backend_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) {
|
if (xendev->xgth) {
|
||||||
xengnttab_close(xendev->xgth);
|
xengnttab_close(xendev->xgth);
|
||||||
xendev->xgth = NULL;
|
xendev->xgth = NULL;
|
||||||
|
@ -1046,16 +1067,6 @@ static void xen_device_exit(Notifier *n, void *data)
|
||||||
xen_device_unrealize(DEVICE(xendev), &error_abort);
|
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)
|
static void xen_device_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
XenDevice *xendev = XEN_DEVICE(dev);
|
XenDevice *xendev = XEN_DEVICE(dev);
|
||||||
|
@ -1096,16 +1107,6 @@ static void xen_device_realize(DeviceState *dev, Error **errp)
|
||||||
xendev->feature_grant_copy =
|
xendev->feature_grant_copy =
|
||||||
(xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
|
(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);
|
xen_device_backend_create(xendev, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
typedef void (*XenWatchHandler)(void *opaque);
|
typedef void (*XenWatchHandler)(void *opaque);
|
||||||
|
|
||||||
typedef struct XenWatch XenWatch;
|
typedef struct XenWatch XenWatch;
|
||||||
|
typedef struct XenEventChannel XenEventChannel;
|
||||||
|
|
||||||
typedef struct XenDevice {
|
typedef struct XenDevice {
|
||||||
DeviceState qdev;
|
DeviceState qdev;
|
||||||
|
@ -28,8 +29,7 @@ typedef struct XenDevice {
|
||||||
XenWatch *backend_online_watch;
|
XenWatch *backend_online_watch;
|
||||||
xengnttab_handle *xgth;
|
xengnttab_handle *xgth;
|
||||||
bool feature_grant_copy;
|
bool feature_grant_copy;
|
||||||
xenevtchn_handle *xeh;
|
QLIST_HEAD(, XenEventChannel) event_channels;
|
||||||
NotifierList event_notifiers;
|
|
||||||
} XenDevice;
|
} XenDevice;
|
||||||
|
|
||||||
typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp);
|
typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp);
|
||||||
|
@ -119,8 +119,6 @@ void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
|
||||||
XenDeviceGrantCopySegment segs[],
|
XenDeviceGrantCopySegment segs[],
|
||||||
unsigned int nr_segs, Error **errp);
|
unsigned int nr_segs, Error **errp);
|
||||||
|
|
||||||
typedef struct XenEventChannel XenEventChannel;
|
|
||||||
|
|
||||||
typedef void (*XenEventHandler)(void *opaque);
|
typedef void (*XenEventHandler)(void *opaque);
|
||||||
|
|
||||||
XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
|
XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue