qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Kevin Wolf" <kwolf@redhat.com>,
	"Laurent Vivier" <lvivier@redhat.com>,
	"Thomas Huth" <thuth@redhat.com>,
	"Eduardo Habkost" <ehabkost@redhat.com>,
	qemu-block@nongnu.org, "Michael S. Tsirkin" <mst@redhat.com>,
	jasowang@redhat.com, cohuck@redhat.com,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	"Raphael Norwitz" <raphael.norwitz@nutanix.com>,
	"Gonglei (Arei)" <arei.gonglei@huawei.com>,
	"Gerd Hoffmann" <kraxel@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Fam Zheng" <fam@euphon.net>, "Max Reitz" <mreitz@redhat.com>
Subject: [PATCH 2/5] vhost: involve device backends in feature negotiation
Date: Fri, 22 May 2020 18:17:23 +0100	[thread overview]
Message-ID: <20200522171726.648279-3-stefanha@redhat.com> (raw)
In-Reply-To: <20200522171726.648279-1-stefanha@redhat.com>

Many vhost devices in QEMU currently do not involve the device backend
in feature negotiation. This seems fine at first glance for device types
without their own feature bits (virtio-net has many but other device
types have none).

This overlooks the fact that QEMU's virtqueue implementation and the
device backend's implementation may support different features.  QEMU
must not report features to the guest that the the device backend
doesn't support.

For example, QEMU supports VIRTIO 1.1 packed virtqueues while many
existing vhost device backends do not. When the user sets packed=on the
device backend breaks. This should have been handled gracefully by
feature negotiation instead.

Introduce vhost_get_default_features() and update all vhost devices in
QEMU to involve the device backend in feature negotiation.

This patch fixes the following error:

  $ x86_64-softmmu/qemu-system-x86_64 \
      -drive if=virtio,file=test.img,format=raw \
      -chardev socket,path=/tmp/vhost-user-blk.sock,id=char0 \
      -device vhost-user-blk-pci,chardev=char0,packed=on \
      -object memory-backend-memfd,size=1G,share=on,id=ram0 \
      -M accel=kvm,memory-backend=ram0
  qemu-system-x86_64: Failed to set msg fds.
  qemu-system-x86_64: vhost VQ 0 ring restore failed: -1: Success (0)

The vhost-user-blk backend failed as follows:

  $ ./vhost-user-blk --socket-path=/tmp/vhost-user-blk.sock -b test2.img
  vu_panic: virtio: zero sized buffers are not allowed
  virtio-blk request missing headers

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/hw/virtio/vhost.h        |  1 +
 include/hw/virtio/virtio-gpu.h   |  2 ++
 include/sysemu/cryptodev-vhost.h | 11 +++++++++++
 backends/cryptodev-vhost.c       | 19 +++++++++++++++++++
 hw/display/vhost-user-gpu.c      | 17 +++++++++++++++++
 hw/display/virtio-gpu-base.c     |  2 +-
 hw/input/vhost-user-input.c      |  9 +++++++++
 hw/virtio/vhost-user-fs.c        |  5 +++--
 hw/virtio/vhost-vsock.c          |  5 +++--
 hw/virtio/vhost.c                | 22 ++++++++++++++++++++++
 hw/virtio/virtio-crypto.c        |  3 ++-
 11 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 085450c6f8..d2e54dd4a8 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -112,6 +112,7 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
                           bool mask);
 uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
                             uint64_t features);
+uint64_t vhost_get_default_features(struct vhost_dev *hdev, uint64_t features);
 void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
                         uint64_t features);
 bool vhost_has_free_slot(void);
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 6dd57f2025..41d270d80e 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -192,6 +192,8 @@ bool virtio_gpu_base_device_realize(DeviceState *qdev,
 void virtio_gpu_base_reset(VirtIOGPUBase *g);
 void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g,
                         struct virtio_gpu_resp_display_info *dpy_info);
