From patchwork Tue Sep 1 15:11:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 11749289 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D1FCD109A for ; Tue, 1 Sep 2020 17:23:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B6FC721548 for ; Tue, 1 Sep 2020 17:23:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728788AbgIARXU (ORCPT ); Tue, 1 Sep 2020 13:23:20 -0400 Received: from mga07.intel.com ([134.134.136.100]:55893 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727112AbgIAPL7 (ORCPT ); Tue, 1 Sep 2020 11:11:59 -0400 IronPort-SDR: 7m7f6xU7N+UzjPxmzEoY+7C5UQHr7sBI1Dp/RUxBYiWZv/spVNe6t+FB+wXwEX1NYzCvgTVn5i qlWR4SNoE7AA== X-IronPort-AV: E=McAfee;i="6000,8403,9730"; a="221408208" X-IronPort-AV: E=Sophos;i="5.76,379,1592895600"; d="scan'208";a="221408208" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Sep 2020 08:11:59 -0700 IronPort-SDR: /wgnN22BFee6yJ3dN/boURLM6bcZdYWN5tJ46cG829uTIa4Uit3+gy/yMn0VDIFFh0A3ftGTJz cpLlK+qcSsTg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,379,1592895600"; d="scan'208";a="501776247" Received: from gliakhov-mobl2.ger.corp.intel.com (HELO ubuntu.ger.corp.intel.com) ([10.252.56.69]) by fmsmga006.fm.intel.com with ESMTP; 01 Sep 2020 08:11:56 -0700 From: Guennadi Liakhovetski To: kvm@vger.kernel.org Cc: linux-remoteproc@vger.kernel.org, virtualization@lists.linux-foundation.org, sound-open-firmware@alsa-project.org, Pierre-Louis Bossart , Liam Girdwood , "Michael S. Tsirkin" , Jason Wang , Ohad Ben-Cohen , Bjorn Andersson , Mathieu Poirier , Vincent Whitchurch Subject: [PATCH v6 1/4] vhost: convert VHOST_VSOCK_SET_RUNNING to a generic ioctl Date: Tue, 1 Sep 2020 17:11:50 +0200 Message-Id: <20200901151153.28111-2-guennadi.liakhovetski@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200901151153.28111-1-guennadi.liakhovetski@linux.intel.com> References: <20200901151153.28111-1-guennadi.liakhovetski@linux.intel.com> MIME-Version: 1.0 Sender: linux-remoteproc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-remoteproc@vger.kernel.org VHOST_VSOCK_SET_RUNNING is used by the vhost vsock driver to perform crucial VirtQueue initialisation, like assigning .private fields and calling vhost_vq_init_access(), and clean up. However, this ioctl is actually extremely useful for any vhost driver, that doesn't have a side channel to inform it of a status change, e.g. upon a guest reboot. This patch makes that ioctl generic, while preserving its numeric value and also keeping the original alias. Signed-off-by: Guennadi Liakhovetski --- include/uapi/linux/vhost.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h index 75232185324a..11a4948b6216 100644 --- a/include/uapi/linux/vhost.h +++ b/include/uapi/linux/vhost.h @@ -97,6 +97,8 @@ #define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64) #define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64) +#define VHOST_SET_RUNNING _IOW(VHOST_VIRTIO, 0x61, int) + /* VHOST_NET specific defines */ /* Attach virtio net ring to a raw socket, or tap device. @@ -118,7 +120,7 @@ /* VHOST_VSOCK specific defines */ #define VHOST_VSOCK_SET_GUEST_CID _IOW(VHOST_VIRTIO, 0x60, __u64) -#define VHOST_VSOCK_SET_RUNNING _IOW(VHOST_VIRTIO, 0x61, int) +#define VHOST_VSOCK_SET_RUNNING VHOST_SET_RUNNING /* VHOST_VDPA specific defines */ From patchwork Tue Sep 1 15:11:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 11749285 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 83F55109A for ; Tue, 1 Sep 2020 17:22:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 70BE02078B for ; Tue, 1 Sep 2020 17:22:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732583AbgIARWf (ORCPT ); Tue, 1 Sep 2020 13:22:35 -0400 Received: from mga07.intel.com ([134.134.136.100]:55909 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727820AbgIAPME (ORCPT ); Tue, 1 Sep 2020 11:12:04 -0400 IronPort-SDR: 8ltii0s1c+lgVytTIDXeriosPWd7VDfGsXbGTakodx44T4bniv75Hz+C23I1EQgoFnCuH+FAnN 5nq3MENE8j9Q== X-IronPort-AV: E=McAfee;i="6000,8403,9730"; a="221408223" X-IronPort-AV: E=Sophos;i="5.76,379,1592895600"; d="scan'208";a="221408223" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Sep 2020 08:12:02 -0700 IronPort-SDR: P7iFU2OfdO05FbpyK9ina94/lW2Gc5jD/EMGahSsKEpm7nASxWmujGlap+xFJSP8wyd/CgZsjf 2rODbQv68JMQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,379,1592895600"; d="scan'208";a="501776273" Received: from gliakhov-mobl2.ger.corp.intel.com (HELO ubuntu.ger.corp.intel.com) ([10.252.56.69]) by fmsmga006.fm.intel.com with ESMTP; 01 Sep 2020 08:11:59 -0700 From: Guennadi Liakhovetski To: kvm@vger.kernel.org Cc: linux-remoteproc@vger.kernel.org, virtualization@lists.linux-foundation.org, sound-open-firmware@alsa-project.org, Pierre-Louis Bossart , Liam Girdwood , "Michael S. Tsirkin" , Jason Wang , Ohad Ben-Cohen , Bjorn Andersson , Mathieu Poirier , Vincent Whitchurch Subject: [PATCH v6 2/4] rpmsg: move common structures and defines to headers Date: Tue, 1 Sep 2020 17:11:51 +0200 Message-Id: <20200901151153.28111-3-guennadi.liakhovetski@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200901151153.28111-1-guennadi.liakhovetski@linux.intel.com> References: <20200901151153.28111-1-guennadi.liakhovetski@linux.intel.com> MIME-Version: 1.0 Sender: linux-remoteproc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-remoteproc@vger.kernel.org virtio_rpmsg_bus.c keeps RPMsg protocol structure declarations and common defines like the ones, needed for name-space announcements, internal. Move them to common headers instead. Signed-off-by: Guennadi Liakhovetski Reviewed-by: Mathieu Poirier --- drivers/rpmsg/virtio_rpmsg_bus.c | 78 +----------------------------- include/linux/rpmsg/virtio.h | 83 ++++++++++++++++++++++++++++++++ include/uapi/linux/rpmsg.h | 3 ++ 3 files changed, 88 insertions(+), 76 deletions(-) create mode 100644 include/linux/rpmsg/virtio.h diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 9006fc7f73d0..f39c426f9c5e 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include "rpmsg_internal.h" @@ -70,58 +72,6 @@ struct virtproc_info { struct rpmsg_endpoint *ns_ept; }; -/* The feature bitmap for virtio rpmsg */ -#define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ - -/** - * struct rpmsg_hdr - common header for all rpmsg messages - * @src: source address - * @dst: destination address - * @reserved: reserved for future use - * @len: length of payload (in bytes) - * @flags: message flags - * @data: @len bytes of message payload data - * - * Every message sent(/received) on the rpmsg bus begins with this header. - */ -struct rpmsg_hdr { - __virtio32 src; - __virtio32 dst; - __virtio32 reserved; - __virtio16 len; - __virtio16 flags; - u8 data[]; -} __packed; - -/** - * struct rpmsg_ns_msg - dynamic name service announcement message - * @name: name of remote service that is published - * @addr: address of remote service that is published - * @flags: indicates whether service is created or destroyed - * - * This message is sent across to publish a new service, or announce - * about its removal. When we receive these messages, an appropriate - * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe() - * or ->remove() handler of the appropriate rpmsg driver will be invoked - * (if/as-soon-as one is registered). - */ -struct rpmsg_ns_msg { - char name[RPMSG_NAME_SIZE]; - __virtio32 addr; - __virtio32 flags; -} __packed; - -/** - * enum rpmsg_ns_flags - dynamic name service announcement flags - * - * @RPMSG_NS_CREATE: a new remote service was just created - * @RPMSG_NS_DESTROY: a known remote service was just destroyed - */ -enum rpmsg_ns_flags { - RPMSG_NS_CREATE = 0, - RPMSG_NS_DESTROY = 1, -}; - /** * @vrp: the remote processor this channel belongs to */ @@ -134,27 +84,6 @@ struct virtio_rpmsg_channel { #define to_virtio_rpmsg_channel(_rpdev) \ container_of(_rpdev, struct virtio_rpmsg_channel, rpdev) -/* - * We're allocating buffers of 512 bytes each for communications. The - * number of buffers will be computed from the number of buffers supported - * by the vring, upto a maximum of 512 buffers (256 in each direction). - * - * Each buffer will have 16 bytes for the msg header and 496 bytes for - * the payload. - * - * This will utilize a maximum total space of 256KB for the buffers. - * - * We might also want to add support for user-provided buffers in time. - * This will allow bigger buffer size flexibility, and can also be used - * to achieve zero-copy messaging. - * - * Note that these numbers are purely a decision of this driver - we - * can change this without changing anything in the firmware of the remote - * processor. - */ -#define MAX_RPMSG_NUM_BUFS (512) -#define MAX_RPMSG_BUF_SIZE (512) - /* * Local addresses are dynamically allocated on-demand. * We do not dynamically assign addresses from the low 1024 range, @@ -162,9 +91,6 @@ struct virtio_rpmsg_channel { */ #define RPMSG_RESERVED_ADDRESSES (1024) -/* Address 53 is reserved for advertising remote services */ -#define RPMSG_NS_ADDR (53) - static void virtio_rpmsg_destroy_ept(struct rpmsg_endpoint *ept); static int virtio_rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len); static int virtio_rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, diff --git a/include/linux/rpmsg/virtio.h b/include/linux/rpmsg/virtio.h new file mode 100644 index 000000000000..3ede1a4a68a3 --- /dev/null +++ b/include/linux/rpmsg/virtio.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _LINUX_RPMSG_VIRTIO_H +#define _LINUX_RPMSG_VIRTIO_H + +#include +#include +#include + +/** + * struct rpmsg_hdr - common header for all rpmsg messages + * @src: source address + * @dst: destination address + * @reserved: reserved for future use + * @len: length of payload (in bytes) + * @flags: message flags + * @data: @len bytes of message payload data + * + * Every message sent(/received) on the rpmsg bus begins with this header. + */ +struct rpmsg_hdr { + __virtio32 src; + __virtio32 dst; + __virtio32 reserved; + __virtio16 len; + __virtio16 flags; + u8 data[]; +} __packed; + +/** + * struct rpmsg_ns_msg - dynamic name service announcement message + * @name: name of remote service that is published + * @addr: address of remote service that is published + * @flags: indicates whether service is created or destroyed + * + * This message is sent across to publish a new service, or announce + * about its removal. When we receive these messages, an appropriate + * rpmsg channel (i.e device) is created/destroyed. In turn, the ->probe() + * or ->remove() handler of the appropriate rpmsg driver will be invoked + * (if/as-soon-as one is registered). + */ +struct rpmsg_ns_msg { + char name[RPMSG_NAME_SIZE]; + __virtio32 addr; + __virtio32 flags; +} __packed; + +/** + * enum rpmsg_ns_flags - dynamic name service announcement flags + * + * @RPMSG_NS_CREATE: a new remote service was just created + * @RPMSG_NS_DESTROY: a known remote service was just destroyed + */ +enum rpmsg_ns_flags { + RPMSG_NS_CREATE = 0, + RPMSG_NS_DESTROY = 1, +}; + +/* + * We're allocating buffers of 512 bytes each for communications. The + * number of buffers will be computed from the number of buffers supported + * by the vring, upto a maximum of 512 buffers (256 in each direction). + * + * Each buffer will have 16 bytes for the msg header and 496 bytes for + * the payload. + * + * This will utilize a maximum total space of 256KB for the buffers. + * + * We might also want to add support for user-provided buffers in time. + * This will allow bigger buffer size flexibility, and can also be used + * to achieve zero-copy messaging. + * + * Note that these numbers are purely a decision of this driver - we + * can change this without changing anything in the firmware of the remote + * processor. + */ +#define MAX_RPMSG_NUM_BUFS 512 +#define MAX_RPMSG_BUF_SIZE 512 + +/* Address 53 is reserved for advertising remote services */ +#define RPMSG_NS_ADDR 53 + +#endif diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h index e14c6dab4223..d669c04ef289 100644 --- a/include/uapi/linux/rpmsg.h +++ b/include/uapi/linux/rpmsg.h @@ -24,4 +24,7 @@ struct rpmsg_endpoint_info { #define RPMSG_CREATE_EPT_IOCTL _IOW(0xb5, 0x1, struct rpmsg_endpoint_info) #define RPMSG_DESTROY_EPT_IOCTL _IO(0xb5, 0x2) +/* The feature bitmap for virtio rpmsg */ +#define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ + #endif From patchwork Tue Sep 1 15:11:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 11749281 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E0188109B for ; Tue, 1 Sep 2020 17:22:36 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D1FC52078B for ; Tue, 1 Sep 2020 17:22:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728548AbgIARWe (ORCPT ); Tue, 1 Sep 2020 13:22:34 -0400 Received: from mga07.intel.com ([134.134.136.100]:55917 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728376AbgIAPMF (ORCPT ); Tue, 1 Sep 2020 11:12:05 -0400 IronPort-SDR: Yi8Sr5vMSz4huBJpKBQAa6uChiIVNIJr3Il/vQ0fqW8gbrWb1YII5D7zfvN5bvVwwQHVvJ75G2 c7oXqV4tyYrQ== X-IronPort-AV: E=McAfee;i="6000,8403,9730"; a="221408238" X-IronPort-AV: E=Sophos;i="5.76,379,1592895600"; d="scan'208";a="221408238" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Sep 2020 08:12:05 -0700 IronPort-SDR: KY3ITyjNybES8RRoN5nLNNm1NBcyDuWPMFZT+NH7uYeYoNN4duRxHzIHvcxKnGkPNz9gw+iQT5 ydYZmEmEYUFw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,379,1592895600"; d="scan'208";a="501776301" Received: from gliakhov-mobl2.ger.corp.intel.com (HELO ubuntu.ger.corp.intel.com) ([10.252.56.69]) by fmsmga006.fm.intel.com with ESMTP; 01 Sep 2020 08:12:02 -0700 From: Guennadi Liakhovetski To: kvm@vger.kernel.org Cc: linux-remoteproc@vger.kernel.org, virtualization@lists.linux-foundation.org, sound-open-firmware@alsa-project.org, Pierre-Louis Bossart , Liam Girdwood , "Michael S. Tsirkin" , Jason Wang , Ohad Ben-Cohen , Bjorn Andersson , Mathieu Poirier , Vincent Whitchurch Subject: [PATCH v6 3/4] rpmsg: update documentation Date: Tue, 1 Sep 2020 17:11:52 +0200 Message-Id: <20200901151153.28111-4-guennadi.liakhovetski@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200901151153.28111-1-guennadi.liakhovetski@linux.intel.com> References: <20200901151153.28111-1-guennadi.liakhovetski@linux.intel.com> MIME-Version: 1.0 Sender: linux-remoteproc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-remoteproc@vger.kernel.org rpmsg_create_ept() takes struct rpmsg_channel_info chinfo as its last argument, not a u32 value. The first two arguments are also updated. Signed-off-by: Guennadi Liakhovetski --- Documentation/rpmsg.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/rpmsg.txt b/Documentation/rpmsg.txt index 24b7a9e1a5f9..1ce353cb232a 100644 --- a/Documentation/rpmsg.txt +++ b/Documentation/rpmsg.txt @@ -192,9 +192,9 @@ Returns 0 on success and an appropriate error value on failure. :: - struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_channel *rpdev, - void (*cb)(struct rpmsg_channel *, void *, int, void *, u32), - void *priv, u32 addr); + struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev, + rpmsg_rx_cb_t cb, void *priv, + struct rpmsg_channel_info chinfo); every rpmsg address in the system is bound to an rx callback (so when inbound messages arrive, they are dispatched by the rpmsg bus using the From patchwork Tue Sep 1 15:11:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 11748679 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0939A138A for ; Tue, 1 Sep 2020 15:12:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EAC01208CA for ; Tue, 1 Sep 2020 15:12:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728498AbgIAPMM (ORCPT ); Tue, 1 Sep 2020 11:12:12 -0400 Received: from mga07.intel.com ([134.134.136.100]:55926 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728454AbgIAPMJ (ORCPT ); Tue, 1 Sep 2020 11:12:09 -0400 IronPort-SDR: rQ+UJPrJFURGXjA915btLw5hFn8qhHHfSArfjNVLhhZ1GfzRglmcPKajFYLZN5HuUlqfwF/EOl L/VaZYgcpv8A== X-IronPort-AV: E=McAfee;i="6000,8403,9730"; a="221408251" X-IronPort-AV: E=Sophos;i="5.76,379,1592895600"; d="scan'208";a="221408251" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 01 Sep 2020 08:12:08 -0700 IronPort-SDR: T7qyvAHrbLTBm6zjOM/+O5db6VeI77o7L91ZbZykzUgDAI5Lpkc2uqt38lw3g7Cvre1WIYcdgV LQaG0j+pKIYQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.76,379,1592895600"; d="scan'208";a="501776316" Received: from gliakhov-mobl2.ger.corp.intel.com (HELO ubuntu.ger.corp.intel.com) ([10.252.56.69]) by fmsmga006.fm.intel.com with ESMTP; 01 Sep 2020 08:12:05 -0700 From: Guennadi Liakhovetski To: kvm@vger.kernel.org Cc: linux-remoteproc@vger.kernel.org, virtualization@lists.linux-foundation.org, sound-open-firmware@alsa-project.org, Pierre-Louis Bossart , Liam Girdwood , "Michael S. Tsirkin" , Jason Wang , Ohad Ben-Cohen , Bjorn Andersson , Mathieu Poirier , Vincent Whitchurch Subject: [PATCH v6 4/4] vhost: add an RPMsg API Date: Tue, 1 Sep 2020 17:11:53 +0200 Message-Id: <20200901151153.28111-5-guennadi.liakhovetski@linux.intel.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200901151153.28111-1-guennadi.liakhovetski@linux.intel.com> References: <20200901151153.28111-1-guennadi.liakhovetski@linux.intel.com> MIME-Version: 1.0 Sender: linux-remoteproc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-remoteproc@vger.kernel.org Linux supports running the RPMsg protocol over the VirtIO transport protocol, but currently there is only support for VirtIO clients and no support for a VirtIO server. This patch adds a vhost-based RPMsg server implementation. Signed-off-by: Guennadi Liakhovetski --- drivers/vhost/Kconfig | 7 + drivers/vhost/Makefile | 3 + drivers/vhost/rpmsg.c | 373 ++++++++++++++++++++++++++++++++++++ drivers/vhost/vhost_rpmsg.h | 74 +++++++ 4 files changed, 457 insertions(+) create mode 100644 drivers/vhost/rpmsg.c create mode 100644 drivers/vhost/vhost_rpmsg.h diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig index 587fbae06182..046b948fc411 100644 --- a/drivers/vhost/Kconfig +++ b/drivers/vhost/Kconfig @@ -38,6 +38,13 @@ config VHOST_NET To compile this driver as a module, choose M here: the module will be called vhost_net. +config VHOST_RPMSG + tristate + select VHOST + help + Vhost RPMsg API allows vhost drivers to communicate with VirtIO + drivers, using the RPMsg over VirtIO protocol. + config VHOST_SCSI tristate "VHOST_SCSI TCM fabric driver" depends on TARGET_CORE && EVENTFD diff --git a/drivers/vhost/Makefile b/drivers/vhost/Makefile index f3e1897cce85..9cf459d59f97 100644 --- a/drivers/vhost/Makefile +++ b/drivers/vhost/Makefile @@ -2,6 +2,9 @@ obj-$(CONFIG_VHOST_NET) += vhost_net.o vhost_net-y := net.o +obj-$(CONFIG_VHOST_RPMSG) += vhost_rpmsg.o +vhost_rpmsg-y := rpmsg.o + obj-$(CONFIG_VHOST_SCSI) += vhost_scsi.o vhost_scsi-y := scsi.o diff --git a/drivers/vhost/rpmsg.c b/drivers/vhost/rpmsg.c new file mode 100644 index 000000000000..2fa527121a8f --- /dev/null +++ b/drivers/vhost/rpmsg.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Guennadi Liakhovetski + * + * Vhost RPMsg VirtIO interface. It provides a set of functions to match the + * guest side RPMsg VirtIO API, provided by drivers/rpmsg/virtio_rpmsg_bus.c + * These functions handle creation of 2 virtual queues, handling of endpoint + * addresses, sending a name-space announcement to the guest as well as any + * user messages. This API can be used by any vhost driver to handle RPMsg + * specific processing. + * Specific vhost drivers, using this API will use their own VirtIO device + * IDs, that should then also be added to the ID table in virtio_rpmsg_bus.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vhost.h" +#include "vhost_rpmsg.h" + +/* + * All virtio-rpmsg virtual queue kicks always come with just one buffer - + * either input or output, but we can also handle split messages + */ +static int vhost_rpmsg_get_msg(struct vhost_virtqueue *vq, unsigned int *cnt) +{ + struct vhost_rpmsg *vr = container_of(vq->dev, struct vhost_rpmsg, dev); + unsigned int out, in; + int head = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov), &out, &in, + NULL, NULL); + if (head < 0) { + vq_err(vq, "%s(): error %d getting buffer\n", + __func__, head); + return head; + } + + /* Nothing new? */ + if (head == vq->num) + return head; + + if (vq == &vr->vq[VIRTIO_RPMSG_RESPONSE]) { + if (out) { + vq_err(vq, "%s(): invalid %d output in response queue\n", + __func__, out); + goto return_buf; + } + + *cnt = in; + } + + if (vq == &vr->vq[VIRTIO_RPMSG_REQUEST]) { + if (in) { + vq_err(vq, "%s(): invalid %d input in request queue\n", + __func__, in); + goto return_buf; + } + + *cnt = out; + } + + return head; + +return_buf: + vhost_add_used(vq, head, 0); + + return -EINVAL; +} + +static const struct vhost_rpmsg_ept *vhost_rpmsg_ept_find(struct vhost_rpmsg *vr, int addr) +{ + unsigned int i; + + for (i = 0; i < vr->n_epts; i++) + if (vr->ept[i].addr == addr) + return vr->ept + i; + + return NULL; +} + +/* + * if len < 0, then for reading a request, the complete virtual queue buffer + * size is prepared, for sending a response, the length in the iterator is used + */ +int vhost_rpmsg_start_lock(struct vhost_rpmsg *vr, struct vhost_rpmsg_iter *iter, + unsigned int qid, ssize_t len) + __acquires(vq->mutex) +{ + struct vhost_virtqueue *vq = vr->vq + qid; + unsigned int cnt; + ssize_t ret; + size_t tmp; + + if (qid >= VIRTIO_RPMSG_NUM_OF_VQS) + return -EINVAL; + + iter->vq = vq; + + mutex_lock(&vq->mutex); + vhost_disable_notify(&vr->dev, vq); + + iter->head = vhost_rpmsg_get_msg(vq, &cnt); + if (iter->head == vq->num) + iter->head = -EAGAIN; + + if (iter->head < 0) { + ret = iter->head; + goto unlock; + } + + tmp = iov_length(vq->iov, cnt); + if (tmp < sizeof(iter->rhdr)) { + vq_err(vq, "%s(): size %zu too small\n", __func__, tmp); + ret = -ENOBUFS; + goto return_buf; + } + + switch (qid) { + case VIRTIO_RPMSG_REQUEST: + if (len >= 0) { + if (tmp < sizeof(iter->rhdr) + len) { + ret = -ENOBUFS; + goto return_buf; + } + + tmp = len + sizeof(iter->rhdr); + } + + /* len is now the size of the payload */ + iov_iter_init(&iter->iov_iter, WRITE, vq->iov, cnt, tmp); + + /* Read the RPMSG header with endpoint addresses */ + tmp = copy_from_iter(&iter->rhdr, sizeof(iter->rhdr), &iter->iov_iter); + if (tmp != sizeof(iter->rhdr)) { + vq_err(vq, "%s(): got %zu instead of %zu\n", __func__, + tmp, sizeof(iter->rhdr)); + ret = -EIO; + goto return_buf; + } + + iter->ept = vhost_rpmsg_ept_find(vr, vhost32_to_cpu(vq, iter->rhdr.dst)); + if (!iter->ept) { + vq_err(vq, "%s(): no endpoint with address %d\n", + __func__, vhost32_to_cpu(vq, iter->rhdr.dst)); + ret = -ENOENT; + goto return_buf; + } + + /* Let the endpoint read the payload */ + if (iter->ept->read) { + ret = iter->ept->read(vr, iter); + if (ret < 0) + goto return_buf; + + iter->rhdr.len = cpu_to_vhost16(vq, ret); + } else { + iter->rhdr.len = 0; + } + + /* Prepare for the response phase */ + iter->rhdr.dst = iter->rhdr.src; + iter->rhdr.src = cpu_to_vhost32(vq, iter->ept->addr); + + break; + case VIRTIO_RPMSG_RESPONSE: + if (!iter->ept && iter->rhdr.dst != cpu_to_vhost32(vq, RPMSG_NS_ADDR)) { + /* + * Usually the iterator is configured when processing a + * message on the request queue, but it's also possible + * to send a message on the response queue without a + * preceding request, in that case the iterator must + * contain source and destination addresses. + */ + iter->ept = vhost_rpmsg_ept_find(vr, vhost32_to_cpu(vq, iter->rhdr.src)); + if (!iter->ept) { + ret = -ENOENT; + goto return_buf; + } + } + + if (len >= 0) { + if (tmp < sizeof(iter->rhdr) + len) { + ret = -ENOBUFS; + goto return_buf; + } + + iter->rhdr.len = cpu_to_vhost16(vq, len); + tmp = len + sizeof(iter->rhdr); + } + + /* len is now the size of the payload */ + iov_iter_init(&iter->iov_iter, READ, vq->iov, cnt, tmp); + + /* Write the RPMSG header with endpoint addresses */ + tmp = copy_to_iter(&iter->rhdr, sizeof(iter->rhdr), &iter->iov_iter); + if (tmp != sizeof(iter->rhdr)) { + ret = -EIO; + goto return_buf; + } + + /* Let the endpoint write the payload */ + if (iter->ept && iter->ept->write) { + ret = iter->ept->write(vr, iter); + if (ret < 0) + goto return_buf; + } + + break; + } + + return 0; + +return_buf: + vhost_add_used(vq, iter->head, 0); +unlock: + vhost_enable_notify(&vr->dev, vq); + mutex_unlock(&vq->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(vhost_rpmsg_start_lock); + +size_t vhost_rpmsg_copy(struct vhost_rpmsg *vr, struct vhost_rpmsg_iter *iter, + void *data, size_t size) +{ + /* + * We could check for excess data, but copy_{to,from}_iter() don't do + * that either + */ + if (iter->vq == vr->vq + VIRTIO_RPMSG_RESPONSE) + return copy_to_iter(data, size, &iter->iov_iter); + + return copy_from_iter(data, size, &iter->iov_iter); +} +EXPORT_SYMBOL_GPL(vhost_rpmsg_copy); + +int vhost_rpmsg_finish_unlock(struct vhost_rpmsg *vr, + struct vhost_rpmsg_iter *iter) + __releases(vq->mutex) +{ + if (iter->head >= 0) + vhost_add_used_and_signal(iter->vq->dev, iter->vq, iter->head, + vhost16_to_cpu(iter->vq, iter->rhdr.len) + + sizeof(iter->rhdr)); + + vhost_enable_notify(&vr->dev, iter->vq); + mutex_unlock(&iter->vq->mutex); + + return iter->head; +} +EXPORT_SYMBOL_GPL(vhost_rpmsg_finish_unlock); + +/* + * Return false to terminate the external loop only if we fail to obtain either + * a request or a response buffer + */ +static bool handle_rpmsg_req_single(struct vhost_rpmsg *vr, + struct vhost_virtqueue *vq) +{ + struct vhost_rpmsg_iter iter; + int ret = vhost_rpmsg_start_lock(vr, &iter, VIRTIO_RPMSG_REQUEST, -EINVAL); + if (!ret) + ret = vhost_rpmsg_finish_unlock(vr, &iter); + if (ret < 0) { + if (ret != -EAGAIN) + vq_err(vq, "%s(): RPMSG processing failed %d\n", + __func__, ret); + return false; + } + + if (!iter.ept->write) + return true; + + ret = vhost_rpmsg_start_lock(vr, &iter, VIRTIO_RPMSG_RESPONSE, -EINVAL); + if (!ret) + ret = vhost_rpmsg_finish_unlock(vr, &iter); + if (ret < 0) { + vq_err(vq, "%s(): RPMSG finalising failed %d\n", __func__, ret); + return false; + } + + return true; +} + +static void handle_rpmsg_req_kick(struct vhost_work *work) +{ + struct vhost_virtqueue *vq = container_of(work, struct vhost_virtqueue, + poll.work); + struct vhost_rpmsg *vr = container_of(vq->dev, struct vhost_rpmsg, dev); + + while (handle_rpmsg_req_single(vr, vq)) + ; +} + +/* + * initialise two virtqueues with an array of endpoints, + * request and response callbacks + */ +void vhost_rpmsg_init(struct vhost_rpmsg *vr, const struct vhost_rpmsg_ept *ept, + unsigned int n_epts) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(vr->vq); i++) + vr->vq_p[i] = &vr->vq[i]; + + /* vq[0]: host -> guest, vq[1]: host <- guest */ + vr->vq[VIRTIO_RPMSG_REQUEST].handle_kick = handle_rpmsg_req_kick; + vr->vq[VIRTIO_RPMSG_RESPONSE].handle_kick = NULL; + + vr->ept = ept; + vr->n_epts = n_epts; + + vhost_dev_init(&vr->dev, vr->vq_p, VIRTIO_RPMSG_NUM_OF_VQS, + UIO_MAXIOV, 0, 0, true, NULL); +} +EXPORT_SYMBOL_GPL(vhost_rpmsg_init); + +void vhost_rpmsg_destroy(struct vhost_rpmsg *vr) +{ + if (vhost_dev_has_owner(&vr->dev)) + vhost_poll_flush(&vr->vq[VIRTIO_RPMSG_REQUEST].poll); + + vhost_dev_cleanup(&vr->dev); +} +EXPORT_SYMBOL_GPL(vhost_rpmsg_destroy); + +/* send namespace */ +int vhost_rpmsg_ns_announce(struct vhost_rpmsg *vr, const char *name, unsigned int src) +{ + struct vhost_virtqueue *vq = &vr->vq[VIRTIO_RPMSG_RESPONSE]; + struct vhost_rpmsg_iter iter = { + .rhdr = { + .src = 0, + .dst = cpu_to_vhost32(vq, RPMSG_NS_ADDR), + .flags = cpu_to_vhost16(vq, RPMSG_NS_CREATE), /* rpmsg_recv_single() */ + }, + }; + struct rpmsg_ns_msg ns = { + .addr = cpu_to_vhost32(vq, src), + .flags = cpu_to_vhost32(vq, RPMSG_NS_CREATE), /* for rpmsg_ns_cb() */ + }; + int ret = vhost_rpmsg_start_lock(vr, &iter, VIRTIO_RPMSG_RESPONSE, sizeof(ns)); + + if (ret < 0) + return ret; + + strlcpy(ns.name, name, sizeof(ns.name)); + + ret = vhost_rpmsg_copy(vr, &iter, &ns, sizeof(ns)); + if (ret != sizeof(ns)) + vq_err(iter.vq, "%s(): added %d instead of %zu bytes\n", + __func__, ret, sizeof(ns)); + + ret = vhost_rpmsg_finish_unlock(vr, &iter); + if (ret < 0) + vq_err(iter.vq, "%s(): namespace announcement failed: %d\n", + __func__, ret); + + return ret; +} +EXPORT_SYMBOL_GPL(vhost_rpmsg_ns_announce); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Intel, Inc."); +MODULE_DESCRIPTION("Vhost RPMsg API"); diff --git a/drivers/vhost/vhost_rpmsg.h b/drivers/vhost/vhost_rpmsg.h new file mode 100644 index 000000000000..c020ea14cd16 --- /dev/null +++ b/drivers/vhost/vhost_rpmsg.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Guennadi Liakhovetski + */ + +#ifndef VHOST_RPMSG_H +#define VHOST_RPMSG_H + +#include +#include + +#include "vhost.h" + +/* RPMsg uses two VirtQueues: one for each direction */ +enum { + VIRTIO_RPMSG_RESPONSE, /* RPMsg response (host->guest) buffers */ + VIRTIO_RPMSG_REQUEST, /* RPMsg request (guest->host) buffers */ + /* Keep last */ + VIRTIO_RPMSG_NUM_OF_VQS, +}; + +struct vhost_rpmsg_ept; + +struct vhost_rpmsg_iter { + struct iov_iter iov_iter; + struct rpmsg_hdr rhdr; + struct vhost_virtqueue *vq; + const struct vhost_rpmsg_ept *ept; + int head; + void *priv; +}; + +struct vhost_rpmsg { + struct vhost_dev dev; + struct vhost_virtqueue vq[VIRTIO_RPMSG_NUM_OF_VQS]; + struct vhost_virtqueue *vq_p[VIRTIO_RPMSG_NUM_OF_VQS]; + const struct vhost_rpmsg_ept *ept; + unsigned int n_epts; +}; + +struct vhost_rpmsg_ept { + ssize_t (*read)(struct vhost_rpmsg *, struct vhost_rpmsg_iter *); + ssize_t (*write)(struct vhost_rpmsg *, struct vhost_rpmsg_iter *); + int addr; +}; + +static inline size_t vhost_rpmsg_iter_len(const struct vhost_rpmsg_iter *iter) +{ + return iter->rhdr.len; +} + +#define VHOST_RPMSG_ITER(_vq, _src, _dst) { \ + .rhdr = { \ + .src = cpu_to_vhost32(_vq, _src), \ + .dst = cpu_to_vhost32(_vq, _dst), \ + }, \ + } + +void vhost_rpmsg_init(struct vhost_rpmsg *vr, const struct vhost_rpmsg_ept *ept, + unsigned int n_epts); +void vhost_rpmsg_destroy(struct vhost_rpmsg *vr); +int vhost_rpmsg_ns_announce(struct vhost_rpmsg *vr, const char *name, + unsigned int src); +int vhost_rpmsg_start_lock(struct vhost_rpmsg *vr, + struct vhost_rpmsg_iter *iter, + unsigned int qid, ssize_t len); +size_t vhost_rpmsg_copy(struct vhost_rpmsg *vr, struct vhost_rpmsg_iter *iter, + void *data, size_t size); +int vhost_rpmsg_finish_unlock(struct vhost_rpmsg *vr, + struct vhost_rpmsg_iter *iter); + +#endif