Re: [PATCH v2 5/5] vhost: add an RPMsg API

Guennadi Liakhovetski
2020-05-27T17:47:19Z

Hi Mathieu,

On Tue, May 26, 2020 at 02:50:39PM -0600, Mathieu Poirier wrote:
> Hi Guennadi,
>
> On Mon, May 25, 2020 at 04:44:58PM +0200, Guennadi Liakhovetski wrote:
> > 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 <guennadi.liakhovetski@linux.intel.com>
> > ---
> > drivers/vhost/Kconfig | 7 +
> > drivers/vhost/Makefile | 3 +
> > drivers/vhost/rpmsg.c | 372 ++++++++++++++++++++++++++++++++++++++++++++
> > drivers/vhost/vhost_rpmsg.h | 74 +++++++++
> > 4 files changed, 456 insertions(+)
> > create mode 100644 drivers/vhost/rpmsg.c
> > create mode 100644 drivers/vhost/vhost_rpmsg.h

[snip]

> > +/* send namespace */
> > +int vhost_rpmsg_ns_announce(struct vhost_rpmsg *vr, const char *name,
> > + unsigned int src)
> > +{
> > + struct vhost_rpmsg_iter iter = {
> > + .rhdr = {
> > + .src = 0,
> > + .dst = RPMSG_NS_ADDR,
> > + .flags = RPMSG_NS_CREATE, /* rpmsg_recv_single() */
> > + },
> > + };
> > + struct rpmsg_ns_msg ns = {
> > + .addr = src,
> > + .flags = RPMSG_NS_CREATE, /* for rpmsg_ns_cb() */
> > + };
>
> I think it would be worth mentioning that someone on the guest side needs to
> call register_virtio_device() with a vdev->id->device == VIRTIO_ID_RPMSG,
> something that will match that device to the virtio_ipc_driver. Otherwise the
> connection between them is very difficult to establish.

In fact you don't want to use just one ID, as you add more drivers, using RPMsg
over VirtIO, you'll add more IDs to the ID table in virtio_rpmsg_bus.c. I am
adding a comment at the top of this file to explain that.

Thanks
Guennadi

> Aside from the checkpatch warning I already pointed out, I don't have much else.
>
> Thanks,
> Mathieu
>
> > + 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 00000000..5248ac9
> > --- /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 <guennadi.liakhovetski@linux.intel.com>
> > + */
> > +
> > +#ifndef VHOST_RPMSG_H
> > +#define VHOST_RPMSG_H
> > +
> > +#include <linux/uio.h>
> > +#include <linux/virtio_rpmsg.h>
> > +
> > +#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(_src, _dst) { \
> > + .rhdr = { \
> > + .src = _src, \
> > + .dst = _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
> > --
> > 1.9.3
> >