+uint64_t virtio_gpu_base_get_features(VirtIODevice *vdev, uint64_t features,
+                                      Error **errp);
 
 /* virtio-gpu.c */
 void virtio_gpu_ctrl_response(VirtIOGPU *g,
diff --git a/include/sysemu/cryptodev-vhost.h b/include/sysemu/cryptodev-vhost.h
index f42824fbde..e629446bfb 100644
--- a/include/sysemu/cryptodev-vhost.h
+++ b/include/sysemu/cryptodev-vhost.h
@@ -122,6 +122,17 @@ int cryptodev_vhost_start(VirtIODevice *dev, int total_queues);
  */
 void cryptodev_vhost_stop(VirtIODevice *dev, int total_queues);
 
+/**
+ * cryptodev_vhost_get_features:
+ * @dev: the virtio crypto object
+ * @requested_features: the features being offered
+ *
+ * Returns: the requested features bits that are supported by the vhost device,
+ * or the original request feature bits if vhost is disabled
+ *
+ */
+uint64_t cryptodev_vhost_get_features(VirtIODevice *dev, uint64_t features);
+
 /**
  * cryptodev_vhost_virtqueue_mask:
  * @dev: the virtio crypto object
diff --git a/backends/cryptodev-vhost.c b/backends/cryptodev-vhost.c
index 8337c9a495..5f5a4fda7b 100644
--- a/backends/cryptodev-vhost.c
+++ b/backends/cryptodev-vhost.c
@@ -266,6 +266,20 @@ void cryptodev_vhost_stop(VirtIODevice *dev, int total_queues)
     assert(r >= 0);
 }
 
+uint64_t cryptodev_vhost_get_features(VirtIODevice *dev, uint64_t features)
+{
+    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
+    CryptoDevBackend *b = vcrypto->cryptodev;
+    CryptoDevBackendClient *cc = b->conf.peers.ccs[0];
+    CryptoDevBackendVhost *vhost_crypto = cryptodev_get_vhost(cc, b, 0);
+
+    if (!vhost_crypto) {
+        return features; /* vhost disabled */
+    }
+
+    return vhost_get_default_features(&vhost_crypto->dev, features);
+}
+
 void cryptodev_vhost_virtqueue_mask(VirtIODevice *dev,
                                            int queue,
                                            int idx, bool mask)
@@ -333,6 +347,11 @@ void cryptodev_vhost_stop(VirtIODevice *dev, int total_queues)
 {
 }
 
+uint64_t cryptodev_vhost_get_features(VirtIODevice *dev, uint64_t features)
+{
+    return features;
+}
+
 void cryptodev_vhost_virtqueue_mask(VirtIODevice *dev,
                                     int queue,
                                     int idx, bool mask)
diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index 4cdaee1bde..e483df2a9e 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -466,6 +466,22 @@ vhost_user_gpu_set_config(VirtIODevice *vdev,
     }
 }
 
+static uint64_t
+vhost_user_gpu_get_features(VirtIODevice *vdev, uint64_t features,
+                            Error **errp)
+{
+    VhostUserGPU *g = VHOST_USER_GPU(vdev);
+    Error *local_err = NULL;
+
+    features = virtio_gpu_base_get_features(vdev, features, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return 0;
+    }
+
+    return vhost_get_default_features(&g->vhost->dev, features);
+}
+
 static void
 vhost_user_gpu_set_status(VirtIODevice *vdev, uint8_t val)
 {
@@ -582,6 +598,7 @@ vhost_user_gpu_class_init(ObjectClass *klass, void *data)
 
     vdc->realize = vhost_user_gpu_device_realize;
     vdc->reset = vhost_user_gpu_reset;
+    vdc->get_features = vhost_user_gpu_get_features;
     vdc->set_status   = vhost_user_gpu_set_status;
     vdc->guest_notifier_mask = vhost_user_gpu_guest_notifier_mask;
     vdc->guest_notifier_pending = vhost_user_gpu_guest_notifier_pending;
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index c159351be3..05d1ff2db2 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -176,7 +176,7 @@ virtio_gpu_base_device_realize(DeviceState *qdev,
     return true;
 }
 
-static uint64_t
+uint64_t
 virtio_gpu_base_get_features(VirtIODevice *vdev, uint64_t features,
                              Error **errp)
 {
diff --git a/hw/input/vhost-user-input.c b/hw/input/vhost-user-input.c
index 63984a8ba7..1371fb32cc 100644
--- a/hw/input/vhost-user-input.c
+++ b/hw/input/vhost-user-input.c
@@ -45,6 +45,14 @@ static void vhost_input_change_active(VirtIOInput *vinput)
     }
 }
 
