aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Brucker <jean-philippe@linaro.org>2023-06-06 14:04:18 +0100
committerWill Deacon <will@kernel.org>2023-06-08 22:39:03 +0100
commit13ea439a1f48a19cc31e5c39abb8079aa8deedef (patch)
tree08903e662473bcb1c0253647e763e44089d2f710
parentb8420e8d5d8dd74c7efd86d4ed7df724127fe184 (diff)
downloadkvmtool-13ea439a1f48a19cc31e5c39abb8079aa8deedef.tar.gz
virtio/scsi: Fix feature selection
We should advertise to the guest only the features supported by vhost and kvmtool. Then we should set in vhost only the features acked by the guest. Move vhost feature query to get_host_features(), and vhost feature setting to device start (after the guest has acked features). This fixes scsi because we used to enable all vhost features including VIRTIO_SCSI_F_T10_PI which changes the request layout and caused inconsistency between guest and vhost. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Link: https://lore.kernel.org/r/20230606130426.978945-10-jean-philippe@linaro.org Signed-off-by: Will Deacon <will@kernel.org>
-rw-r--r--virtio/scsi.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/virtio/scsi.c b/virtio/scsi.c
index 4d1ed9b8..50f184c7 100644
--- a/virtio/scsi.c
+++ b/virtio/scsi.c
@@ -46,19 +46,35 @@ static size_t get_config_size(struct kvm *kvm, void *dev)
static u64 get_host_features(struct kvm *kvm, void *dev)
{
- return 1UL << VIRTIO_RING_F_EVENT_IDX |
- 1UL << VIRTIO_RING_F_INDIRECT_DESC;
+ int r;
+ u64 features;
+ struct scsi_dev *sdev = dev;
+
+ r = ioctl(sdev->vhost_fd, VHOST_GET_FEATURES, &features);
+ if (r != 0)
+ die_perror("VHOST_GET_FEATURES failed");
+
+ return features &
+ (1ULL << VIRTIO_RING_F_EVENT_IDX | \
+ 1ULL << VIRTIO_RING_F_INDIRECT_DESC | \
+ 1ULL << VIRTIO_F_ANY_LAYOUT);
}
static void notify_status(struct kvm *kvm, void *dev, u32 status)
{
+ int r;
struct scsi_dev *sdev = dev;
struct virtio_device *vdev = &sdev->vdev;
struct virtio_scsi_config *conf = &sdev->config;
u16 endian = vdev->endian;
if (status & VIRTIO__STATUS_START) {
- int r = ioctl(sdev->vhost_fd, VHOST_SCSI_SET_ENDPOINT,
+ r = ioctl(sdev->vhost_fd, VHOST_SET_FEATURES,
+ &sdev->vdev.features);
+ if (r != 0)
+ die_perror("VHOST_SET_FEATURES failed");
+
+ r = ioctl(sdev->vhost_fd, VHOST_SCSI_SET_ENDPOINT,
&sdev->target);
if (r != 0)
die("VHOST_SCSI_SET_ENDPOINT failed %d", errno);
@@ -161,23 +177,12 @@ static struct virtio_ops scsi_dev_virtio_ops = {
static void virtio_scsi_vhost_init(struct kvm *kvm, struct scsi_dev *sdev)
{
- u64 features;
- int r;
-
sdev->vhost_fd = open("/dev/vhost-scsi", O_RDWR);
if (sdev->vhost_fd < 0)
die_perror("Failed openning vhost-scsi device");
virtio_vhost_init(kvm, sdev->vhost_fd);
- r = ioctl(sdev->vhost_fd, VHOST_GET_FEATURES, &features);
- if (r != 0)
- die_perror("VHOST_GET_FEATURES failed");
-
- r = ioctl(sdev->vhost_fd, VHOST_SET_FEATURES, &features);
- if (r != 0)
- die_perror("VHOST_SET_FEATURES failed");
-
sdev->vdev.use_vhost = true;
}