Vhost interprets the VIRTIO_F_ACCESS_PLATFORM flag as if accesses need to use vhost-iotlb, and since kvmtool does not implement vhost-iotlb, vhost will fail to access the virtqueue. This fix is preventive. Kvmtool does not set VIRTIO_F_ACCESS_PLATFORM at the moment but the Arm CCA and pKVM changes will likely hit the issue (as experienced with the CCA development tree), so we might as well fix it now. Signed-off-by: Jean-Philippe Brucker <jean-philippe@xxxxxxxxxx> --- include/kvm/virtio.h | 1 + virtio/net.c | 16 +++++----------- virtio/scsi.c | 3 +-- virtio/vhost.c | 11 +++++++++++ virtio/vsock.c | 4 ++-- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/include/kvm/virtio.h b/include/kvm/virtio.h index 1fa33e5b..95b5142b 100644 --- a/include/kvm/virtio.h +++ b/include/kvm/virtio.h @@ -273,6 +273,7 @@ void virtio_vhost_set_vring_irqfd(struct kvm *kvm, u32 gsi, struct virt_queue *queue); void virtio_vhost_reset_vring(struct kvm *kvm, int vhost_fd, u32 index, struct virt_queue *queue); +int virtio_vhost_set_features(int vhost_fd, u64 features); int virtio_transport_parser(const struct option *opt, const char *arg, int unset); diff --git a/virtio/net.c b/virtio/net.c index 2b4b3661..f09dd0a4 100644 --- a/virtio/net.c +++ b/virtio/net.c @@ -517,23 +517,17 @@ static u64 get_host_features(struct kvm *kvm, void *dev) return features; } -static int virtio_net__vhost_set_features(struct net_dev *ndev) -{ - /* VHOST_NET_F_VIRTIO_NET_HDR clashes with VIRTIO_F_ANY_LAYOUT! */ - u64 features = ndev->vdev.features & - ~(1UL << VHOST_NET_F_VIRTIO_NET_HDR); - - return ioctl(ndev->vhost_fd, VHOST_SET_FEATURES, &features); -} - static void virtio_net_start(struct net_dev *ndev) { + /* VHOST_NET_F_VIRTIO_NET_HDR clashes with VIRTIO_F_ANY_LAYOUT! */ + u64 features = ndev->vdev.features & ~(1UL << VHOST_NET_F_VIRTIO_NET_HDR); + if (ndev->mode == NET_MODE_TAP) { if (!virtio_net__tap_init(ndev)) die_perror("TAP device initialized failed because"); - if (ndev->vhost_fd && - virtio_net__vhost_set_features(ndev) != 0) + if (ndev->vhost_fd && virtio_vhost_set_features(ndev->vhost_fd, + features)) die_perror("VHOST_SET_FEATURES failed"); } else { ndev->info.vnet_hdr_len = virtio_net_hdr_len(ndev); diff --git a/virtio/scsi.c b/virtio/scsi.c index 27cb3798..a842290b 100644 --- a/virtio/scsi.c +++ b/virtio/scsi.c @@ -69,8 +69,7 @@ static void notify_status(struct kvm *kvm, void *dev, u32 status) u16 endian = vdev->endian; if (status & VIRTIO__STATUS_START) { - r = ioctl(sdev->vhost_fd, VHOST_SET_FEATURES, - &sdev->vdev.features); + r = virtio_vhost_set_features(sdev->vhost_fd, sdev->vdev.features); if (r != 0) die_perror("VHOST_SET_FEATURES failed"); diff --git a/virtio/vhost.c b/virtio/vhost.c index 0049003b..ea640fa6 100644 --- a/virtio/vhost.c +++ b/virtio/vhost.c @@ -196,3 +196,14 @@ void virtio_vhost_reset_vring(struct kvm *kvm, int vhost_fd, u32 index, close(queue->irqfd); queue->irqfd = 0; } + +int virtio_vhost_set_features(int vhost_fd, u64 features) +{ + /* + * vhost interprets VIRTIO_F_ACCESS_PLATFORM as meaning there is an + * iotlb. Since this is not the case for kvmtool, mask it. + */ + u64 masked_feat = features & ~(1ULL << VIRTIO_F_ACCESS_PLATFORM); + + return ioctl(vhost_fd, VHOST_SET_FEATURES, &masked_feat); +} diff --git a/virtio/vsock.c b/virtio/vsock.c index 5d22bd24..7d4053a1 100644 --- a/virtio/vsock.c +++ b/virtio/vsock.c @@ -107,8 +107,8 @@ static void notify_status(struct kvm *kvm, void *dev, u32 status) if (status & VIRTIO__STATUS_START) { start = 1; - r = ioctl(vdev->vhost_fd, VHOST_SET_FEATURES, - &vdev->vdev.features); + r = virtio_vhost_set_features(vdev->vhost_fd, + vdev->vdev.features); if (r != 0) die_perror("VHOST_SET_FEATURES failed"); } else if (status & VIRTIO__STATUS_STOP) { -- 2.40.1