+static uint64_t vhost_input_get_features(VirtIODevice *vdev, uint64_t features,
+                                         Error **errp)
+{
+    VHostUserInput *vhi = VHOST_USER_INPUT(vdev);
+
+    return vhost_get_default_features(&vhi->vhost->dev, features);
+}
+
 static void vhost_input_get_config(VirtIODevice *vdev, uint8_t *config_data)
 {
     VirtIOInput *vinput = VIRTIO_INPUT(vdev);
@@ -89,6 +97,7 @@ static void vhost_input_class_init(ObjectClass *klass, void *data)
     DeviceClass *dc = DEVICE_CLASS(klass);
 
     dc->vmsd = &vmstate_vhost_input;
+    vdc->get_features = vhost_input_get_features;
     vdc->get_config = vhost_input_get_config;
     vdc->set_config = vhost_input_set_config;
     vic->realize = vhost_input_realize;
diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c
index 1bc5d03a00..56015ca3d4 100644
--- a/hw/virtio/vhost-user-fs.c
+++ b/hw/virtio/vhost-user-fs.c
@@ -130,8 +130,9 @@ static uint64_t vuf_get_features(VirtIODevice *vdev,
                                       uint64_t requested_features,
                                       Error **errp)
 {
-    /* No feature bits used yet */
-    return requested_features;
+    VHostUserFS *fs = VHOST_USER_FS(vdev);
+
+    return vhost_get_default_features(&fs->vhost_dev, requested_features);
 }
 
 static void vuf_handle_output(VirtIODevice *vdev, VirtQueue *vq)
diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c
index 4a228f5168..7276587be6 100644
--- a/hw/virtio/vhost-vsock.c
+++ b/hw/virtio/vhost-vsock.c
@@ -180,8 +180,9 @@ static uint64_t vhost_vsock_get_features(VirtIODevice *vdev,
                                          uint64_t requested_features,
                                          Error **errp)
 {
-    /* No feature bits used yet */
-    return requested_features;
+    VHostVSock *vsock = VHOST_VSOCK(vdev);
+
+    return vhost_get_default_features(&vsock->vhost_dev, requested_features);
 }
 
 static void vhost_vsock_handle_output(VirtIODevice *vdev, VirtQueue *vq)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index aff98a0ede..f8a144dcd0 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -48,6 +48,23 @@ static unsigned int used_memslots;
 static QLIST_HEAD(, vhost_dev) vhost_devices =
     QLIST_HEAD_INITIALIZER(vhost_devices);
 
+/*
+ * Feature bits that device backends must explicitly report. Feature bits not
+ * listed here maybe set by QEMU without checking with the device backend.
+ * Ideally all feature bits would be listed here but existing vhost device
+ * implementations do not explicitly report bits like VIRTIO_F_VERSION_1, so we
+ * can only assume they are supported.
+ *
+ * New feature bits added to the VIRTIO spec should usually be included here
+ * so that existing vhost device backends that do not support them yet continue
+ * to work.
+ */
+static const int vhost_default_feature_bits[] = {
+    VIRTIO_F_IOMMU_PLATFORM,
+    VIRTIO_F_RING_PACKED,
+    VHOST_INVALID_FEATURE_BIT
+};
+
 bool vhost_has_free_slot(void)
 {
     unsigned int slots_limit = ~0U;
@@ -1468,6 +1485,11 @@ uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
     return features;
 }
 
+uint64_t vhost_get_default_features(struct vhost_dev *hdev, uint64_t features)
+{
+    return vhost_get_features(hdev, vhost_default_feature_bits, features);
+}
+
 void vhost_ack_features(struct vhost_dev *hdev, const int *feature_bits,
                         uint64_t features)
 {
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index bd9165c565..ef711b56f4 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -739,7 +739,8 @@ static uint64_t virtio_crypto_get_features(VirtIODevice *vdev,
                                            uint64_t features,
                                            Error **errp)
 {
-    return features;
+    /* Just returns features when vhost is disabled */
+    return cryptodev_vhost_get_features(vdev, features);
 }
 
 static void virtio_crypto_reset(VirtIODevice *vdev)
-- 
2.25.3


  parent reply	other threads:[~2020-05-22 17:18 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-22 17:17 [PATCH 0/5] virtio: enable VIRTIO_F_RING_PACKED for all devices Stefan Hajnoczi
2020-05-22 17:17 ` [PATCH 1/5] tests/libqos: mask out VIRTIO_F_RING_PACKED for now Stefan Hajnoczi
2020-05-22 19:21   ` Thomas Huth
2020-05-22 17:17 ` Stefan Hajnoczi [this message]
2020-05-27 14:28   ` [PATCH 2/5] vhost: involve device backends in feature negotiation Marc-André Lureau
2020-05-29 15:20     ` Stefan Hajnoczi
2020-05-29  7:04   ` Jason Wang
2020-05-29 13:56     ` Stefan Hajnoczi
2020-05-29 14:29       ` Dr. David Alan Gilbert
2020-06-03 14:44         ` Stefan Hajnoczi
2020-06-01 12:51       ` Jason Wang
2020-06-03 14:39         ` Stefan Hajnoczi
2020-05-22 17:17 ` [PATCH 3/5] vhost-user-blk: add VIRTIO_F_RING_PACKED feature bit Stefan Hajnoczi
2020-05-25  4:06   ` Raphael Norwitz
2020-05-22 17:17 ` [PATCH 4/5] vhost-scsi: add VIRTIO_F_VERSION_1 and VIRTIO_F_RING_PACKED Stefan Hajnoczi
2020-05-25  4:02   ` Raphael Norwitz
2020-05-22 17:17 ` [PATCH 5/5] virtio: enable VIRTIO_F_RING_PACKED for all devices Stefan Hajnoczi
2020-05-26 17:29   ` Dr. David Alan Gilbert
2020-05-29  7:15   ` Jason Wang
2020-05-29 15:28     ` Stefan Hajnoczi

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=20200522171726.648279-3-stefanha@redhat.com \
    --to=stefanha@redhat.com \
    --cc=arei.gonglei@huawei.com \
    --cc=cohuck@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=fam@euphon.net \
    --cc=jasowang@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=lvivier@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=raphael.norwitz@nutanix.com \
    --cc=thuth@redhat.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).