[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 09/25] xen: add event channel interface for XenDevice
From: |
Anthony PERARD |
Subject: |
[Qemu-devel] [PULL 09/25] xen: add event channel interface for XenDevice-s |
Date: |
Thu, 10 Jan 2019 13:49:01 +0000 |
From: Paul Durrant <address@hidden>
The legacy PV backend infrastructure provides functions to bind, unbind
and send notifications to event channnels. Similar functionality will be
required by XenDevice implementations so this patch adds the necessary
support.
Signed-off-by: Paul Durrant <address@hidden>
Reviewed-by: Anthony Perard <address@hidden>
Signed-off-by: Anthony PERARD <address@hidden>
---
hw/xen/xen-bus.c | 101 +++++++++++++++++++++++++++++++++++++++
include/hw/xen/xen-bus.h | 18 +++++++
2 files changed, 119 insertions(+)
diff --git a/hw/xen/xen-bus.c b/hw/xen/xen-bus.c
index faa9fd3577..9443f27d44 100644
--- a/hw/xen/xen-bus.c
+++ b/hw/xen/xen-bus.c
@@ -617,6 +617,81 @@ void xen_device_copy_grant_refs(XenDevice *xendev, bool
to_domain,
g_free(xengnttab_segs);
}
+struct XenEventChannel {
+ unsigned int local_port;
+ XenEventHandler handler;
+ void *opaque;
+ Notifier notifier;
+};
+
+static void event_notify(Notifier *n, void *data)
+{
+ XenEventChannel *channel = container_of(n, XenEventChannel, notifier);
+ unsigned long port = (unsigned long)data;
+
+ if (port == channel->local_port) {
+ channel->handler(channel->opaque);
+ }
+}
+
+XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
+ unsigned int port,
+ XenEventHandler handler,
+ void *opaque, Error **errp)
+{
+ XenEventChannel *channel = g_new0(XenEventChannel, 1);
+
+ channel->local_port = xenevtchn_bind_interdomain(xendev->xeh,
+ xendev->frontend_id,
+ port);
+ if (xendev->local_port < 0) {
+ error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
+
+ g_free(channel);
+ return NULL;
+ }
+
+ channel->handler = handler;
+ channel->opaque = opaque;
+ channel->notifier.notify = event_notify;
+
+ notifier_list_add(&xendev->event_notifiers, &channel->notifier);
+
+ return channel;
+}
+
+void xen_device_notify_event_channel(XenDevice *xendev,
+ XenEventChannel *channel,
+ Error **errp)
+{
+ if (!channel) {
+ error_setg(errp, "bad channel");
+ return;
+ }
+
+ if (xenevtchn_notify(xendev->xeh, channel->local_port) < 0) {
+ error_setg_errno(errp, errno, "xenevtchn_notify failed");
+ }
+}
+
+void xen_device_unbind_event_channel(XenDevice *xendev,
+ XenEventChannel *channel,
+ Error **errp)
+{
+ if (!channel) {
+ error_setg(errp, "bad channel");
+ return;
+ }
+
+ notifier_remove(&channel->notifier);
+
+ if (xenevtchn_unbind(xendev->xeh, channel->local_port) < 0) {
+ error_setg_errno(errp, errno, "xenevtchn_unbind failed");
+ }
+
+ g_free(channel);
+}
+
static void xen_device_unrealize(DeviceState *dev, Error **errp)
{
XenDevice *xendev = XEN_DEVICE(dev);
@@ -641,6 +716,12 @@ static void xen_device_unrealize(DeviceState *dev, Error
**errp)
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;
@@ -657,6 +738,16 @@ 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);
@@ -697,6 +788,16 @@ 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/include/hw/xen/xen-bus.h b/include/hw/xen/xen-bus.h
index 63a09b67ee..f83a95cebd 100644
--- a/include/hw/xen/xen-bus.h
+++ b/include/hw/xen/xen-bus.h
@@ -26,6 +26,9 @@ typedef struct XenDevice {
XenWatch *frontend_state_watch;
xengnttab_handle *xgth;
bool feature_grant_copy;
+ xenevtchn_handle *xeh;
+ xenevtchn_port_or_error_t local_port;
+ NotifierList event_notifiers;
} XenDevice;
typedef char *(*XenDeviceGetName)(XenDevice *xendev, Error **errp);
@@ -104,4 +107,19 @@ void xen_device_copy_grant_refs(XenDevice *xendev, bool
to_domain,
XenDeviceGrantCopySegment segs[],
unsigned int nr_segs, Error **errp);
+typedef struct XenEventChannel XenEventChannel;
+
+typedef void (*XenEventHandler)(void *opaque);
+
+XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
+ unsigned int port,
+ XenEventHandler handler,
+ void *opaque, Error **errp);
+void xen_device_notify_event_channel(XenDevice *xendev,
+ XenEventChannel *channel,
+ Error **errp);
+void xen_device_unbind_event_channel(XenDevice *xendev,
+ XenEventChannel *channel,
+ Error **errp);
+
#endif /* HW_XEN_BUS_H */
--
Anthony PERARD
- [Qemu-devel] [PULL 00/25] xen queue, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 08/25] xen: add grant table interface for XenDevice-s, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 05/25] xen: introduce 'xen-block', 'xen-disk' and 'xen-cdrom', Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 01/25] hw/xen/xen_pt_graphics: Don't trust the BIOS ROM contents so much, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 02/25] xen/pt: allow passthrough of devices with bogus interrupt pin, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 09/25] xen: add event channel interface for XenDevice-s,
Anthony PERARD <=
- [Qemu-devel] [PULL 07/25] xen: add xenstore watcher infrastructure, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 04/25] xen: introduce new 'XenBus' and 'XenDevice' object hierarchy, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 06/25] xen: create xenstore areas for XenDevice-s, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 03/25] xen: re-name XenDevice to XenLegacyDevice..., Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 19/25] MAINTAINERS: add myself as a Xen maintainer, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 12/25] xen: add header and build dataplane/xen-block.c, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 14/25] xen: remove 'ioreq' struct/varable/field names from dataplane/xen-block.c, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 23/25] xen-block: improve batching behaviour, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 24/25] xen-block: improve response latency, Anthony PERARD, 2019/01/10
- [Qemu-devel] [PULL 17/25] xen: add a mechanism to automatically create XenDevice-s..., Anthony PERARD, 2019/01/10