diff options
Diffstat (limited to 'hw/virtio/vhost-backend.c')
-rw-r--r-- | hw/virtio/vhost-backend.c | 86 |
1 files changed, 70 insertions, 16 deletions
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index 782b1d6..88c8ecc 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -156,6 +156,28 @@ static int vhost_kernel_set_features(struct vhost_dev *dev, return vhost_kernel_call(dev, VHOST_SET_FEATURES, &features); } +static int vhost_kernel_set_backend_cap(struct vhost_dev *dev) +{ + uint64_t features; + uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2; + int r; + + if (vhost_kernel_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) { + return 0; + } + + features &= f; + r = vhost_kernel_call(dev, VHOST_SET_BACKEND_FEATURES, + &features); + if (r) { + return 0; + } + + dev->backend_cap = features; + + return 0; +} + static int vhost_kernel_get_features(struct vhost_dev *dev, uint64_t *features) { @@ -195,34 +217,65 @@ static int vhost_kernel_vsock_set_running(struct vhost_dev *dev, int start) static void vhost_kernel_iotlb_read(void *opaque) { struct vhost_dev *dev = opaque; - struct vhost_msg msg; ssize_t len; - while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) { - if (len < sizeof msg) { - error_report("Wrong vhost message len: %d", (int)len); - break; + if (dev->backend_cap & + (0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)) { + struct vhost_msg_v2 msg; + + while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) { + if (len < sizeof msg) { + error_report("Wrong vhost message len: %d", (int)len); + break; + } + if (msg.type != VHOST_IOTLB_MSG_V2) { + error_report("Unknown vhost iotlb message type"); + break; + } + + vhost_backend_handle_iotlb_msg(dev, &msg.iotlb); } - if (msg.type != VHOST_IOTLB_MSG) { - error_report("Unknown vhost iotlb message type"); - break; + } else { + struct vhost_msg msg; + + while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) { + if (len < sizeof msg) { + error_report("Wrong vhost message len: %d", (int)len); + break; + } + if (msg.type != VHOST_IOTLB_MSG) { + error_report("Unknown vhost iotlb message type"); + break; + } + + vhost_backend_handle_iotlb_msg(dev, &msg.iotlb); } - - vhost_backend_handle_iotlb_msg(dev, &msg.iotlb); } } static int vhost_kernel_send_device_iotlb_msg(struct vhost_dev *dev, struct vhost_iotlb_msg *imsg) { - struct vhost_msg msg; + if (dev->backend_cap & (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)) { + struct vhost_msg_v2 msg; - msg.type = VHOST_IOTLB_MSG; - msg.iotlb = *imsg; + msg.type = VHOST_IOTLB_MSG_V2; + msg.iotlb = *imsg; - if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) { - error_report("Fail to update device iotlb"); - return -EFAULT; + if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) { + error_report("Fail to update device iotlb"); + return -EFAULT; + } + } else { + struct vhost_msg msg; + + msg.type = VHOST_IOTLB_MSG; + msg.iotlb = *imsg; + + if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) { + error_report("Fail to update device iotlb"); + return -EFAULT; + } } return 0; @@ -260,6 +313,7 @@ static const VhostOps kernel_ops = { vhost_kernel_set_vring_busyloop_timeout, .vhost_set_features = vhost_kernel_set_features, .vhost_get_features = vhost_kernel_get_features, + .vhost_set_backend_cap = vhost_kernel_set_backend_cap, .vhost_set_owner = vhost_kernel_set_owner, .vhost_reset_device = vhost_kernel_reset_device, .vhost_get_vq_index = vhost_kernel_get_vq_index, |