16b901437SMaxime Coquelin /* SPDX-License-Identifier: BSD-3-Clause 26b901437SMaxime Coquelin * Copyright(c) 2020 Red Hat Inc. 36b901437SMaxime Coquelin */ 46b901437SMaxime Coquelin 56b901437SMaxime Coquelin #include <sys/ioctl.h> 66b901437SMaxime Coquelin #include <sys/types.h> 76b901437SMaxime Coquelin #include <sys/stat.h> 80fd27826SSrujana Challa #include <sys/mman.h> 96b901437SMaxime Coquelin #include <fcntl.h> 1072b452c5SDmitry Kozlyuk #include <stdlib.h> 116b901437SMaxime Coquelin #include <unistd.h> 126b901437SMaxime Coquelin 136b901437SMaxime Coquelin #include <rte_memory.h> 146b901437SMaxime Coquelin 156b901437SMaxime Coquelin #include "vhost.h" 166b901437SMaxime Coquelin #include "virtio_user_dev.h" 176b901437SMaxime Coquelin 184173c55aSMaxime Coquelin struct vhost_vdpa_data { 194173c55aSMaxime Coquelin int vhostfd; 204173c55aSMaxime Coquelin uint64_t protocol_features; 214173c55aSMaxime Coquelin }; 224173c55aSMaxime Coquelin 235b75b63cSMaxime Coquelin #define VHOST_VDPA_SUPPORTED_BACKEND_FEATURES \ 245b75b63cSMaxime Coquelin (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2 | \ 255b75b63cSMaxime Coquelin 1ULL << VHOST_BACKEND_F_IOTLB_BATCH) 265b75b63cSMaxime Coquelin 276b901437SMaxime Coquelin /* vhost kernel & vdpa ioctls */ 286b901437SMaxime Coquelin #define VHOST_VIRTIO 0xAF 296b901437SMaxime Coquelin #define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64) 306b901437SMaxime Coquelin #define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64) 316b901437SMaxime Coquelin #define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01) 326b901437SMaxime Coquelin #define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02) 336b901437SMaxime Coquelin #define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64) 346b901437SMaxime Coquelin #define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int) 356b901437SMaxime Coquelin #define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state) 366b901437SMaxime Coquelin #define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr) 376b901437SMaxime Coquelin #define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state) 386b901437SMaxime Coquelin #define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state) 396b901437SMaxime Coquelin #define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file) 406b901437SMaxime Coquelin #define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file) 416b901437SMaxime Coquelin #define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file) 426b901437SMaxime Coquelin #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file) 436b901437SMaxime Coquelin #define VHOST_VDPA_GET_DEVICE_ID _IOR(VHOST_VIRTIO, 0x70, __u32) 446b901437SMaxime Coquelin #define VHOST_VDPA_GET_STATUS _IOR(VHOST_VIRTIO, 0x71, __u8) 456b901437SMaxime Coquelin #define VHOST_VDPA_SET_STATUS _IOW(VHOST_VIRTIO, 0x72, __u8) 469b7466f6SMaxime Coquelin #define VHOST_VDPA_GET_CONFIG _IOR(VHOST_VIRTIO, 0x73, struct vhost_vdpa_config) 479b7466f6SMaxime Coquelin #define VHOST_VDPA_SET_CONFIG _IOW(VHOST_VIRTIO, 0x74, struct vhost_vdpa_config) 48ab9098d2SMaxime Coquelin #define VHOST_VDPA_SET_VRING_ENABLE _IOW(VHOST_VIRTIO, 0x75, struct vhost_vring_state) 4935a6630eSMaxime Coquelin #define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64) 5035a6630eSMaxime Coquelin #define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64) 516b901437SMaxime Coquelin 526b901437SMaxime Coquelin /* no alignment requirement */ 536b901437SMaxime Coquelin struct vhost_iotlb_msg { 546b901437SMaxime Coquelin uint64_t iova; 556b901437SMaxime Coquelin uint64_t size; 566b901437SMaxime Coquelin uint64_t uaddr; 576b901437SMaxime Coquelin #define VHOST_ACCESS_RO 0x1 586b901437SMaxime Coquelin #define VHOST_ACCESS_WO 0x2 596b901437SMaxime Coquelin #define VHOST_ACCESS_RW 0x3 606b901437SMaxime Coquelin uint8_t perm; 616b901437SMaxime Coquelin #define VHOST_IOTLB_MISS 1 626b901437SMaxime Coquelin #define VHOST_IOTLB_UPDATE 2 636b901437SMaxime Coquelin #define VHOST_IOTLB_INVALIDATE 3 646b901437SMaxime Coquelin #define VHOST_IOTLB_ACCESS_FAIL 4 65a121f175SMaxime Coquelin #define VHOST_IOTLB_BATCH_BEGIN 5 66a121f175SMaxime Coquelin #define VHOST_IOTLB_BATCH_END 6 676b901437SMaxime Coquelin uint8_t type; 686b901437SMaxime Coquelin }; 696b901437SMaxime Coquelin 706b901437SMaxime Coquelin #define VHOST_IOTLB_MSG_V2 0x2 716b901437SMaxime Coquelin 729b7466f6SMaxime Coquelin struct vhost_vdpa_config { 739b7466f6SMaxime Coquelin uint32_t off; 749b7466f6SMaxime Coquelin uint32_t len; 75013b4c52SBruce Richardson uint8_t buf[]; 769b7466f6SMaxime Coquelin }; 779b7466f6SMaxime Coquelin 786b901437SMaxime Coquelin struct vhost_msg { 796b901437SMaxime Coquelin uint32_t type; 806b901437SMaxime Coquelin uint32_t reserved; 816b901437SMaxime Coquelin union { 826b901437SMaxime Coquelin struct vhost_iotlb_msg iotlb; 836b901437SMaxime Coquelin uint8_t padding[64]; 846b901437SMaxime Coquelin }; 856b901437SMaxime Coquelin }; 866b901437SMaxime Coquelin 8706856cabSMaxime Coquelin 8806856cabSMaxime Coquelin static int 8906856cabSMaxime Coquelin vhost_vdpa_ioctl(int fd, uint64_t request, void *arg) 9006856cabSMaxime Coquelin { 9106856cabSMaxime Coquelin int ret; 9206856cabSMaxime Coquelin 9306856cabSMaxime Coquelin ret = ioctl(fd, request, arg); 9406856cabSMaxime Coquelin if (ret) { 9506856cabSMaxime Coquelin PMD_DRV_LOG(ERR, "Vhost-vDPA ioctl %"PRIu64" failed (%s)", 9606856cabSMaxime Coquelin request, strerror(errno)); 9706856cabSMaxime Coquelin return -1; 9806856cabSMaxime Coquelin } 9906856cabSMaxime Coquelin 10006856cabSMaxime Coquelin return 0; 10106856cabSMaxime Coquelin } 10206856cabSMaxime Coquelin 10306856cabSMaxime Coquelin static int 10406856cabSMaxime Coquelin vhost_vdpa_set_owner(struct virtio_user_dev *dev) 10506856cabSMaxime Coquelin { 1064173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 1074173c55aSMaxime Coquelin 1084173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_SET_OWNER, NULL); 10906856cabSMaxime Coquelin } 11006856cabSMaxime Coquelin 1116b901437SMaxime Coquelin static int 1125b75b63cSMaxime Coquelin vhost_vdpa_get_protocol_features(struct virtio_user_dev *dev, uint64_t *features) 1136c251919SMaxime Coquelin { 1144173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 1154173c55aSMaxime Coquelin 1164173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_GET_BACKEND_FEATURES, features); 1176c251919SMaxime Coquelin } 1186c251919SMaxime Coquelin 1196c251919SMaxime Coquelin static int 1205b75b63cSMaxime Coquelin vhost_vdpa_set_protocol_features(struct virtio_user_dev *dev, uint64_t features) 1216c251919SMaxime Coquelin { 1224173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 1234173c55aSMaxime Coquelin 1244173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_SET_BACKEND_FEATURES, &features); 1256c251919SMaxime Coquelin } 1266c251919SMaxime Coquelin 1276c251919SMaxime Coquelin static int 128cc0151b3SMaxime Coquelin vhost_vdpa_get_features(struct virtio_user_dev *dev, uint64_t *features) 129cc0151b3SMaxime Coquelin { 1304173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 131cc0151b3SMaxime Coquelin int ret; 132cc0151b3SMaxime Coquelin 1334173c55aSMaxime Coquelin ret = vhost_vdpa_ioctl(data->vhostfd, VHOST_GET_FEATURES, features); 134cc0151b3SMaxime Coquelin if (ret) { 135cc0151b3SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to get features"); 136cc0151b3SMaxime Coquelin return -1; 137cc0151b3SMaxime Coquelin } 138cc0151b3SMaxime Coquelin 139b277308eSMaxime Coquelin if (*features & 1ULL << VIRTIO_NET_F_CTRL_VQ) 140b277308eSMaxime Coquelin dev->hw_cvq = true; 141cc0151b3SMaxime Coquelin 1425b75b63cSMaxime Coquelin /* Negotiated vDPA backend features */ 1434173c55aSMaxime Coquelin ret = vhost_vdpa_get_protocol_features(dev, &data->protocol_features); 1445b75b63cSMaxime Coquelin if (ret < 0) { 1455b75b63cSMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to get backend features"); 1465b75b63cSMaxime Coquelin return -1; 1475b75b63cSMaxime Coquelin } 1485b75b63cSMaxime Coquelin 1494173c55aSMaxime Coquelin data->protocol_features &= VHOST_VDPA_SUPPORTED_BACKEND_FEATURES; 1505b75b63cSMaxime Coquelin 1514173c55aSMaxime Coquelin ret = vhost_vdpa_set_protocol_features(dev, data->protocol_features); 1525b75b63cSMaxime Coquelin if (ret < 0) { 1535b75b63cSMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to set backend features"); 1545b75b63cSMaxime Coquelin return -1; 1555b75b63cSMaxime Coquelin } 1565b75b63cSMaxime Coquelin 157cc0151b3SMaxime Coquelin return 0; 158cc0151b3SMaxime Coquelin } 159cc0151b3SMaxime Coquelin 160cc0151b3SMaxime Coquelin static int 161cc0151b3SMaxime Coquelin vhost_vdpa_set_features(struct virtio_user_dev *dev, uint64_t features) 162cc0151b3SMaxime Coquelin { 1634173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 1644173c55aSMaxime Coquelin 165cc0151b3SMaxime Coquelin /* WORKAROUND */ 166cc0151b3SMaxime Coquelin features |= 1ULL << VIRTIO_F_IOMMU_PLATFORM; 167cc0151b3SMaxime Coquelin 1684173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_SET_FEATURES, &features); 169cc0151b3SMaxime Coquelin } 170cc0151b3SMaxime Coquelin 171cc0151b3SMaxime Coquelin static int 172a121f175SMaxime Coquelin vhost_vdpa_iotlb_batch_begin(struct virtio_user_dev *dev) 173a121f175SMaxime Coquelin { 1744173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 175a121f175SMaxime Coquelin struct vhost_msg msg = {}; 176a121f175SMaxime Coquelin 1774173c55aSMaxime Coquelin if (!(data->protocol_features & (1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) 178a121f175SMaxime Coquelin return 0; 179a121f175SMaxime Coquelin 1804173c55aSMaxime Coquelin if (!(data->protocol_features & (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2))) { 181a121f175SMaxime Coquelin PMD_DRV_LOG(ERR, "IOTLB_MSG_V2 not supported by the backend."); 182a121f175SMaxime Coquelin return -1; 183a121f175SMaxime Coquelin } 184a121f175SMaxime Coquelin 185a121f175SMaxime Coquelin msg.type = VHOST_IOTLB_MSG_V2; 186a121f175SMaxime Coquelin msg.iotlb.type = VHOST_IOTLB_BATCH_BEGIN; 187a121f175SMaxime Coquelin 1884173c55aSMaxime Coquelin if (write(data->vhostfd, &msg, sizeof(msg)) != sizeof(msg)) { 189a121f175SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to send IOTLB batch begin (%s)", 190a121f175SMaxime Coquelin strerror(errno)); 191a121f175SMaxime Coquelin return -1; 192a121f175SMaxime Coquelin } 193a121f175SMaxime Coquelin 194a121f175SMaxime Coquelin return 0; 195a121f175SMaxime Coquelin } 196a121f175SMaxime Coquelin 197a121f175SMaxime Coquelin static int 198a121f175SMaxime Coquelin vhost_vdpa_iotlb_batch_end(struct virtio_user_dev *dev) 199a121f175SMaxime Coquelin { 2004173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 201a121f175SMaxime Coquelin struct vhost_msg msg = {}; 202a121f175SMaxime Coquelin 2034173c55aSMaxime Coquelin if (!(data->protocol_features & (1ULL << VHOST_BACKEND_F_IOTLB_BATCH))) 204a121f175SMaxime Coquelin return 0; 205a121f175SMaxime Coquelin 2064173c55aSMaxime Coquelin if (!(data->protocol_features & (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2))) { 207a121f175SMaxime Coquelin PMD_DRV_LOG(ERR, "IOTLB_MSG_V2 not supported by the backend."); 208a121f175SMaxime Coquelin return -1; 209a121f175SMaxime Coquelin } 210a121f175SMaxime Coquelin 211a121f175SMaxime Coquelin msg.type = VHOST_IOTLB_MSG_V2; 212a121f175SMaxime Coquelin msg.iotlb.type = VHOST_IOTLB_BATCH_END; 213a121f175SMaxime Coquelin 2144173c55aSMaxime Coquelin if (write(data->vhostfd, &msg, sizeof(msg)) != sizeof(msg)) { 215a121f175SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to send IOTLB batch end (%s)", 216a121f175SMaxime Coquelin strerror(errno)); 217a121f175SMaxime Coquelin return -1; 218a121f175SMaxime Coquelin } 219a121f175SMaxime Coquelin 220a121f175SMaxime Coquelin return 0; 221a121f175SMaxime Coquelin } 222a121f175SMaxime Coquelin 223a121f175SMaxime Coquelin static int 2246b901437SMaxime Coquelin vhost_vdpa_dma_map(struct virtio_user_dev *dev, void *addr, 2256b901437SMaxime Coquelin uint64_t iova, size_t len) 2266b901437SMaxime Coquelin { 2274173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 2286b901437SMaxime Coquelin struct vhost_msg msg = {}; 2296b901437SMaxime Coquelin 2304173c55aSMaxime Coquelin if (!(data->protocol_features & (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2))) { 23135a6630eSMaxime Coquelin PMD_DRV_LOG(ERR, "IOTLB_MSG_V2 not supported by the backend."); 23235a6630eSMaxime Coquelin return -1; 23335a6630eSMaxime Coquelin } 23435a6630eSMaxime Coquelin 2356b901437SMaxime Coquelin msg.type = VHOST_IOTLB_MSG_V2; 2366b901437SMaxime Coquelin msg.iotlb.type = VHOST_IOTLB_UPDATE; 2376b901437SMaxime Coquelin msg.iotlb.iova = iova; 2386b901437SMaxime Coquelin msg.iotlb.uaddr = (uint64_t)(uintptr_t)addr; 2396b901437SMaxime Coquelin msg.iotlb.size = len; 2406b901437SMaxime Coquelin msg.iotlb.perm = VHOST_ACCESS_RW; 2416b901437SMaxime Coquelin 24252ae8f2fSMaxime Coquelin PMD_DRV_LOG(DEBUG, "%s: iova: 0x%" PRIx64 ", addr: %p, len: 0x%zx", 24352ae8f2fSMaxime Coquelin __func__, iova, addr, len); 24452ae8f2fSMaxime Coquelin 2454173c55aSMaxime Coquelin if (write(data->vhostfd, &msg, sizeof(msg)) != sizeof(msg)) { 2466b901437SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to send IOTLB update (%s)", 2476b901437SMaxime Coquelin strerror(errno)); 2486b901437SMaxime Coquelin return -1; 2496b901437SMaxime Coquelin } 2506b901437SMaxime Coquelin 2516b901437SMaxime Coquelin return 0; 2526b901437SMaxime Coquelin } 2536b901437SMaxime Coquelin 2546b901437SMaxime Coquelin static int 2556b901437SMaxime Coquelin vhost_vdpa_dma_unmap(struct virtio_user_dev *dev, __rte_unused void *addr, 2566b901437SMaxime Coquelin uint64_t iova, size_t len) 2576b901437SMaxime Coquelin { 2584173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 2596b901437SMaxime Coquelin struct vhost_msg msg = {}; 2606b901437SMaxime Coquelin 2614173c55aSMaxime Coquelin if (!(data->protocol_features & (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2))) { 26235a6630eSMaxime Coquelin PMD_DRV_LOG(ERR, "IOTLB_MSG_V2 not supported by the backend."); 26335a6630eSMaxime Coquelin return -1; 26435a6630eSMaxime Coquelin } 26535a6630eSMaxime Coquelin 2666b901437SMaxime Coquelin msg.type = VHOST_IOTLB_MSG_V2; 2676b901437SMaxime Coquelin msg.iotlb.type = VHOST_IOTLB_INVALIDATE; 2686b901437SMaxime Coquelin msg.iotlb.iova = iova; 2696b901437SMaxime Coquelin msg.iotlb.size = len; 2706b901437SMaxime Coquelin 27152ae8f2fSMaxime Coquelin PMD_DRV_LOG(DEBUG, "%s: iova: 0x%" PRIx64 ", len: 0x%zx", 27252ae8f2fSMaxime Coquelin __func__, iova, len); 27352ae8f2fSMaxime Coquelin 2744173c55aSMaxime Coquelin if (write(data->vhostfd, &msg, sizeof(msg)) != sizeof(msg)) { 2756b901437SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to send IOTLB invalidate (%s)", 2766b901437SMaxime Coquelin strerror(errno)); 2776b901437SMaxime Coquelin return -1; 2786b901437SMaxime Coquelin } 2796b901437SMaxime Coquelin 2806b901437SMaxime Coquelin return 0; 2816b901437SMaxime Coquelin } 2826b901437SMaxime Coquelin 283a121f175SMaxime Coquelin static int 284a121f175SMaxime Coquelin vhost_vdpa_dma_map_batch(struct virtio_user_dev *dev, void *addr, 285a121f175SMaxime Coquelin uint64_t iova, size_t len) 286a121f175SMaxime Coquelin { 287a121f175SMaxime Coquelin int ret; 288a121f175SMaxime Coquelin 289a121f175SMaxime Coquelin if (vhost_vdpa_iotlb_batch_begin(dev) < 0) 290a121f175SMaxime Coquelin return -1; 291a121f175SMaxime Coquelin 292a121f175SMaxime Coquelin ret = vhost_vdpa_dma_map(dev, addr, iova, len); 293a121f175SMaxime Coquelin 294a121f175SMaxime Coquelin if (vhost_vdpa_iotlb_batch_end(dev) < 0) 295a121f175SMaxime Coquelin return -1; 296a121f175SMaxime Coquelin 297a121f175SMaxime Coquelin return ret; 298a121f175SMaxime Coquelin } 299a121f175SMaxime Coquelin 300a121f175SMaxime Coquelin static int 301a121f175SMaxime Coquelin vhost_vdpa_dma_unmap_batch(struct virtio_user_dev *dev, void *addr, 302a121f175SMaxime Coquelin uint64_t iova, size_t len) 303a121f175SMaxime Coquelin { 304a121f175SMaxime Coquelin int ret; 305a121f175SMaxime Coquelin 306a121f175SMaxime Coquelin if (vhost_vdpa_iotlb_batch_begin(dev) < 0) 307a121f175SMaxime Coquelin return -1; 308a121f175SMaxime Coquelin 309a121f175SMaxime Coquelin ret = vhost_vdpa_dma_unmap(dev, addr, iova, len); 310a121f175SMaxime Coquelin 311a121f175SMaxime Coquelin if (vhost_vdpa_iotlb_batch_end(dev) < 0) 312a121f175SMaxime Coquelin return -1; 313a121f175SMaxime Coquelin 314a121f175SMaxime Coquelin return ret; 315a121f175SMaxime Coquelin } 3166b901437SMaxime Coquelin 3176b901437SMaxime Coquelin static int 3186b901437SMaxime Coquelin vhost_vdpa_map_contig(const struct rte_memseg_list *msl, 3196b901437SMaxime Coquelin const struct rte_memseg *ms, size_t len, void *arg) 3206b901437SMaxime Coquelin { 3216b901437SMaxime Coquelin struct virtio_user_dev *dev = arg; 3226b901437SMaxime Coquelin 3236b901437SMaxime Coquelin if (msl->external) 3246b901437SMaxime Coquelin return 0; 3256b901437SMaxime Coquelin 3266b901437SMaxime Coquelin return vhost_vdpa_dma_map(dev, ms->addr, ms->iova, len); 3276b901437SMaxime Coquelin } 3286b901437SMaxime Coquelin 3296b901437SMaxime Coquelin static int 3306b901437SMaxime Coquelin vhost_vdpa_map(const struct rte_memseg_list *msl, const struct rte_memseg *ms, 3316b901437SMaxime Coquelin void *arg) 3326b901437SMaxime Coquelin { 3336b901437SMaxime Coquelin struct virtio_user_dev *dev = arg; 3346b901437SMaxime Coquelin 3356b901437SMaxime Coquelin /* skip external memory that isn't a heap */ 3366b901437SMaxime Coquelin if (msl->external && !msl->heap) 3376b901437SMaxime Coquelin return 0; 3386b901437SMaxime Coquelin 3396b901437SMaxime Coquelin /* skip any segments with invalid IOVA addresses */ 3406b901437SMaxime Coquelin if (ms->iova == RTE_BAD_IOVA) 3416b901437SMaxime Coquelin return 0; 3426b901437SMaxime Coquelin 3436b901437SMaxime Coquelin /* if IOVA mode is VA, we've already mapped the internal segments */ 3446b901437SMaxime Coquelin if (!msl->external && rte_eal_iova_mode() == RTE_IOVA_VA) 3456b901437SMaxime Coquelin return 0; 3466b901437SMaxime Coquelin 3476b901437SMaxime Coquelin return vhost_vdpa_dma_map(dev, ms->addr, ms->iova, ms->len); 3486b901437SMaxime Coquelin } 3496b901437SMaxime Coquelin 3506b901437SMaxime Coquelin static int 351539d910cSMaxime Coquelin vhost_vdpa_set_memory_table(struct virtio_user_dev *dev) 3526b901437SMaxime Coquelin { 353a121f175SMaxime Coquelin int ret; 354a121f175SMaxime Coquelin 355a121f175SMaxime Coquelin if (vhost_vdpa_iotlb_batch_begin(dev) < 0) 356a121f175SMaxime Coquelin return -1; 357a121f175SMaxime Coquelin 3586b901437SMaxime Coquelin vhost_vdpa_dma_unmap(dev, NULL, 0, SIZE_MAX); 3596b901437SMaxime Coquelin 3606b901437SMaxime Coquelin if (rte_eal_iova_mode() == RTE_IOVA_VA) { 3616b901437SMaxime Coquelin /* with IOVA as VA mode, we can get away with mapping contiguous 3626b901437SMaxime Coquelin * chunks rather than going page-by-page. 3636b901437SMaxime Coquelin */ 364a121f175SMaxime Coquelin ret = rte_memseg_contig_walk_thread_unsafe( 3656b901437SMaxime Coquelin vhost_vdpa_map_contig, dev); 3666b901437SMaxime Coquelin if (ret) 367a121f175SMaxime Coquelin goto batch_end; 3686b901437SMaxime Coquelin /* we have to continue the walk because we've skipped the 3696b901437SMaxime Coquelin * external segments during the config walk. 3706b901437SMaxime Coquelin */ 3716b901437SMaxime Coquelin } 372a121f175SMaxime Coquelin ret = rte_memseg_walk_thread_unsafe(vhost_vdpa_map, dev); 373a121f175SMaxime Coquelin 374a121f175SMaxime Coquelin batch_end: 375a121f175SMaxime Coquelin if (vhost_vdpa_iotlb_batch_end(dev) < 0) 376a121f175SMaxime Coquelin return -1; 377a121f175SMaxime Coquelin 378a121f175SMaxime Coquelin return ret; 3796b901437SMaxime Coquelin } 3806b901437SMaxime Coquelin 381ab9098d2SMaxime Coquelin static int 382ab9098d2SMaxime Coquelin vhost_vdpa_set_vring_enable(struct virtio_user_dev *dev, struct vhost_vring_state *state) 383ab9098d2SMaxime Coquelin { 3844173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 3854173c55aSMaxime Coquelin 3864173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_VDPA_SET_VRING_ENABLE, state); 387ab9098d2SMaxime Coquelin } 388ab9098d2SMaxime Coquelin 389ab9098d2SMaxime Coquelin static int 390ab9098d2SMaxime Coquelin vhost_vdpa_set_vring_num(struct virtio_user_dev *dev, struct vhost_vring_state *state) 391ab9098d2SMaxime Coquelin { 3924173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 3934173c55aSMaxime Coquelin 3944173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_SET_VRING_NUM, state); 395ab9098d2SMaxime Coquelin } 396ab9098d2SMaxime Coquelin 397ab9098d2SMaxime Coquelin static int 398ab9098d2SMaxime Coquelin vhost_vdpa_set_vring_base(struct virtio_user_dev *dev, struct vhost_vring_state *state) 399ab9098d2SMaxime Coquelin { 4004173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 4014173c55aSMaxime Coquelin 4024173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_SET_VRING_BASE, state); 403ab9098d2SMaxime Coquelin } 404ab9098d2SMaxime Coquelin 405ab9098d2SMaxime Coquelin static int 406ab9098d2SMaxime Coquelin vhost_vdpa_get_vring_base(struct virtio_user_dev *dev, struct vhost_vring_state *state) 407ab9098d2SMaxime Coquelin { 4084173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 4094173c55aSMaxime Coquelin 4104173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_GET_VRING_BASE, state); 411ab9098d2SMaxime Coquelin } 412ab9098d2SMaxime Coquelin 413ce399c36SMaxime Coquelin static int 414ce399c36SMaxime Coquelin vhost_vdpa_set_vring_call(struct virtio_user_dev *dev, struct vhost_vring_file *file) 415ce399c36SMaxime Coquelin { 4164173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 4174173c55aSMaxime Coquelin 4184173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_SET_VRING_CALL, file); 419ce399c36SMaxime Coquelin } 420ce399c36SMaxime Coquelin 421ce399c36SMaxime Coquelin static int 422ce399c36SMaxime Coquelin vhost_vdpa_set_vring_kick(struct virtio_user_dev *dev, struct vhost_vring_file *file) 423ce399c36SMaxime Coquelin { 4244173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 4254173c55aSMaxime Coquelin 4264173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_SET_VRING_KICK, file); 427ce399c36SMaxime Coquelin } 428ce399c36SMaxime Coquelin 429dc65db73SMaxime Coquelin static int 430dc65db73SMaxime Coquelin vhost_vdpa_set_vring_addr(struct virtio_user_dev *dev, struct vhost_vring_addr *addr) 431dc65db73SMaxime Coquelin { 4324173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 4334173c55aSMaxime Coquelin 4344173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_SET_VRING_ADDR, addr); 435dc65db73SMaxime Coquelin } 436dc65db73SMaxime Coquelin 4378723c894SMaxime Coquelin static int 4388723c894SMaxime Coquelin vhost_vdpa_get_status(struct virtio_user_dev *dev, uint8_t *status) 4398723c894SMaxime Coquelin { 4404173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 4414173c55aSMaxime Coquelin 4424173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_VDPA_GET_STATUS, status); 4438723c894SMaxime Coquelin } 4448723c894SMaxime Coquelin 4458723c894SMaxime Coquelin static int 4468723c894SMaxime Coquelin vhost_vdpa_set_status(struct virtio_user_dev *dev, uint8_t status) 4478723c894SMaxime Coquelin { 4484173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 4494173c55aSMaxime Coquelin 4504173c55aSMaxime Coquelin return vhost_vdpa_ioctl(data->vhostfd, VHOST_VDPA_SET_STATUS, &status); 4518723c894SMaxime Coquelin } 4528723c894SMaxime Coquelin 4539b7466f6SMaxime Coquelin static int 4549b7466f6SMaxime Coquelin vhost_vdpa_get_config(struct virtio_user_dev *dev, uint8_t *data, uint32_t off, uint32_t len) 4559b7466f6SMaxime Coquelin { 4569b7466f6SMaxime Coquelin struct vhost_vdpa_data *vdpa_data = dev->backend_data; 4579b7466f6SMaxime Coquelin struct vhost_vdpa_config *config; 4589b7466f6SMaxime Coquelin int ret = 0; 4599b7466f6SMaxime Coquelin 4609b7466f6SMaxime Coquelin config = malloc(sizeof(*config) + len); 4619b7466f6SMaxime Coquelin if (!config) { 4629b7466f6SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to allocate vDPA config data"); 4639b7466f6SMaxime Coquelin return -1; 4649b7466f6SMaxime Coquelin } 4659b7466f6SMaxime Coquelin 4669b7466f6SMaxime Coquelin config->off = off; 4679b7466f6SMaxime Coquelin config->len = len; 4689b7466f6SMaxime Coquelin 4699b7466f6SMaxime Coquelin ret = vhost_vdpa_ioctl(vdpa_data->vhostfd, VHOST_VDPA_GET_CONFIG, config); 4709b7466f6SMaxime Coquelin if (ret) { 4719b7466f6SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to get vDPA config (offset 0x%x, len 0x%x)", off, len); 4729b7466f6SMaxime Coquelin ret = -1; 4739b7466f6SMaxime Coquelin goto out; 4749b7466f6SMaxime Coquelin } 4759b7466f6SMaxime Coquelin 4769b7466f6SMaxime Coquelin memcpy(data, config->buf, len); 4779b7466f6SMaxime Coquelin out: 4789b7466f6SMaxime Coquelin free(config); 4799b7466f6SMaxime Coquelin 4809b7466f6SMaxime Coquelin return ret; 4819b7466f6SMaxime Coquelin } 4829b7466f6SMaxime Coquelin 4839b7466f6SMaxime Coquelin static int 4849b7466f6SMaxime Coquelin vhost_vdpa_set_config(struct virtio_user_dev *dev, const uint8_t *data, uint32_t off, uint32_t len) 4859b7466f6SMaxime Coquelin { 4869b7466f6SMaxime Coquelin struct vhost_vdpa_data *vdpa_data = dev->backend_data; 4879b7466f6SMaxime Coquelin struct vhost_vdpa_config *config; 4889b7466f6SMaxime Coquelin int ret = 0; 4899b7466f6SMaxime Coquelin 4909b7466f6SMaxime Coquelin config = malloc(sizeof(*config) + len); 4919b7466f6SMaxime Coquelin if (!config) { 4929b7466f6SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to allocate vDPA config data"); 4939b7466f6SMaxime Coquelin return -1; 4949b7466f6SMaxime Coquelin } 4959b7466f6SMaxime Coquelin 4969b7466f6SMaxime Coquelin config->off = off; 4979b7466f6SMaxime Coquelin config->len = len; 4989b7466f6SMaxime Coquelin 4999b7466f6SMaxime Coquelin memcpy(config->buf, data, len); 5009b7466f6SMaxime Coquelin 5019b7466f6SMaxime Coquelin ret = vhost_vdpa_ioctl(vdpa_data->vhostfd, VHOST_VDPA_SET_CONFIG, config); 5029b7466f6SMaxime Coquelin if (ret) { 5039b7466f6SMaxime Coquelin PMD_DRV_LOG(ERR, "Failed to set vDPA config (offset 0x%x, len 0x%x)", off, len); 5049b7466f6SMaxime Coquelin ret = -1; 5059b7466f6SMaxime Coquelin } 5069b7466f6SMaxime Coquelin 5079b7466f6SMaxime Coquelin free(config); 5089b7466f6SMaxime Coquelin 5099b7466f6SMaxime Coquelin return ret; 5109b7466f6SMaxime Coquelin } 5119b7466f6SMaxime Coquelin 5126b901437SMaxime Coquelin /** 5136b901437SMaxime Coquelin * Set up environment to talk with a vhost vdpa backend. 5146b901437SMaxime Coquelin * 5156b901437SMaxime Coquelin * @return 5166b901437SMaxime Coquelin * - (-1) if fail to set up; 5176b901437SMaxime Coquelin * - (>=0) if successful. 5186b901437SMaxime Coquelin */ 5196b901437SMaxime Coquelin static int 5206b901437SMaxime Coquelin vhost_vdpa_setup(struct virtio_user_dev *dev) 5216b901437SMaxime Coquelin { 5224173c55aSMaxime Coquelin struct vhost_vdpa_data *data; 5236b901437SMaxime Coquelin uint32_t did = (uint32_t)-1; 5246b901437SMaxime Coquelin 5254173c55aSMaxime Coquelin data = malloc(sizeof(*data)); 5264173c55aSMaxime Coquelin if (!data) { 5274173c55aSMaxime Coquelin PMD_DRV_LOG(ERR, "(%s) Faidle to allocate backend data", dev->path); 5286b901437SMaxime Coquelin return -1; 5296b901437SMaxime Coquelin } 5306b901437SMaxime Coquelin 5314173c55aSMaxime Coquelin data->vhostfd = open(dev->path, O_RDWR); 5324173c55aSMaxime Coquelin if (data->vhostfd < 0) { 533f3854ebaSThomas Monjalon PMD_DRV_LOG(ERR, "Failed to open %s: %s", 5344173c55aSMaxime Coquelin dev->path, strerror(errno)); 5354173c55aSMaxime Coquelin free(data); 5366b901437SMaxime Coquelin return -1; 5376b901437SMaxime Coquelin } 5386b901437SMaxime Coquelin 5394173c55aSMaxime Coquelin if (ioctl(data->vhostfd, VHOST_VDPA_GET_DEVICE_ID, &did) < 0 || 5404173c55aSMaxime Coquelin did != VIRTIO_ID_NETWORK) { 541f3854ebaSThomas Monjalon PMD_DRV_LOG(ERR, "Invalid vdpa device ID: %u", did); 5424173c55aSMaxime Coquelin close(data->vhostfd); 5434173c55aSMaxime Coquelin free(data); 5444173c55aSMaxime Coquelin return -1; 5454173c55aSMaxime Coquelin } 5464173c55aSMaxime Coquelin 5474173c55aSMaxime Coquelin dev->backend_data = data; 5484173c55aSMaxime Coquelin 5496b901437SMaxime Coquelin return 0; 5506b901437SMaxime Coquelin } 5516b901437SMaxime Coquelin 5526b901437SMaxime Coquelin static int 5534173c55aSMaxime Coquelin vhost_vdpa_destroy(struct virtio_user_dev *dev) 554748e5ea5SMaxime Coquelin { 5554173c55aSMaxime Coquelin struct vhost_vdpa_data *data = dev->backend_data; 5564173c55aSMaxime Coquelin 5574173c55aSMaxime Coquelin if (!data) 5584173c55aSMaxime Coquelin return 0; 5594173c55aSMaxime Coquelin 5604173c55aSMaxime Coquelin close(data->vhostfd); 5614173c55aSMaxime Coquelin 5624173c55aSMaxime Coquelin free(data); 5634173c55aSMaxime Coquelin dev->backend_data = NULL; 5644173c55aSMaxime Coquelin 565748e5ea5SMaxime Coquelin return 0; 566748e5ea5SMaxime Coquelin } 567748e5ea5SMaxime Coquelin 568748e5ea5SMaxime Coquelin static int 5699eb56fb2SMaxime Coquelin vhost_vdpa_cvq_enable(struct virtio_user_dev *dev, int enable) 5709eb56fb2SMaxime Coquelin { 5719eb56fb2SMaxime Coquelin struct vhost_vring_state state = { 5729eb56fb2SMaxime Coquelin .index = dev->max_queue_pairs * 2, 5739eb56fb2SMaxime Coquelin .num = enable, 5749eb56fb2SMaxime Coquelin }; 5759eb56fb2SMaxime Coquelin 5769eb56fb2SMaxime Coquelin return vhost_vdpa_set_vring_enable(dev, &state); 5779eb56fb2SMaxime Coquelin } 5789eb56fb2SMaxime Coquelin 5799eb56fb2SMaxime Coquelin static int 5806b901437SMaxime Coquelin vhost_vdpa_enable_queue_pair(struct virtio_user_dev *dev, 5816b901437SMaxime Coquelin uint16_t pair_idx, 5826b901437SMaxime Coquelin int enable) 5836b901437SMaxime Coquelin { 5846b901437SMaxime Coquelin int i; 5856b901437SMaxime Coquelin 5866b901437SMaxime Coquelin if (dev->qp_enabled[pair_idx] == enable) 5876b901437SMaxime Coquelin return 0; 5886b901437SMaxime Coquelin 5896b901437SMaxime Coquelin for (i = 0; i < 2; ++i) { 5906b901437SMaxime Coquelin struct vhost_vring_state state = { 5916b901437SMaxime Coquelin .index = pair_idx * 2 + i, 5926b901437SMaxime Coquelin .num = enable, 5936b901437SMaxime Coquelin }; 5946b901437SMaxime Coquelin 595ab9098d2SMaxime Coquelin if (vhost_vdpa_set_vring_enable(dev, &state)) 5966b901437SMaxime Coquelin return -1; 5976b901437SMaxime Coquelin } 5986b901437SMaxime Coquelin 5996b901437SMaxime Coquelin dev->qp_enabled[pair_idx] = enable; 6006b901437SMaxime Coquelin 6016b901437SMaxime Coquelin return 0; 6026b901437SMaxime Coquelin } 6036b901437SMaxime Coquelin 6045b75b63cSMaxime Coquelin static int 6055b75b63cSMaxime Coquelin vhost_vdpa_get_backend_features(uint64_t *features) 6065b75b63cSMaxime Coquelin { 6075b75b63cSMaxime Coquelin *features = 0; 6085b75b63cSMaxime Coquelin 6095b75b63cSMaxime Coquelin return 0; 6105b75b63cSMaxime Coquelin } 6115b75b63cSMaxime Coquelin 61294973531SMaxime Coquelin static int 61394973531SMaxime Coquelin vhost_vdpa_update_link_state(struct virtio_user_dev *dev __rte_unused) 61494973531SMaxime Coquelin { 61594973531SMaxime Coquelin /* Nothing to update (for now?) */ 61694973531SMaxime Coquelin return 0; 61794973531SMaxime Coquelin } 61894973531SMaxime Coquelin 61994973531SMaxime Coquelin static int 62094973531SMaxime Coquelin vhost_vdpa_get_intr_fd(struct virtio_user_dev *dev __rte_unused) 62194973531SMaxime Coquelin { 62294973531SMaxime Coquelin /* No link state interrupt with Vhost-vDPA */ 62394973531SMaxime Coquelin return -1; 62494973531SMaxime Coquelin } 62594973531SMaxime Coquelin 6260fd27826SSrujana Challa static int 6270fd27826SSrujana Challa vhost_vdpa_get_nr_vrings(struct virtio_user_dev *dev) 6280fd27826SSrujana Challa { 6290fd27826SSrujana Challa int nr_vrings = dev->max_queue_pairs * 2; 6300fd27826SSrujana Challa 6310fd27826SSrujana Challa if (dev->device_features & (1ull << VIRTIO_NET_F_CTRL_VQ)) 6320fd27826SSrujana Challa nr_vrings += 1; 6330fd27826SSrujana Challa 6340fd27826SSrujana Challa return nr_vrings; 6350fd27826SSrujana Challa } 6360fd27826SSrujana Challa 6370fd27826SSrujana Challa static int 6380fd27826SSrujana Challa vhost_vdpa_unmap_notification_area(struct virtio_user_dev *dev) 6390fd27826SSrujana Challa { 6400fd27826SSrujana Challa int i, nr_vrings; 6410fd27826SSrujana Challa 6420fd27826SSrujana Challa nr_vrings = vhost_vdpa_get_nr_vrings(dev); 6430fd27826SSrujana Challa 6440fd27826SSrujana Challa for (i = 0; i < nr_vrings; i++) { 6450fd27826SSrujana Challa if (dev->notify_area[i]) 6460fd27826SSrujana Challa munmap(dev->notify_area[i], getpagesize()); 6470fd27826SSrujana Challa } 6480fd27826SSrujana Challa free(dev->notify_area); 6490fd27826SSrujana Challa dev->notify_area = NULL; 6500fd27826SSrujana Challa 6510fd27826SSrujana Challa return 0; 6520fd27826SSrujana Challa } 6530fd27826SSrujana Challa 6540fd27826SSrujana Challa static int 6550fd27826SSrujana Challa vhost_vdpa_map_notification_area(struct virtio_user_dev *dev) 6560fd27826SSrujana Challa { 6570fd27826SSrujana Challa struct vhost_vdpa_data *data = dev->backend_data; 6580fd27826SSrujana Challa int nr_vrings, i, page_size = getpagesize(); 6590fd27826SSrujana Challa uint16_t **notify_area; 6600fd27826SSrujana Challa 6610fd27826SSrujana Challa nr_vrings = vhost_vdpa_get_nr_vrings(dev); 6620fd27826SSrujana Challa 6630fd27826SSrujana Challa notify_area = malloc(nr_vrings * sizeof(*notify_area)); 6640fd27826SSrujana Challa if (!notify_area) { 6650fd27826SSrujana Challa PMD_DRV_LOG(ERR, "(%s) Failed to allocate notify area array", dev->path); 6660fd27826SSrujana Challa return -1; 6670fd27826SSrujana Challa } 6680fd27826SSrujana Challa 6690fd27826SSrujana Challa for (i = 0; i < nr_vrings; i++) { 6700fd27826SSrujana Challa notify_area[i] = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED | MAP_FILE, 6710fd27826SSrujana Challa data->vhostfd, i * page_size); 6720fd27826SSrujana Challa if (notify_area[i] == MAP_FAILED) { 673*f665790aSDavid Marchand PMD_DRV_LOG(ERR, "(%s) Map failed for notify address of queue %d", 6740fd27826SSrujana Challa dev->path, i); 6750fd27826SSrujana Challa i--; 6760fd27826SSrujana Challa goto map_err; 6770fd27826SSrujana Challa } 6780fd27826SSrujana Challa } 6790fd27826SSrujana Challa dev->notify_area = notify_area; 6800fd27826SSrujana Challa 6810fd27826SSrujana Challa return 0; 6820fd27826SSrujana Challa 6830fd27826SSrujana Challa map_err: 6840fd27826SSrujana Challa for (; i >= 0; i--) 6850fd27826SSrujana Challa munmap(notify_area[i], page_size); 6860fd27826SSrujana Challa free(notify_area); 6870fd27826SSrujana Challa 6880fd27826SSrujana Challa return -1; 6890fd27826SSrujana Challa } 6900fd27826SSrujana Challa 6916b901437SMaxime Coquelin struct virtio_user_backend_ops virtio_ops_vdpa = { 6926b901437SMaxime Coquelin .setup = vhost_vdpa_setup, 693748e5ea5SMaxime Coquelin .destroy = vhost_vdpa_destroy, 6945b75b63cSMaxime Coquelin .get_backend_features = vhost_vdpa_get_backend_features, 69506856cabSMaxime Coquelin .set_owner = vhost_vdpa_set_owner, 696cc0151b3SMaxime Coquelin .get_features = vhost_vdpa_get_features, 697cc0151b3SMaxime Coquelin .set_features = vhost_vdpa_set_features, 698539d910cSMaxime Coquelin .set_memory_table = vhost_vdpa_set_memory_table, 699ab9098d2SMaxime Coquelin .set_vring_num = vhost_vdpa_set_vring_num, 700ab9098d2SMaxime Coquelin .set_vring_base = vhost_vdpa_set_vring_base, 701ab9098d2SMaxime Coquelin .get_vring_base = vhost_vdpa_get_vring_base, 702ce399c36SMaxime Coquelin .set_vring_call = vhost_vdpa_set_vring_call, 703ce399c36SMaxime Coquelin .set_vring_kick = vhost_vdpa_set_vring_kick, 704dc65db73SMaxime Coquelin .set_vring_addr = vhost_vdpa_set_vring_addr, 7058723c894SMaxime Coquelin .get_status = vhost_vdpa_get_status, 7068723c894SMaxime Coquelin .set_status = vhost_vdpa_set_status, 7079b7466f6SMaxime Coquelin .get_config = vhost_vdpa_get_config, 7089b7466f6SMaxime Coquelin .set_config = vhost_vdpa_set_config, 7099eb56fb2SMaxime Coquelin .cvq_enable = vhost_vdpa_cvq_enable, 7106b901437SMaxime Coquelin .enable_qp = vhost_vdpa_enable_queue_pair, 711a121f175SMaxime Coquelin .dma_map = vhost_vdpa_dma_map_batch, 712a121f175SMaxime Coquelin .dma_unmap = vhost_vdpa_dma_unmap_batch, 71394973531SMaxime Coquelin .update_link_state = vhost_vdpa_update_link_state, 71494973531SMaxime Coquelin .get_intr_fd = vhost_vdpa_get_intr_fd, 7150fd27826SSrujana Challa .map_notification_area = vhost_vdpa_map_notification_area, 7160fd27826SSrujana Challa .unmap_notification_area = vhost_vdpa_unmap_notification_area, 7176b901437SMaxime Coquelin }; 718