1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc. 4 */ 5 6 #include <linux/vfio.h> 7 #include <linux/cdx/cdx_bus.h> 8 9 #include "private.h" 10 11 static int vfio_cdx_open_device(struct vfio_device *core_vdev) 12 { 13 struct vfio_cdx_device *vdev = 14 container_of(core_vdev, struct vfio_cdx_device, vdev); 15 struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev); 16 int count = cdx_dev->res_count; 17 int i, ret; 18 19 vdev->regions = kcalloc(count, sizeof(struct vfio_cdx_region), 20 GFP_KERNEL_ACCOUNT); 21 if (!vdev->regions) 22 return -ENOMEM; 23 24 for (i = 0; i < count; i++) { 25 struct resource *res = &cdx_dev->res[i]; 26 27 vdev->regions[i].addr = res->start; 28 vdev->regions[i].size = resource_size(res); 29 vdev->regions[i].type = res->flags; 30 /* 31 * Only regions addressed with PAGE granularity may be 32 * MMAP'ed securely. 33 */ 34 if (!(vdev->regions[i].addr & ~PAGE_MASK) && 35 !(vdev->regions[i].size & ~PAGE_MASK)) 36 vdev->regions[i].flags |= 37 VFIO_REGION_INFO_FLAG_MMAP; 38 vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ; 39 if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY)) 40 vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE; 41 } 42 ret = cdx_dev_reset(core_vdev->dev); 43 if (ret) { 44 kfree(vdev->regions); 45 vdev->regions = NULL; 46 return ret; 47 } 48 ret = cdx_clear_master(cdx_dev); 49 if (ret) 50 vdev->flags &= ~BME_SUPPORT; 51 else 52 vdev->flags |= BME_SUPPORT; 53 54 return 0; 55 } 56 57 static void vfio_cdx_close_device(struct vfio_device *core_vdev) 58 { 59 struct vfio_cdx_device *vdev = 60 container_of(core_vdev, struct vfio_cdx_device, vdev); 61 62 kfree(vdev->regions); 63 cdx_dev_reset(core_vdev->dev); 64 } 65 66 static int vfio_cdx_bm_ctrl(struct vfio_device *core_vdev, u32 flags, 67 void __user *arg, size_t argsz) 68 { 69 size_t minsz = 70 offsetofend(struct vfio_device_feature_bus_master, op); 71 struct vfio_cdx_device *vdev = 72 container_of(core_vdev, struct vfio_cdx_device, vdev); 73 struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev); 74 struct vfio_device_feature_bus_master ops; 75 int ret; 76 77 if (!(vdev->flags & BME_SUPPORT)) 78 return -ENOTTY; 79 80 ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET, 81 sizeof(ops)); 82 if (ret != 1) 83 return ret; 84 85 if (copy_from_user(&ops, arg, minsz)) 86 return -EFAULT; 87 88 switch (ops.op) { 89 case VFIO_DEVICE_FEATURE_CLEAR_MASTER: 90 return cdx_clear_master(cdx_dev); 91 case VFIO_DEVICE_FEATURE_SET_MASTER: 92 return cdx_set_master(cdx_dev); 93 default: 94 return -EINVAL; 95 } 96 } 97 98 static int vfio_cdx_ioctl_feature(struct vfio_device *device, u32 flags, 99 void __user *arg, size_t argsz) 100 { 101 switch (flags & VFIO_DEVICE_FEATURE_MASK) { 102 case VFIO_DEVICE_FEATURE_BUS_MASTER: 103 return vfio_cdx_bm_ctrl(device, flags, arg, argsz); 104 default: 105 return -ENOTTY; 106 } 107 } 108 109 static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device *vdev, 110 struct vfio_device_info __user *arg) 111 { 112 unsigned long minsz = offsetofend(struct vfio_device_info, num_irqs); 113 struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev); 114 struct vfio_device_info info; 115 116 if (copy_from_user(&info, arg, minsz)) 117 return -EFAULT; 118 119 if (info.argsz < minsz) 120 return -EINVAL; 121 122 info.flags = VFIO_DEVICE_FLAGS_CDX; 123 info.flags |= VFIO_DEVICE_FLAGS_RESET; 124 125 info.num_regions = cdx_dev->res_count; 126 info.num_irqs = 0; 127 128 return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; 129 } 130 131 static int vfio_cdx_ioctl_get_region_info(struct vfio_cdx_device *vdev, 132 struct vfio_region_info __user *arg) 133 { 134 unsigned long minsz = offsetofend(struct vfio_region_info, offset); 135 struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev); 136 struct vfio_region_info info; 137 138 if (copy_from_user(&info, arg, minsz)) 139 return -EFAULT; 140 141 if (info.argsz < minsz) 142 return -EINVAL; 143 144 if (info.index >= cdx_dev->res_count) 145 return -EINVAL; 146 147 /* map offset to the physical address */ 148 info.offset = vfio_cdx_index_to_offset(info.index); 149 info.size = vdev->regions[info.index].size; 150 info.flags = vdev->regions[info.index].flags; 151 152 return copy_to_user(arg, &info, minsz) ? -EFAULT : 0; 153 } 154 155 static long vfio_cdx_ioctl(struct vfio_device *core_vdev, 156 unsigned int cmd, unsigned long arg) 157 { 158 struct vfio_cdx_device *vdev = 159 container_of(core_vdev, struct vfio_cdx_device, vdev); 160 void __user *uarg = (void __user *)arg; 161 162 switch (cmd) { 163 case VFIO_DEVICE_GET_INFO: 164 return vfio_cdx_ioctl_get_info(vdev, uarg); 165 case VFIO_DEVICE_GET_REGION_INFO: 166 return vfio_cdx_ioctl_get_region_info(vdev, uarg); 167 case VFIO_DEVICE_RESET: 168 return cdx_dev_reset(core_vdev->dev); 169 default: 170 return -ENOTTY; 171 } 172 } 173 174 static int vfio_cdx_mmap_mmio(struct vfio_cdx_region region, 175 struct vm_area_struct *vma) 176 { 177 u64 size = vma->vm_end - vma->vm_start; 178 u64 pgoff, base; 179 180 pgoff = vma->vm_pgoff & 181 ((1U << (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT)) - 1); 182 base = pgoff << PAGE_SHIFT; 183 184 if (base + size > region.size) 185 return -EINVAL; 186 187 vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff; 188 vma->vm_page_prot = pgprot_device(vma->vm_page_prot); 189 190 return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, 191 size, vma->vm_page_prot); 192 } 193 194 static int vfio_cdx_mmap(struct vfio_device *core_vdev, 195 struct vm_area_struct *vma) 196 { 197 struct vfio_cdx_device *vdev = 198 container_of(core_vdev, struct vfio_cdx_device, vdev); 199 struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev); 200 unsigned int index; 201 202 index = vma->vm_pgoff >> (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT); 203 204 if (index >= cdx_dev->res_count) 205 return -EINVAL; 206 207 if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP)) 208 return -EINVAL; 209 210 if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ) && 211 (vma->vm_flags & VM_READ)) 212 return -EPERM; 213 214 if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE) && 215 (vma->vm_flags & VM_WRITE)) 216 return -EPERM; 217 218 return vfio_cdx_mmap_mmio(vdev->regions[index], vma); 219 } 220 221 static const struct vfio_device_ops vfio_cdx_ops = { 222 .name = "vfio-cdx", 223 .open_device = vfio_cdx_open_device, 224 .close_device = vfio_cdx_close_device, 225 .ioctl = vfio_cdx_ioctl, 226 .device_feature = vfio_cdx_ioctl_feature, 227 .mmap = vfio_cdx_mmap, 228 .bind_iommufd = vfio_iommufd_physical_bind, 229 .unbind_iommufd = vfio_iommufd_physical_unbind, 230 .attach_ioas = vfio_iommufd_physical_attach_ioas, 231 }; 232 233 static int vfio_cdx_probe(struct cdx_device *cdx_dev) 234 { 235 struct vfio_cdx_device *vdev; 236 struct device *dev = &cdx_dev->dev; 237 int ret; 238 239 vdev = vfio_alloc_device(vfio_cdx_device, vdev, dev, 240 &vfio_cdx_ops); 241 if (IS_ERR(vdev)) 242 return PTR_ERR(vdev); 243 244 ret = vfio_register_group_dev(&vdev->vdev); 245 if (ret) 246 goto out_uninit; 247 248 dev_set_drvdata(dev, vdev); 249 return 0; 250 251 out_uninit: 252 vfio_put_device(&vdev->vdev); 253 return ret; 254 } 255 256 static int vfio_cdx_remove(struct cdx_device *cdx_dev) 257 { 258 struct device *dev = &cdx_dev->dev; 259 struct vfio_cdx_device *vdev = dev_get_drvdata(dev); 260 261 vfio_unregister_group_dev(&vdev->vdev); 262 vfio_put_device(&vdev->vdev); 263 264 return 0; 265 } 266 267 static const struct cdx_device_id vfio_cdx_table[] = { 268 { CDX_DEVICE_DRIVER_OVERRIDE(CDX_ANY_ID, CDX_ANY_ID, 269 CDX_ID_F_VFIO_DRIVER_OVERRIDE) }, /* match all by default */ 270 {} 271 }; 272 273 MODULE_DEVICE_TABLE(cdx, vfio_cdx_table); 274 275 static struct cdx_driver vfio_cdx_driver = { 276 .probe = vfio_cdx_probe, 277 .remove = vfio_cdx_remove, 278 .match_id_table = vfio_cdx_table, 279 .driver = { 280 .name = "vfio-cdx", 281 }, 282 .driver_managed_dma = true, 283 }; 284 285 module_driver(vfio_cdx_driver, cdx_driver_register, cdx_driver_unregister); 286 287 MODULE_LICENSE("GPL"); 288 MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver"); 289 MODULE_IMPORT_NS(CDX_BUS); 290