1*108a6481SCindy Lu /* 2*108a6481SCindy Lu * vhost-vdpa 3*108a6481SCindy Lu * 4*108a6481SCindy Lu * Copyright(c) 2017-2018 Intel Corporation. 5*108a6481SCindy Lu * Copyright(c) 2020 Red Hat, Inc. 6*108a6481SCindy Lu * 7*108a6481SCindy Lu * This work is licensed under the terms of the GNU GPL, version 2 or later. 8*108a6481SCindy Lu * See the COPYING file in the top-level directory. 9*108a6481SCindy Lu * 10*108a6481SCindy Lu */ 11*108a6481SCindy Lu 12*108a6481SCindy Lu #include "qemu/osdep.h" 13*108a6481SCindy Lu #include <linux/vhost.h> 14*108a6481SCindy Lu #include <linux/vfio.h> 15*108a6481SCindy Lu #include <sys/eventfd.h> 16*108a6481SCindy Lu #include <sys/ioctl.h> 17*108a6481SCindy Lu #include "hw/virtio/vhost.h" 18*108a6481SCindy Lu #include "hw/virtio/vhost-backend.h" 19*108a6481SCindy Lu #include "hw/virtio/virtio-net.h" 20*108a6481SCindy Lu #include "hw/virtio/vhost-vdpa.h" 21*108a6481SCindy Lu #include "qemu/main-loop.h" 22*108a6481SCindy Lu #include <linux/kvm.h> 23*108a6481SCindy Lu #include "sysemu/kvm.h" 24*108a6481SCindy Lu 25*108a6481SCindy Lu static bool vhost_vdpa_listener_skipped_section(MemoryRegionSection *section) 26*108a6481SCindy Lu { 27*108a6481SCindy Lu return (!memory_region_is_ram(section->mr) && 28*108a6481SCindy Lu !memory_region_is_iommu(section->mr)) || 29*108a6481SCindy Lu /* 30*108a6481SCindy Lu * Sizing an enabled 64-bit BAR can cause spurious mappings to 31*108a6481SCindy Lu * addresses in the upper part of the 64-bit address space. These 32*108a6481SCindy Lu * are never accessed by the CPU and beyond the address width of 33*108a6481SCindy Lu * some IOMMU hardware. TODO: VDPA should tell us the IOMMU width. 34*108a6481SCindy Lu */ 35*108a6481SCindy Lu section->offset_within_address_space & (1ULL << 63); 36*108a6481SCindy Lu } 37*108a6481SCindy Lu 38*108a6481SCindy Lu static int vhost_vdpa_dma_map(struct vhost_vdpa *v, hwaddr iova, hwaddr size, 39*108a6481SCindy Lu void *vaddr, bool readonly) 40*108a6481SCindy Lu { 41*108a6481SCindy Lu struct vhost_msg_v2 msg; 42*108a6481SCindy Lu int fd = v->device_fd; 43*108a6481SCindy Lu int ret = 0; 44*108a6481SCindy Lu 45*108a6481SCindy Lu msg.type = v->msg_type; 46*108a6481SCindy Lu msg.iotlb.iova = iova; 47*108a6481SCindy Lu msg.iotlb.size = size; 48*108a6481SCindy Lu msg.iotlb.uaddr = (uint64_t)(uintptr_t)vaddr; 49*108a6481SCindy Lu msg.iotlb.perm = readonly ? VHOST_ACCESS_RO : VHOST_ACCESS_RW; 50*108a6481SCindy Lu msg.iotlb.type = VHOST_IOTLB_UPDATE; 51*108a6481SCindy Lu 52*108a6481SCindy Lu if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { 53*108a6481SCindy Lu error_report("failed to write, fd=%d, errno=%d (%s)", 54*108a6481SCindy Lu fd, errno, strerror(errno)); 55*108a6481SCindy Lu return -EIO ; 56*108a6481SCindy Lu } 57*108a6481SCindy Lu 58*108a6481SCindy Lu return ret; 59*108a6481SCindy Lu } 60*108a6481SCindy Lu 61*108a6481SCindy Lu static int vhost_vdpa_dma_unmap(struct vhost_vdpa *v, hwaddr iova, 62*108a6481SCindy Lu hwaddr size) 63*108a6481SCindy Lu { 64*108a6481SCindy Lu struct vhost_msg_v2 msg; 65*108a6481SCindy Lu int fd = v->device_fd; 66*108a6481SCindy Lu int ret = 0; 67*108a6481SCindy Lu 68*108a6481SCindy Lu msg.type = v->msg_type; 69*108a6481SCindy Lu msg.iotlb.iova = iova; 70*108a6481SCindy Lu msg.iotlb.size = size; 71*108a6481SCindy Lu msg.iotlb.type = VHOST_IOTLB_INVALIDATE; 72*108a6481SCindy Lu 73*108a6481SCindy Lu if (write(fd, &msg, sizeof(msg)) != sizeof(msg)) { 74*108a6481SCindy Lu error_report("failed to write, fd=%d, errno=%d (%s)", 75*108a6481SCindy Lu fd, errno, strerror(errno)); 76*108a6481SCindy Lu return -EIO ; 77*108a6481SCindy Lu } 78*108a6481SCindy Lu 79*108a6481SCindy Lu return ret; 80*108a6481SCindy Lu } 81*108a6481SCindy Lu 82*108a6481SCindy Lu static void vhost_vdpa_listener_region_add(MemoryListener *listener, 83*108a6481SCindy Lu MemoryRegionSection *section) 84*108a6481SCindy Lu { 85*108a6481SCindy Lu struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); 86*108a6481SCindy Lu hwaddr iova; 87*108a6481SCindy Lu Int128 llend, llsize; 88*108a6481SCindy Lu void *vaddr; 89*108a6481SCindy Lu int ret; 90*108a6481SCindy Lu 91*108a6481SCindy Lu if (vhost_vdpa_listener_skipped_section(section)) { 92*108a6481SCindy Lu return; 93*108a6481SCindy Lu } 94*108a6481SCindy Lu 95*108a6481SCindy Lu if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != 96*108a6481SCindy Lu (section->offset_within_region & ~TARGET_PAGE_MASK))) { 97*108a6481SCindy Lu error_report("%s received unaligned region", __func__); 98*108a6481SCindy Lu return; 99*108a6481SCindy Lu } 100*108a6481SCindy Lu 101*108a6481SCindy Lu iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); 102*108a6481SCindy Lu llend = int128_make64(section->offset_within_address_space); 103*108a6481SCindy Lu llend = int128_add(llend, section->size); 104*108a6481SCindy Lu llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK)); 105*108a6481SCindy Lu 106*108a6481SCindy Lu if (int128_ge(int128_make64(iova), llend)) { 107*108a6481SCindy Lu return; 108*108a6481SCindy Lu } 109*108a6481SCindy Lu 110*108a6481SCindy Lu memory_region_ref(section->mr); 111*108a6481SCindy Lu 112*108a6481SCindy Lu /* Here we assume that memory_region_is_ram(section->mr)==true */ 113*108a6481SCindy Lu 114*108a6481SCindy Lu vaddr = memory_region_get_ram_ptr(section->mr) + 115*108a6481SCindy Lu section->offset_within_region + 116*108a6481SCindy Lu (iova - section->offset_within_address_space); 117*108a6481SCindy Lu 118*108a6481SCindy Lu llsize = int128_sub(llend, int128_make64(iova)); 119*108a6481SCindy Lu 120*108a6481SCindy Lu ret = vhost_vdpa_dma_map(v, iova, int128_get64(llsize), 121*108a6481SCindy Lu vaddr, section->readonly); 122*108a6481SCindy Lu if (ret) { 123*108a6481SCindy Lu error_report("vhost vdpa map fail!"); 124*108a6481SCindy Lu if (memory_region_is_ram_device(section->mr)) { 125*108a6481SCindy Lu /* Allow unexpected mappings not to be fatal for RAM devices */ 126*108a6481SCindy Lu error_report("map ram fail!"); 127*108a6481SCindy Lu return ; 128*108a6481SCindy Lu } 129*108a6481SCindy Lu goto fail; 130*108a6481SCindy Lu } 131*108a6481SCindy Lu 132*108a6481SCindy Lu return; 133*108a6481SCindy Lu 134*108a6481SCindy Lu fail: 135*108a6481SCindy Lu if (memory_region_is_ram_device(section->mr)) { 136*108a6481SCindy Lu error_report("failed to vdpa_dma_map. pci p2p may not work"); 137*108a6481SCindy Lu return; 138*108a6481SCindy Lu 139*108a6481SCindy Lu } 140*108a6481SCindy Lu /* 141*108a6481SCindy Lu * On the initfn path, store the first error in the container so we 142*108a6481SCindy Lu * can gracefully fail. Runtime, there's not much we can do other 143*108a6481SCindy Lu * than throw a hardware error. 144*108a6481SCindy Lu */ 145*108a6481SCindy Lu error_report("vhost-vdpa: DMA mapping failed, unable to continue"); 146*108a6481SCindy Lu return; 147*108a6481SCindy Lu 148*108a6481SCindy Lu } 149*108a6481SCindy Lu 150*108a6481SCindy Lu static void vhost_vdpa_listener_region_del(MemoryListener *listener, 151*108a6481SCindy Lu MemoryRegionSection *section) 152*108a6481SCindy Lu { 153*108a6481SCindy Lu struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); 154*108a6481SCindy Lu hwaddr iova; 155*108a6481SCindy Lu Int128 llend, llsize; 156*108a6481SCindy Lu int ret; 157*108a6481SCindy Lu bool try_unmap = true; 158*108a6481SCindy Lu 159*108a6481SCindy Lu if (vhost_vdpa_listener_skipped_section(section)) { 160*108a6481SCindy Lu return; 161*108a6481SCindy Lu } 162*108a6481SCindy Lu 163*108a6481SCindy Lu if (unlikely((section->offset_within_address_space & ~TARGET_PAGE_MASK) != 164*108a6481SCindy Lu (section->offset_within_region & ~TARGET_PAGE_MASK))) { 165*108a6481SCindy Lu error_report("%s received unaligned region", __func__); 166*108a6481SCindy Lu return; 167*108a6481SCindy Lu } 168*108a6481SCindy Lu 169*108a6481SCindy Lu iova = TARGET_PAGE_ALIGN(section->offset_within_address_space); 170*108a6481SCindy Lu llend = int128_make64(section->offset_within_address_space); 171*108a6481SCindy Lu llend = int128_add(llend, section->size); 172*108a6481SCindy Lu llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK)); 173*108a6481SCindy Lu 174*108a6481SCindy Lu if (int128_ge(int128_make64(iova), llend)) { 175*108a6481SCindy Lu return; 176*108a6481SCindy Lu } 177*108a6481SCindy Lu 178*108a6481SCindy Lu llsize = int128_sub(llend, int128_make64(iova)); 179*108a6481SCindy Lu 180*108a6481SCindy Lu if (try_unmap) { 181*108a6481SCindy Lu ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); 182*108a6481SCindy Lu if (ret) { 183*108a6481SCindy Lu error_report("vhost_vdpa dma unmap error!"); 184*108a6481SCindy Lu } 185*108a6481SCindy Lu } 186*108a6481SCindy Lu 187*108a6481SCindy Lu memory_region_unref(section->mr); 188*108a6481SCindy Lu } 189*108a6481SCindy Lu /* 190*108a6481SCindy Lu * IOTLB API is used by vhost-vpda which requires incremental updating 191*108a6481SCindy Lu * of the mapping. So we can not use generic vhost memory listener which 192*108a6481SCindy Lu * depends on the addnop(). 193*108a6481SCindy Lu */ 194*108a6481SCindy Lu static const MemoryListener vhost_vdpa_memory_listener = { 195*108a6481SCindy Lu .region_add = vhost_vdpa_listener_region_add, 196*108a6481SCindy Lu .region_del = vhost_vdpa_listener_region_del, 197*108a6481SCindy Lu }; 198*108a6481SCindy Lu 199*108a6481SCindy Lu static int vhost_vdpa_call(struct vhost_dev *dev, unsigned long int request, 200*108a6481SCindy Lu void *arg) 201*108a6481SCindy Lu { 202*108a6481SCindy Lu struct vhost_vdpa *v = dev->opaque; 203*108a6481SCindy Lu int fd = v->device_fd; 204*108a6481SCindy Lu 205*108a6481SCindy Lu assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); 206*108a6481SCindy Lu 207*108a6481SCindy Lu return ioctl(fd, request, arg); 208*108a6481SCindy Lu } 209*108a6481SCindy Lu 210*108a6481SCindy Lu static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status) 211*108a6481SCindy Lu { 212*108a6481SCindy Lu uint8_t s; 213*108a6481SCindy Lu 214*108a6481SCindy Lu if (vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &s)) { 215*108a6481SCindy Lu return; 216*108a6481SCindy Lu } 217*108a6481SCindy Lu 218*108a6481SCindy Lu s |= status; 219*108a6481SCindy Lu 220*108a6481SCindy Lu vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &s); 221*108a6481SCindy Lu } 222*108a6481SCindy Lu 223*108a6481SCindy Lu static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque) 224*108a6481SCindy Lu { 225*108a6481SCindy Lu struct vhost_vdpa *v; 226*108a6481SCindy Lu uint64_t features; 227*108a6481SCindy Lu assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); 228*108a6481SCindy Lu 229*108a6481SCindy Lu v = opaque; 230*108a6481SCindy Lu dev->opaque = opaque ; 231*108a6481SCindy Lu vhost_vdpa_call(dev, VHOST_GET_FEATURES, &features); 232*108a6481SCindy Lu dev->backend_features = features; 233*108a6481SCindy Lu v->listener = vhost_vdpa_memory_listener; 234*108a6481SCindy Lu v->msg_type = VHOST_IOTLB_MSG_V2; 235*108a6481SCindy Lu 236*108a6481SCindy Lu vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE | 237*108a6481SCindy Lu VIRTIO_CONFIG_S_DRIVER); 238*108a6481SCindy Lu 239*108a6481SCindy Lu return 0; 240*108a6481SCindy Lu } 241*108a6481SCindy Lu 242*108a6481SCindy Lu static int vhost_vdpa_cleanup(struct vhost_dev *dev) 243*108a6481SCindy Lu { 244*108a6481SCindy Lu struct vhost_vdpa *v; 245*108a6481SCindy Lu assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); 246*108a6481SCindy Lu v = dev->opaque; 247*108a6481SCindy Lu memory_listener_unregister(&v->listener); 248*108a6481SCindy Lu 249*108a6481SCindy Lu dev->opaque = NULL; 250*108a6481SCindy Lu return 0; 251*108a6481SCindy Lu } 252*108a6481SCindy Lu 253*108a6481SCindy Lu static int vhost_vdpa_memslots_limit(struct vhost_dev *dev) 254*108a6481SCindy Lu { 255*108a6481SCindy Lu return INT_MAX; 256*108a6481SCindy Lu } 257*108a6481SCindy Lu 258*108a6481SCindy Lu static int vhost_vdpa_set_mem_table(struct vhost_dev *dev, 259*108a6481SCindy Lu struct vhost_memory *mem) 260*108a6481SCindy Lu { 261*108a6481SCindy Lu 262*108a6481SCindy Lu if (mem->padding) { 263*108a6481SCindy Lu return -1; 264*108a6481SCindy Lu } 265*108a6481SCindy Lu 266*108a6481SCindy Lu return 0; 267*108a6481SCindy Lu } 268*108a6481SCindy Lu 269*108a6481SCindy Lu static int vhost_vdpa_set_features(struct vhost_dev *dev, 270*108a6481SCindy Lu uint64_t features) 271*108a6481SCindy Lu { 272*108a6481SCindy Lu int ret; 273*108a6481SCindy Lu ret = vhost_vdpa_call(dev, VHOST_SET_FEATURES, &features); 274*108a6481SCindy Lu uint8_t status = 0; 275*108a6481SCindy Lu if (ret) { 276*108a6481SCindy Lu return ret; 277*108a6481SCindy Lu } 278*108a6481SCindy Lu vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); 279*108a6481SCindy Lu vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status); 280*108a6481SCindy Lu 281*108a6481SCindy Lu return !(status & VIRTIO_CONFIG_S_FEATURES_OK); 282*108a6481SCindy Lu } 283*108a6481SCindy Lu 284*108a6481SCindy Lu int vhost_vdpa_get_device_id(struct vhost_dev *dev, 285*108a6481SCindy Lu uint32_t *device_id) 286*108a6481SCindy Lu { 287*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_VDPA_GET_DEVICE_ID, device_id); 288*108a6481SCindy Lu } 289*108a6481SCindy Lu 290*108a6481SCindy Lu static int vhost_vdpa_reset_device(struct vhost_dev *dev) 291*108a6481SCindy Lu { 292*108a6481SCindy Lu uint8_t status = 0; 293*108a6481SCindy Lu 294*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status); 295*108a6481SCindy Lu } 296*108a6481SCindy Lu 297*108a6481SCindy Lu static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, int idx) 298*108a6481SCindy Lu { 299*108a6481SCindy Lu assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs); 300*108a6481SCindy Lu 301*108a6481SCindy Lu return idx - dev->vq_index; 302*108a6481SCindy Lu } 303*108a6481SCindy Lu 304*108a6481SCindy Lu static int vhost_vdpa_set_vring_ready(struct vhost_dev *dev) 305*108a6481SCindy Lu { 306*108a6481SCindy Lu int i; 307*108a6481SCindy Lu for (i = 0; i < dev->nvqs; ++i) { 308*108a6481SCindy Lu struct vhost_vring_state state = { 309*108a6481SCindy Lu .index = dev->vq_index + i, 310*108a6481SCindy Lu .num = 1, 311*108a6481SCindy Lu }; 312*108a6481SCindy Lu vhost_vdpa_call(dev, VHOST_VDPA_SET_VRING_ENABLE, &state); 313*108a6481SCindy Lu } 314*108a6481SCindy Lu return 0; 315*108a6481SCindy Lu } 316*108a6481SCindy Lu 317*108a6481SCindy Lu static int vhost_vdpa_set_config(struct vhost_dev *dev, const uint8_t *data, 318*108a6481SCindy Lu uint32_t offset, uint32_t size, 319*108a6481SCindy Lu uint32_t flags) 320*108a6481SCindy Lu { 321*108a6481SCindy Lu struct vhost_vdpa_config *config; 322*108a6481SCindy Lu int ret; 323*108a6481SCindy Lu unsigned long config_size = offsetof(struct vhost_vdpa_config, buf); 324*108a6481SCindy Lu config = g_malloc(size + config_size); 325*108a6481SCindy Lu if (config == NULL) { 326*108a6481SCindy Lu return -1; 327*108a6481SCindy Lu } 328*108a6481SCindy Lu config->off = offset; 329*108a6481SCindy Lu config->len = size; 330*108a6481SCindy Lu memcpy(config->buf, data, size); 331*108a6481SCindy Lu ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_CONFIG, config); 332*108a6481SCindy Lu g_free(config); 333*108a6481SCindy Lu return ret; 334*108a6481SCindy Lu } 335*108a6481SCindy Lu 336*108a6481SCindy Lu static int vhost_vdpa_get_config(struct vhost_dev *dev, uint8_t *config, 337*108a6481SCindy Lu uint32_t config_len) 338*108a6481SCindy Lu { 339*108a6481SCindy Lu struct vhost_vdpa_config *v_config; 340*108a6481SCindy Lu unsigned long config_size = offsetof(struct vhost_vdpa_config, buf); 341*108a6481SCindy Lu int ret; 342*108a6481SCindy Lu 343*108a6481SCindy Lu v_config = g_malloc(config_len + config_size); 344*108a6481SCindy Lu if (v_config == NULL) { 345*108a6481SCindy Lu return -1; 346*108a6481SCindy Lu } 347*108a6481SCindy Lu v_config->len = config_len; 348*108a6481SCindy Lu v_config->off = 0; 349*108a6481SCindy Lu ret = vhost_vdpa_call(dev, VHOST_VDPA_GET_CONFIG, v_config); 350*108a6481SCindy Lu memcpy(config, v_config->buf, config_len); 351*108a6481SCindy Lu g_free(v_config); 352*108a6481SCindy Lu return ret; 353*108a6481SCindy Lu } 354*108a6481SCindy Lu 355*108a6481SCindy Lu static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) 356*108a6481SCindy Lu { 357*108a6481SCindy Lu struct vhost_vdpa *v = dev->opaque; 358*108a6481SCindy Lu if (started) { 359*108a6481SCindy Lu uint8_t status = 0; 360*108a6481SCindy Lu memory_listener_register(&v->listener, &address_space_memory); 361*108a6481SCindy Lu vhost_vdpa_set_vring_ready(dev); 362*108a6481SCindy Lu vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); 363*108a6481SCindy Lu vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status); 364*108a6481SCindy Lu 365*108a6481SCindy Lu return !(status & VIRTIO_CONFIG_S_DRIVER_OK); 366*108a6481SCindy Lu } else { 367*108a6481SCindy Lu vhost_vdpa_reset_device(dev); 368*108a6481SCindy Lu vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE | 369*108a6481SCindy Lu VIRTIO_CONFIG_S_DRIVER); 370*108a6481SCindy Lu memory_listener_unregister(&v->listener); 371*108a6481SCindy Lu 372*108a6481SCindy Lu return 0; 373*108a6481SCindy Lu } 374*108a6481SCindy Lu } 375*108a6481SCindy Lu 376*108a6481SCindy Lu static int vhost_vdpa_set_log_base(struct vhost_dev *dev, uint64_t base, 377*108a6481SCindy Lu struct vhost_log *log) 378*108a6481SCindy Lu { 379*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_SET_LOG_BASE, &base); 380*108a6481SCindy Lu } 381*108a6481SCindy Lu 382*108a6481SCindy Lu static int vhost_vdpa_set_vring_addr(struct vhost_dev *dev, 383*108a6481SCindy Lu struct vhost_vring_addr *addr) 384*108a6481SCindy Lu { 385*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_SET_VRING_ADDR, addr); 386*108a6481SCindy Lu } 387*108a6481SCindy Lu 388*108a6481SCindy Lu static int vhost_vdpa_set_vring_num(struct vhost_dev *dev, 389*108a6481SCindy Lu struct vhost_vring_state *ring) 390*108a6481SCindy Lu { 391*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_SET_VRING_NUM, ring); 392*108a6481SCindy Lu } 393*108a6481SCindy Lu 394*108a6481SCindy Lu static int vhost_vdpa_set_vring_base(struct vhost_dev *dev, 395*108a6481SCindy Lu struct vhost_vring_state *ring) 396*108a6481SCindy Lu { 397*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_SET_VRING_BASE, ring); 398*108a6481SCindy Lu } 399*108a6481SCindy Lu 400*108a6481SCindy Lu static int vhost_vdpa_get_vring_base(struct vhost_dev *dev, 401*108a6481SCindy Lu struct vhost_vring_state *ring) 402*108a6481SCindy Lu { 403*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_GET_VRING_BASE, ring); 404*108a6481SCindy Lu } 405*108a6481SCindy Lu 406*108a6481SCindy Lu static int vhost_vdpa_set_vring_kick(struct vhost_dev *dev, 407*108a6481SCindy Lu struct vhost_vring_file *file) 408*108a6481SCindy Lu { 409*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_SET_VRING_KICK, file); 410*108a6481SCindy Lu } 411*108a6481SCindy Lu 412*108a6481SCindy Lu static int vhost_vdpa_set_vring_call(struct vhost_dev *dev, 413*108a6481SCindy Lu struct vhost_vring_file *file) 414*108a6481SCindy Lu { 415*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_SET_VRING_CALL, file); 416*108a6481SCindy Lu } 417*108a6481SCindy Lu 418*108a6481SCindy Lu static int vhost_vdpa_get_features(struct vhost_dev *dev, 419*108a6481SCindy Lu uint64_t *features) 420*108a6481SCindy Lu { 421*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_GET_FEATURES, features); 422*108a6481SCindy Lu } 423*108a6481SCindy Lu 424*108a6481SCindy Lu static int vhost_vdpa_set_owner(struct vhost_dev *dev) 425*108a6481SCindy Lu { 426*108a6481SCindy Lu return vhost_vdpa_call(dev, VHOST_SET_OWNER, NULL); 427*108a6481SCindy Lu } 428*108a6481SCindy Lu 429*108a6481SCindy Lu static int vhost_vdpa_vq_get_addr(struct vhost_dev *dev, 430*108a6481SCindy Lu struct vhost_vring_addr *addr, struct vhost_virtqueue *vq) 431*108a6481SCindy Lu { 432*108a6481SCindy Lu assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA); 433*108a6481SCindy Lu addr->desc_user_addr = (uint64_t)(unsigned long)vq->desc_phys; 434*108a6481SCindy Lu addr->avail_user_addr = (uint64_t)(unsigned long)vq->avail_phys; 435*108a6481SCindy Lu addr->used_user_addr = (uint64_t)(unsigned long)vq->used_phys; 436*108a6481SCindy Lu return 0; 437*108a6481SCindy Lu } 438*108a6481SCindy Lu 439*108a6481SCindy Lu static bool vhost_vdpa_force_iommu(struct vhost_dev *dev) 440*108a6481SCindy Lu { 441*108a6481SCindy Lu return true; 442*108a6481SCindy Lu } 443*108a6481SCindy Lu 444*108a6481SCindy Lu const VhostOps vdpa_ops = { 445*108a6481SCindy Lu .backend_type = VHOST_BACKEND_TYPE_VDPA, 446*108a6481SCindy Lu .vhost_backend_init = vhost_vdpa_init, 447*108a6481SCindy Lu .vhost_backend_cleanup = vhost_vdpa_cleanup, 448*108a6481SCindy Lu .vhost_set_log_base = vhost_vdpa_set_log_base, 449*108a6481SCindy Lu .vhost_set_vring_addr = vhost_vdpa_set_vring_addr, 450*108a6481SCindy Lu .vhost_set_vring_num = vhost_vdpa_set_vring_num, 451*108a6481SCindy Lu .vhost_set_vring_base = vhost_vdpa_set_vring_base, 452*108a6481SCindy Lu .vhost_get_vring_base = vhost_vdpa_get_vring_base, 453*108a6481SCindy Lu .vhost_set_vring_kick = vhost_vdpa_set_vring_kick, 454*108a6481SCindy Lu .vhost_set_vring_call = vhost_vdpa_set_vring_call, 455*108a6481SCindy Lu .vhost_get_features = vhost_vdpa_get_features, 456*108a6481SCindy Lu .vhost_set_owner = vhost_vdpa_set_owner, 457*108a6481SCindy Lu .vhost_set_vring_endian = NULL, 458*108a6481SCindy Lu .vhost_backend_memslots_limit = vhost_vdpa_memslots_limit, 459*108a6481SCindy Lu .vhost_set_mem_table = vhost_vdpa_set_mem_table, 460*108a6481SCindy Lu .vhost_set_features = vhost_vdpa_set_features, 461*108a6481SCindy Lu .vhost_reset_device = vhost_vdpa_reset_device, 462*108a6481SCindy Lu .vhost_get_vq_index = vhost_vdpa_get_vq_index, 463*108a6481SCindy Lu .vhost_get_config = vhost_vdpa_get_config, 464*108a6481SCindy Lu .vhost_set_config = vhost_vdpa_set_config, 465*108a6481SCindy Lu .vhost_requires_shm_log = NULL, 466*108a6481SCindy Lu .vhost_migration_done = NULL, 467*108a6481SCindy Lu .vhost_backend_can_merge = NULL, 468*108a6481SCindy Lu .vhost_net_set_mtu = NULL, 469*108a6481SCindy Lu .vhost_set_iotlb_callback = NULL, 470*108a6481SCindy Lu .vhost_send_device_iotlb_msg = NULL, 471*108a6481SCindy Lu .vhost_dev_start = vhost_vdpa_dev_start, 472*108a6481SCindy Lu .vhost_get_device_id = vhost_vdpa_get_device_id, 473*108a6481SCindy Lu .vhost_vq_get_addr = vhost_vdpa_vq_get_addr, 474*108a6481SCindy Lu .vhost_force_iommu = vhost_vdpa_force_iommu, 475*108a6481SCindy Lu }; 476