From patchwork Mon Dec 17 11:40:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Durrant X-Patchwork-Id: 10733165 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7747B6C2 for ; Mon, 17 Dec 2018 11:42:29 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6526229C79 for ; Mon, 17 Dec 2018 11:42:29 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 56B7829C87; Mon, 17 Dec 2018 11:42:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id C087629C79 for ; Mon, 17 Dec 2018 11:42:27 +0000 (UTC) Received: from localhost ([::1]:46158 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gYrI2-0005JH-DB for patchwork-qemu-devel@patchwork.kernel.org; Mon, 17 Dec 2018 06:42:26 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52842) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gYrGc-00048r-QX for qemu-devel@nongnu.org; Mon, 17 Dec 2018 06:41:00 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gYrGa-0006ZT-3x for qemu-devel@nongnu.org; Mon, 17 Dec 2018 06:40:58 -0500 Received: from smtp03.citrix.com ([162.221.156.55]:44677) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gYrGZ-0006YC-S4; Mon, 17 Dec 2018 06:40:56 -0500 X-IronPort-AV: E=Sophos;i="5.56,365,1539648000"; d="scan'208";a="73532588" From: Paul Durrant To: , , Date: Mon, 17 Dec 2018 11:40:37 +0000 Message-ID: <1545046848-14891-8-git-send-email-paul.durrant@citrix.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1545046848-14891-1-git-send-email-paul.durrant@citrix.com> References: <1545046848-14891-1-git-send-email-paul.durrant@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 162.221.156.55 Subject: [Qemu-devel] [PATCH v5 07/18] xen: add event channel interface for XenDevice-s X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paul Durrant , Stefano Stabellini Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Anthony Perard --- Cc: Stefano Stabellini v2: - Added error pointers to notify and unbind --- 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 faa9fd3..9443f27 100644 --- a/hw/xen/xen-bus.c +++ b/hw/xen/xen-bus.c @@ -617,6 +617,81 @@ done: 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 63a09b6..f83a95c 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 */