1 /* 2 * Container for vfio-user IOMMU type: rather than communicating with the kernel 3 * vfio driver, we communicate over a socket to a server using the vfio-user 4 * protocol. 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #include <sys/ioctl.h> 10 #include <linux/vfio.h> 11 #include "qemu/osdep.h" 12 13 #include "hw/vfio-user/container.h" 14 #include "hw/vfio-user/device.h" 15 #include "hw/vfio/vfio-cpr.h" 16 #include "hw/vfio/vfio-device.h" 17 #include "hw/vfio/vfio-listener.h" 18 #include "qapi/error.h" 19 20 static int vfio_user_dma_unmap(const VFIOContainerBase *bcontainer, 21 hwaddr iova, ram_addr_t size, 22 IOMMUTLBEntry *iotlb, bool unmap_all) 23 { 24 return -ENOTSUP; 25 } 26 27 static int vfio_user_dma_map(const VFIOContainerBase *bcontainer, hwaddr iova, 28 ram_addr_t size, void *vaddr, bool readonly, 29 MemoryRegion *mrp) 30 { 31 return -ENOTSUP; 32 } 33 34 static int 35 vfio_user_set_dirty_page_tracking(const VFIOContainerBase *bcontainer, 36 bool start, Error **errp) 37 { 38 error_setg_errno(errp, ENOTSUP, "Not supported"); 39 return -ENOTSUP; 40 } 41 42 static int vfio_user_query_dirty_bitmap(const VFIOContainerBase *bcontainer, 43 VFIOBitmap *vbmap, hwaddr iova, 44 hwaddr size, Error **errp) 45 { 46 error_setg_errno(errp, ENOTSUP, "Not supported"); 47 return -ENOTSUP; 48 } 49 50 static bool vfio_user_setup(VFIOContainerBase *bcontainer, Error **errp) 51 { 52 VFIOUserContainer *container = container_of(bcontainer, VFIOUserContainer, 53 bcontainer); 54 55 assert(container->proxy->dma_pgsizes != 0); 56 bcontainer->pgsizes = container->proxy->dma_pgsizes; 57 bcontainer->dma_max_mappings = container->proxy->max_dma; 58 59 /* No live migration support yet. */ 60 bcontainer->dirty_pages_supported = false; 61 bcontainer->max_dirty_bitmap_size = container->proxy->max_bitmap; 62 bcontainer->dirty_pgsizes = container->proxy->migr_pgsize; 63 64 return true; 65 } 66 67 static VFIOUserContainer *vfio_user_create_container(VFIODevice *vbasedev, 68 Error **errp) 69 { 70 VFIOUserContainer *container; 71 72 container = VFIO_IOMMU_USER(object_new(TYPE_VFIO_IOMMU_USER)); 73 container->proxy = vbasedev->proxy; 74 return container; 75 } 76 77 /* 78 * Try to mirror vfio_container_connect() as much as possible. 79 */ 80 static VFIOUserContainer * 81 vfio_user_container_connect(AddressSpace *as, VFIODevice *vbasedev, 82 Error **errp) 83 { 84 VFIOContainerBase *bcontainer; 85 VFIOUserContainer *container; 86 VFIOAddressSpace *space; 87 VFIOIOMMUClass *vioc; 88 int ret; 89 90 space = vfio_address_space_get(as); 91 92 container = vfio_user_create_container(vbasedev, errp); 93 if (!container) { 94 goto put_space_exit; 95 } 96 97 bcontainer = &container->bcontainer; 98 99 if (!vfio_cpr_register_container(bcontainer, errp)) { 100 goto free_container_exit; 101 } 102 103 ret = ram_block_uncoordinated_discard_disable(true); 104 if (ret) { 105 error_setg_errno(errp, -ret, "Cannot set discarding of RAM broken"); 106 goto unregister_container_exit; 107 } 108 109 vioc = VFIO_IOMMU_GET_CLASS(bcontainer); 110 assert(vioc->setup); 111 112 if (!vioc->setup(bcontainer, errp)) { 113 goto enable_discards_exit; 114 } 115 116 vfio_address_space_insert(space, bcontainer); 117 118 if (!vfio_listener_register(bcontainer, errp)) { 119 goto listener_release_exit; 120 } 121 122 bcontainer->initialized = true; 123 124 return container; 125 126 listener_release_exit: 127 vfio_listener_unregister(bcontainer); 128 if (vioc->release) { 129 vioc->release(bcontainer); 130 } 131 132 enable_discards_exit: 133 ram_block_uncoordinated_discard_disable(false); 134 135 unregister_container_exit: 136 vfio_cpr_unregister_container(bcontainer); 137 138 free_container_exit: 139 object_unref(container); 140 141 put_space_exit: 142 vfio_address_space_put(space); 143 144 return NULL; 145 } 146 147 static void vfio_user_container_disconnect(VFIOUserContainer *container) 148 { 149 VFIOContainerBase *bcontainer = &container->bcontainer; 150 VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer); 151 VFIOAddressSpace *space = bcontainer->space; 152 153 ram_block_uncoordinated_discard_disable(false); 154 155 vfio_listener_unregister(bcontainer); 156 if (vioc->release) { 157 vioc->release(bcontainer); 158 } 159 160 vfio_cpr_unregister_container(bcontainer); 161 object_unref(container); 162 163 vfio_address_space_put(space); 164 } 165 166 static bool vfio_user_device_get(VFIOUserContainer *container, 167 VFIODevice *vbasedev, Error **errp) 168 { 169 struct vfio_device_info info = { .argsz = sizeof(info) }; 170 171 172 if (!vfio_user_get_device_info(vbasedev->proxy, &info, errp)) { 173 return false; 174 } 175 176 vbasedev->fd = -1; 177 178 vfio_device_prepare(vbasedev, &container->bcontainer, &info); 179 180 return true; 181 } 182 183 /* 184 * vfio_user_device_attach: attach a device to a new container. 185 */ 186 static bool vfio_user_device_attach(const char *name, VFIODevice *vbasedev, 187 AddressSpace *as, Error **errp) 188 { 189 VFIOUserContainer *container; 190 191 container = vfio_user_container_connect(as, vbasedev, errp); 192 if (container == NULL) { 193 error_prepend(errp, "failed to connect proxy"); 194 return false; 195 } 196 197 return vfio_user_device_get(container, vbasedev, errp); 198 } 199 200 static void vfio_user_device_detach(VFIODevice *vbasedev) 201 { 202 VFIOUserContainer *container = container_of(vbasedev->bcontainer, 203 VFIOUserContainer, bcontainer); 204 205 vfio_device_unprepare(vbasedev); 206 207 vfio_user_container_disconnect(container); 208 } 209 210 static int vfio_user_pci_hot_reset(VFIODevice *vbasedev, bool single) 211 { 212 /* ->needs_reset is always false for vfio-user. */ 213 return 0; 214 } 215 216 static void vfio_iommu_user_class_init(ObjectClass *klass, const void *data) 217 { 218 VFIOIOMMUClass *vioc = VFIO_IOMMU_CLASS(klass); 219 220 vioc->setup = vfio_user_setup; 221 vioc->dma_map = vfio_user_dma_map; 222 vioc->dma_unmap = vfio_user_dma_unmap; 223 vioc->attach_device = vfio_user_device_attach; 224 vioc->detach_device = vfio_user_device_detach; 225 vioc->set_dirty_page_tracking = vfio_user_set_dirty_page_tracking; 226 vioc->query_dirty_bitmap = vfio_user_query_dirty_bitmap; 227 vioc->pci_hot_reset = vfio_user_pci_hot_reset; 228 }; 229 230 static const TypeInfo types[] = { 231 { 232 .name = TYPE_VFIO_IOMMU_USER, 233 .parent = TYPE_VFIO_IOMMU, 234 .instance_size = sizeof(VFIOUserContainer), 235 .class_init = vfio_iommu_user_class_init, 236 }, 237 }; 238 239 DEFINE_TYPES(types) 240