diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index aedc52c4d7..dbf2643ff7 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -78,6 +78,46 @@ static int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, return ret; } +static void vhost_vdpa_listener_begin(MemoryListener *listener) +{ + struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); + struct vhost_dev *dev = v->dev; + struct vhost_msg_v2 msg; + int fd = v->device_fd; + + if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) { + return; + } + + msg.type = v->msg_type; + msg.iotlb.type = VHOST_IOTLB_BATCH_BEGIN; + + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", + fd, errno, strerror(errno)); + } +} + +static void vhost_vdpa_listener_commit(MemoryListener *listener) +{ + struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); + struct vhost_dev *dev = v->dev; + struct vhost_msg_v2 msg; + int fd = v->device_fd; + + if (!(dev->backend_cap & (0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) { + return; + } + + msg.type = v->msg_type; + msg.iotlb.type = VHOST_IOTLB_BATCH_END; + + if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { + error_report("failed to write, fd=%d, errno=%d (%s)", + fd, errno, strerror(errno)); + } +} + static void vhost_vdpa_listener_region_add(MemoryListener *listener, MemoryRegionSection *section) { @@ -188,6 +228,8 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, * depends on the addnop(). */ static const MemoryListener vhost_vdpa_memory_listener = { + .begin = vhost_vdpa_listener_begin, + .commit = vhost_vdpa_listener_commit, .region_add = vhost_vdpa_listener_region_add, .region_del = vhost_vdpa_listener_region_del, }; @@ -223,6 +265,7 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque) assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); v = opaque; + v->dev = dev; dev->opaque = opaque ; vhost_vdpa_call(dev, VHOST_GET_FEATURES, &features); dev->backend_features = features; @@ -277,6 +320,28 @@ static int vhost_vdpa_set_features(struct vhost_dev *dev, return !(status & VIRTIO_CONFIG_S_FEATURES_OK); } +static int vhost_vdpa_set_backend_cap(struct vhost_dev *dev) +{ + uint64_t features; + uint64_t f = 0x1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2 | + 0x1ULL << VHOST_BACKEND_F_IOTLB_BATCH; + int r; + + if (vhost_vdpa_call(dev, VHOST_GET_BACKEND_FEATURES, &features)) { + return 0; + } + + features &= f; + r = vhost_vdpa_call(dev, VHOST_SET_BACKEND_FEATURES, &features); + if (r) { + return 0; + } + + dev->backend_cap = features; + + return 0; +} + int vhost_vdpa_get_device_id(struct vhost_dev *dev, uint32_t *device_id) { @@ -444,6 +509,7 @@ const VhostOps vdpa_ops = { .vhost_set_vring_kick = vhost_vdpa_set_vring_kick, .vhost_set_vring_call = vhost_vdpa_set_vring_call, .vhost_get_features = vhost_vdpa_get_features, + .vhost_set_backend_cap = vhost_vdpa_set_backend_cap, .vhost_set_owner = vhost_vdpa_set_owner, .vhost_set_vring_endian = NULL, .vhost_backend_memslots_limit = vhost_vdpa_memslots_limit, diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h index 6455663388..9b81a409da 100644 --- a/include/hw/virtio/vhost-vdpa.h +++ b/include/hw/virtio/vhost-vdpa.h @@ -18,6 +18,7 @@ typedef struct vhost_vdpa { int device_fd; uint32_t msg_type; MemoryListener listener; + struct vhost_dev *dev; } VhostVDPA; extern AddressSpace address_space_memory;