@@ -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);
@@ -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);
@@ -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");
@@ -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);
+}
@@ -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) {
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@linaro.org> --- 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(-)