From: "Michael S. Tsirkin" <mst@redhat.com>
To: Greg Kurz <gkurz@linux.vnet.ibm.com>
Cc: linux-api@vger.kernel.org, linux-kernel@vger.kernel.org,
kvm@vger.kernel.org, virtualization@lists.linux-foundation.org
Subject: Re: [PATCH v2 7/7] vhost: feature to set the vring endianness
Date: Thu, 2 Apr 2015 16:20:46 +0200 [thread overview]
Message-ID: <20150402142046.GA23121@redhat.com> (raw)
In-Reply-To: <20150402131713.24676.9924.stgit@bahia.lab.toulouse-stg.fr.ibm.com>
On Thu, Apr 02, 2015 at 03:17:13PM +0200, Greg Kurz wrote:
> This patch brings cross-endian support to vhost when used to implement
> legacy virtio devices. Since it is a relatively rare situation, the feature
> availability is controlled by a kernel config option (not set by default).
>
> If cross-endian support is compiled in, vhost abvertises a new feature
> to be negotiated with userspace. If userspace acknowledges the feature,
> it can inform vhost about the endianness to use with a new ioctl.
>
> This feature is mutually exclusive with virtio 1.0. Even if the vhost device
> advertises virtio 1.0 and legacy cross-endian features, it cannot receive
> aknowledgement for both at the same time.
>
> Hot paths are being preserved from any penalty when the config option is
> disabled or when virtio 1.0 is being used.
>
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> ---
> drivers/vhost/Kconfig | 10 ++++++++++
> drivers/vhost/net.c | 5 +++++
> drivers/vhost/scsi.c | 4 ++++
> drivers/vhost/test.c | 4 ++++
> drivers/vhost/vhost.c | 19 +++++++++++++++++++
> drivers/vhost/vhost.h | 13 ++++++++++++-
> include/uapi/linux/vhost.h | 10 ++++++++++
> 7 files changed, 64 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
> index 017a1e8..5bb8da9 100644
> --- a/drivers/vhost/Kconfig
> +++ b/drivers/vhost/Kconfig
> @@ -32,3 +32,13 @@ config VHOST
> ---help---
> This option is selected by any driver which needs to access
> the core of vhost.
> +
> +config VHOST_SET_ENDIAN_LEGACY
> + bool "Cross-endian support for host kernel accelerator"
> + default n
> + ---help---
> + This option allows vhost to support guests with a different byte
> + ordering
from host
>. It is disabled by default since it adds overhead and it
> + is only needed by a few platforms (powerpc and arm).
> +
> + If unsure, say "n".
"N"
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 2bbfc25..5274a44 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -1011,6 +1011,11 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features)
> vhost_hlen = 0;
> sock_hlen = hdr_len;
> }
> +
> + if (features & ((1ULL << VHOST_F_SET_ENDIAN_LEGACY) |
> + (1ULL << VIRTIO_F_VERSION_1)))
> + return -EINVAL;
> +
> mutex_lock(&n->dev.mutex);
> if ((features & (1 << VHOST_F_LOG_ALL)) &&
> !vhost_log_access_ok(&n->dev)) {
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index 71df240..b53e9c2 100644
> --- a/drivers/vhost/scsi.c
> +++ b/drivers/vhost/scsi.c
> @@ -1544,6 +1544,10 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
> if (features & ~VHOST_SCSI_FEATURES)
> return -EOPNOTSUPP;
>
> + if (features & ((1ULL << VHOST_F_SET_ENDIAN_LEGACY) |
> + (1ULL << VIRTIO_F_VERSION_1)))
> + return -EINVAL;
> +
> mutex_lock(&vs->dev.mutex);
> if ((features & (1 << VHOST_F_LOG_ALL)) &&
> !vhost_log_access_ok(&vs->dev)) {
> diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> index d9c501e..cfefdad 100644
> --- a/drivers/vhost/test.c
> +++ b/drivers/vhost/test.c
> @@ -243,6 +243,10 @@ static int vhost_test_set_features(struct vhost_test *n, u64 features)
> {
> struct vhost_virtqueue *vq;
>
> + if (features & ((1ULL << VHOST_F_SET_ENDIAN_LEGACY) |
> + (1ULL << VIRTIO_F_VERSION_1)))
> + return -EINVAL;
> +
> mutex_lock(&n->dev.mutex);
> if ((features & (1 << VHOST_F_LOG_ALL)) &&
> !vhost_log_access_ok(&n->dev)) {
Above seems to prevent users from specifying either
VIRTIO_F_VERSION_1 or VHOST_F_SET_ENDIAN_LEGACY.
Does it actually work?
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 2ee2826..60a0f32 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -199,6 +199,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
> vq->call = NULL;
> vq->log_ctx = NULL;
> vq->memory = NULL;
> + vq->legacy_big_endian = false;
> }
>
> static int vhost_worker(void *data)
> @@ -806,6 +807,24 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
> } else
> filep = eventfp;
> break;
> +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> + case VHOST_SET_VRING_ENDIAN_LEGACY:
> + {
> + struct vhost_vring_endian e;
> +
> + if (!vhost_has_feature(vq, VHOST_F_SET_ENDIAN_LEGACY)) {
> + r = -EINVAL;
> + break;
> + }
> +
> + if (copy_from_user(&e, argp, sizeof(e))) {
> + r = -EFAULT;
> + break;
> + }
> + vq->legacy_big_endian = e.is_big_endian;
> + break;
> + }
> +#endif
> default:
> r = -ENOIOCTLCMD;
> }
> diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
> index 4e9a186..d50881d 100644
> --- a/drivers/vhost/vhost.h
> +++ b/drivers/vhost/vhost.h
> @@ -106,6 +106,9 @@ struct vhost_virtqueue {
> /* Log write descriptors */
> void __user *log_base;
> struct vhost_log *log;
> +
> + /* We need to know the device endianness with legacy virtio. */
> + bool legacy_big_endian;
> };
>
> struct vhost_dev {
> @@ -165,7 +168,11 @@ enum {
> VHOST_FEATURES = (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) |
> (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
> (1ULL << VIRTIO_RING_F_EVENT_IDX) |
> - (1ULL << VHOST_F_LOG_ALL),
> + (1ULL << VHOST_F_LOG_ALL) |
> +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> + (1ULL << VHOST_F_SET_ENDIAN_LEGACY) |
> +#endif
> + 0ULL,
> };
>
> static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
> @@ -177,6 +184,10 @@ static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
> {
> if (vhost_has_feature(vq, VIRTIO_F_VERSION_1))
> return true;
> +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> + if (vhost_has_feature(vq, VHOST_F_SET_ENDIAN_LEGACY))
> + return !vq->legacy_big_endian;
why do we need to check the feature bit?
How about simple
return !vq->legacy_big_endian;
here?
All you need to do is set legacy_big_endian to
!virtio_legacy_is_little_endian() on reset.
Maybe rename to legacy_is_little_endian so you don't
need to reverse the logic.
> +#endif
> return virtio_legacy_is_little_endian();
> }
>
> diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> index bb6a5b4..09d2a48 100644
> --- a/include/uapi/linux/vhost.h
> +++ b/include/uapi/linux/vhost.h
> @@ -47,6 +47,11 @@ struct vhost_vring_addr {
> __u64 log_guest_addr;
> };
>
> +struct vhost_vring_endian {
> + unsigned int index;
> + bool is_big_endian;
bool in uapi is a bad idea.
Generally, I think you can use vhost_vring_state here.
> +};
> +
> struct vhost_memory_region {
> __u64 guest_phys_addr;
> __u64 memory_size; /* bytes */
> @@ -103,6 +108,9 @@ struct vhost_memory {
> /* Get accessor: reads index, writes value in num */
> #define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
>
> +/* Set endianness for the ring (legacy virtio only) */
> +#define VHOST_SET_VRING_ENDIAN_LEGACY _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_endian)
> +
> /* The following ioctls use eventfd file descriptors to signal and poll
> * for events. */
>
You also need a GET ioctl, as a matter of policy.
> @@ -126,6 +134,8 @@ struct vhost_memory {
> #define VHOST_F_LOG_ALL 26
> /* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
> #define VHOST_NET_F_VIRTIO_NET_HDR 27
> +/* the vring endianness can be explicitly set (legacy virtio only). */
> +#define VHOST_F_SET_ENDIAN_LEGACY 28
>
> /* VHOST_SCSI specific definitions */
VHOST_F_SET_ENDIAN_LEGACY doesn't seem too useful.
Is this so userspace can detect kernel configuration?
I think probing VHOST_SET_VRING_ENDIAN_LEGACY should
be sufficient for this.
--
MST
WARNING: multiple messages have this Message-ID (diff)
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Greg Kurz <gkurz@linux.vnet.ibm.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>,
linux-api@vger.kernel.org, linux-kernel@vger.kernel.org,
kvm@vger.kernel.org, virtualization@lists.linux-foundation.org
Subject: Re: [PATCH v2 7/7] vhost: feature to set the vring endianness
Date: Thu, 2 Apr 2015 16:20:46 +0200 [thread overview]
Message-ID: <20150402142046.GA23121@redhat.com> (raw)
In-Reply-To: <20150402131713.24676.9924.stgit@bahia.lab.toulouse-stg.fr.ibm.com>
On Thu, Apr 02, 2015 at 03:17:13PM +0200, Greg Kurz wrote:
> This patch brings cross-endian support to vhost when used to implement
> legacy virtio devices. Since it is a relatively rare situation, the feature
> availability is controlled by a kernel config option (not set by default).
>
> If cross-endian support is compiled in, vhost abvertises a new feature
> to be negotiated with userspace. If userspace acknowledges the feature,
> it can inform vhost about the endianness to use with a new ioctl.
>
> This feature is mutually exclusive with virtio 1.0. Even if the vhost device
> advertises virtio 1.0 and legacy cross-endian features, it cannot receive
> aknowledgement for both at the same time.
>
> Hot paths are being preserved from any penalty when the config option is
> disabled or when virtio 1.0 is being used.
>
> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> ---
> drivers/vhost/Kconfig | 10 ++++++++++
> drivers/vhost/net.c | 5 +++++
> drivers/vhost/scsi.c | 4 ++++
> drivers/vhost/test.c | 4 ++++
> drivers/vhost/vhost.c | 19 +++++++++++++++++++
> drivers/vhost/vhost.h | 13 ++++++++++++-
> include/uapi/linux/vhost.h | 10 ++++++++++
> 7 files changed, 64 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
> index 017a1e8..5bb8da9 100644
> --- a/drivers/vhost/Kconfig
> +++ b/drivers/vhost/Kconfig
> @@ -32,3 +32,13 @@ config VHOST
> ---help---
> This option is selected by any driver which needs to access
> the core of vhost.
> +
> +config VHOST_SET_ENDIAN_LEGACY
> + bool "Cross-endian support for host kernel accelerator"
> + default n
> + ---help---
> + This option allows vhost to support guests with a different byte
> + ordering
from host
>. It is disabled by default since it adds overhead and it
> + is only needed by a few platforms (powerpc and arm).
> +
> + If unsure, say "n".
"N"
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 2bbfc25..5274a44 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -1011,6 +1011,11 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features)
> vhost_hlen = 0;
> sock_hlen = hdr_len;
> }
> +
> + if (features & ((1ULL << VHOST_F_SET_ENDIAN_LEGACY) |
> + (1ULL << VIRTIO_F_VERSION_1)))
> + return -EINVAL;
> +
> mutex_lock(&n->dev.mutex);
> if ((features & (1 << VHOST_F_LOG_ALL)) &&
> !vhost_log_access_ok(&n->dev)) {
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index 71df240..b53e9c2 100644
> --- a/drivers/vhost/scsi.c
> +++ b/drivers/vhost/scsi.c
> @@ -1544,6 +1544,10 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
> if (features & ~VHOST_SCSI_FEATURES)
> return -EOPNOTSUPP;
>
> + if (features & ((1ULL << VHOST_F_SET_ENDIAN_LEGACY) |
> + (1ULL << VIRTIO_F_VERSION_1)))
> + return -EINVAL;
> +
> mutex_lock(&vs->dev.mutex);
> if ((features & (1 << VHOST_F_LOG_ALL)) &&
> !vhost_log_access_ok(&vs->dev)) {
> diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
> index d9c501e..cfefdad 100644
> --- a/drivers/vhost/test.c
> +++ b/drivers/vhost/test.c
> @@ -243,6 +243,10 @@ static int vhost_test_set_features(struct vhost_test *n, u64 features)
> {
> struct vhost_virtqueue *vq;
>
> + if (features & ((1ULL << VHOST_F_SET_ENDIAN_LEGACY) |
> + (1ULL << VIRTIO_F_VERSION_1)))
> + return -EINVAL;
> +
> mutex_lock(&n->dev.mutex);
> if ((features & (1 << VHOST_F_LOG_ALL)) &&
> !vhost_log_access_ok(&n->dev)) {
Above seems to prevent users from specifying either
VIRTIO_F_VERSION_1 or VHOST_F_SET_ENDIAN_LEGACY.
Does it actually work?
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 2ee2826..60a0f32 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -199,6 +199,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
> vq->call = NULL;
> vq->log_ctx = NULL;
> vq->memory = NULL;
> + vq->legacy_big_endian = false;
> }
>
> static int vhost_worker(void *data)
> @@ -806,6 +807,24 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
> } else
> filep = eventfp;
> break;
> +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> + case VHOST_SET_VRING_ENDIAN_LEGACY:
> + {
> + struct vhost_vring_endian e;
> +
> + if (!vhost_has_feature(vq, VHOST_F_SET_ENDIAN_LEGACY)) {
> + r = -EINVAL;
> + break;
> + }
> +
> + if (copy_from_user(&e, argp, sizeof(e))) {
> + r = -EFAULT;
> + break;
> + }
> + vq->legacy_big_endian = e.is_big_endian;
> + break;
> + }
> +#endif
> default:
> r = -ENOIOCTLCMD;
> }
> diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
> index 4e9a186..d50881d 100644
> --- a/drivers/vhost/vhost.h
> +++ b/drivers/vhost/vhost.h
> @@ -106,6 +106,9 @@ struct vhost_virtqueue {
> /* Log write descriptors */
> void __user *log_base;
> struct vhost_log *log;
> +
> + /* We need to know the device endianness with legacy virtio. */
> + bool legacy_big_endian;
> };
>
> struct vhost_dev {
> @@ -165,7 +168,11 @@ enum {
> VHOST_FEATURES = (1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) |
> (1ULL << VIRTIO_RING_F_INDIRECT_DESC) |
> (1ULL << VIRTIO_RING_F_EVENT_IDX) |
> - (1ULL << VHOST_F_LOG_ALL),
> + (1ULL << VHOST_F_LOG_ALL) |
> +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> + (1ULL << VHOST_F_SET_ENDIAN_LEGACY) |
> +#endif
> + 0ULL,
> };
>
> static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
> @@ -177,6 +184,10 @@ static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
> {
> if (vhost_has_feature(vq, VIRTIO_F_VERSION_1))
> return true;
> +#ifdef CONFIG_VHOST_SET_ENDIAN_LEGACY
> + if (vhost_has_feature(vq, VHOST_F_SET_ENDIAN_LEGACY))
> + return !vq->legacy_big_endian;
why do we need to check the feature bit?
How about simple
return !vq->legacy_big_endian;
here?
All you need to do is set legacy_big_endian to
!virtio_legacy_is_little_endian() on reset.
Maybe rename to legacy_is_little_endian so you don't
need to reverse the logic.
> +#endif
> return virtio_legacy_is_little_endian();
> }
>
> diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> index bb6a5b4..09d2a48 100644
> --- a/include/uapi/linux/vhost.h
> +++ b/include/uapi/linux/vhost.h
> @@ -47,6 +47,11 @@ struct vhost_vring_addr {
> __u64 log_guest_addr;
> };
>
> +struct vhost_vring_endian {
> + unsigned int index;
> + bool is_big_endian;
bool in uapi is a bad idea.
Generally, I think you can use vhost_vring_state here.
> +};
> +
> struct vhost_memory_region {
> __u64 guest_phys_addr;
> __u64 memory_size; /* bytes */
> @@ -103,6 +108,9 @@ struct vhost_memory {
> /* Get accessor: reads index, writes value in num */
> #define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
>
> +/* Set endianness for the ring (legacy virtio only) */
> +#define VHOST_SET_VRING_ENDIAN_LEGACY _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_endian)
> +
> /* The following ioctls use eventfd file descriptors to signal and poll
> * for events. */
>
You also need a GET ioctl, as a matter of policy.
> @@ -126,6 +134,8 @@ struct vhost_memory {
> #define VHOST_F_LOG_ALL 26
> /* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
> #define VHOST_NET_F_VIRTIO_NET_HDR 27
> +/* the vring endianness can be explicitly set (legacy virtio only). */
> +#define VHOST_F_SET_ENDIAN_LEGACY 28
>
> /* VHOST_SCSI specific definitions */
VHOST_F_SET_ENDIAN_LEGACY doesn't seem too useful.
Is this so userspace can detect kernel configuration?
I think probing VHOST_SET_VRING_ENDIAN_LEGACY should
be sufficient for this.
--
MST
next prev parent reply other threads:[~2015-04-02 14:20 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-04-02 13:16 [PATCH v2 0/7] vhost: support for cross endian guests Greg Kurz
2015-04-02 13:16 ` [PATCH v2 1/7] virtio: introduce virtio_is_little_endian() helper Greg Kurz
2015-04-02 13:16 ` Greg Kurz
2015-04-02 13:16 ` [PATCH v2 2/7] tun: add tun_is_little_endian() helper Greg Kurz
2015-04-02 13:16 ` [PATCH v2 3/7] macvtap: introduce macvtap_is_little_endian() helper Greg Kurz
2015-04-02 13:16 ` [PATCH v2 4/7] vringh: introduce vringh_is_little_endian() helper Greg Kurz
2015-04-02 13:17 ` [PATCH v2 5/7] vhost: introduce vhost_is_little_endian() helper Greg Kurz
2015-04-02 13:17 ` [PATCH v2 6/7] virtio: add explicit big-endian support to memory accessors Greg Kurz
2015-04-02 13:17 ` Greg Kurz
2015-04-02 13:17 ` [PATCH v2 7/7] vhost: feature to set the vring endianness Greg Kurz
[not found] ` <20150402131637.24676.60700.stgit-to6p26YowclJmDnNpxttO7KMsZMIf1jtdfLczzV0R5oAvxtiuMwx3w@public.gmane.org>
2015-04-02 13:17 ` Greg Kurz
2015-04-02 13:17 ` Greg Kurz
2015-04-02 14:20 ` Michael S. Tsirkin [this message]
2015-04-02 14:20 ` Michael S. Tsirkin
2015-04-02 16:45 ` Greg Kurz
2015-04-02 16:45 ` Greg Kurz
2015-04-02 18:53 ` Michael S. Tsirkin
2015-04-02 18:53 ` Michael S. Tsirkin
2015-04-02 14:23 ` [PATCH v2 0/7] vhost: support for cross endian guests Michael S. Tsirkin
2015-04-02 14:23 ` Michael S. Tsirkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150402142046.GA23121@redhat.com \
--to=mst@redhat.com \
--cc=gkurz@linux.vnet.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=virtualization@lists.linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.