vhost-vdpa: batch updating IOTLB mappings
To speed up the memory mapping updating between vhost-vDPA and vDPA device driver, this patch passes the IOTLB batching flags via IOTLB API. Two new flags was introduced, VHOST_IOTLB_BATCH_BEGIN is a hint that a bathced IOTLB updating may be initiated from the userspace. VHOST_IOTLB_BATCH_END is a hint that userspace has finished the updating: VHOST_IOTLB_BATCH_BEGIN VHOST_IOTLB_UPDATE/VHOST_IOTLB_INVALIDATE ... VHOST_IOTLB_BATCH_END Vhost-vDPA can then know that all mappings has been set and can do optimization like passing all the mappings to the vDPA device driver. Signed-off-by: Jason Wang <jasowang@redhat.com> Message-Id: <20200907104903.31551-4-jasowang@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
				
					committed by
					
						 Michael S. Tsirkin
						Michael S. Tsirkin
					
				
			
			
				
	
			
			
			
						parent
						
							b37556edec
						
					
				
				
					commit
					a5bd05800f
				
			| @@ -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, | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user