1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
6 #include <linux/vfio.h>
7 #include <linux/cdx/cdx_bus.h>
11 static int vfio_cdx_open_device(struct vfio_device
*core_vdev
)
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
;
19 vdev
->regions
= kcalloc(count
, sizeof(struct vfio_cdx_region
),
24 for (i
= 0; i
< count
; i
++) {
25 struct resource
*res
= &cdx_dev
->res
[i
];
27 vdev
->regions
[i
].addr
= res
->start
;
28 vdev
->regions
[i
].size
= resource_size(res
);
29 vdev
->regions
[i
].type
= res
->flags
;
31 * Only regions addressed with PAGE granularity may be
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
;
42 ret
= cdx_dev_reset(core_vdev
->dev
);
48 ret
= cdx_clear_master(cdx_dev
);
50 vdev
->flags
&= ~BME_SUPPORT
;
52 vdev
->flags
|= BME_SUPPORT
;
57 static void vfio_cdx_close_device(struct vfio_device
*core_vdev
)
59 struct vfio_cdx_device
*vdev
=
60 container_of(core_vdev
, struct vfio_cdx_device
, vdev
);
63 cdx_dev_reset(core_vdev
->dev
);
64 vfio_cdx_irqs_cleanup(vdev
);
67 static int vfio_cdx_bm_ctrl(struct vfio_device
*core_vdev
, u32 flags
,
68 void __user
*arg
, size_t argsz
)
71 offsetofend(struct vfio_device_feature_bus_master
, op
);
72 struct vfio_cdx_device
*vdev
=
73 container_of(core_vdev
, struct vfio_cdx_device
, vdev
);
74 struct cdx_device
*cdx_dev
= to_cdx_device(core_vdev
->dev
);
75 struct vfio_device_feature_bus_master ops
;
78 if (!(vdev
->flags
& BME_SUPPORT
))
81 ret
= vfio_check_feature(flags
, argsz
, VFIO_DEVICE_FEATURE_SET
,
86 if (copy_from_user(&ops
, arg
, minsz
))
90 case VFIO_DEVICE_FEATURE_CLEAR_MASTER
:
91 return cdx_clear_master(cdx_dev
);
92 case VFIO_DEVICE_FEATURE_SET_MASTER
:
93 return cdx_set_master(cdx_dev
);
99 static int vfio_cdx_ioctl_feature(struct vfio_device
*device
, u32 flags
,
100 void __user
*arg
, size_t argsz
)
102 switch (flags
& VFIO_DEVICE_FEATURE_MASK
) {
103 case VFIO_DEVICE_FEATURE_BUS_MASTER
:
104 return vfio_cdx_bm_ctrl(device
, flags
, arg
, argsz
);
110 static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device
*vdev
,
111 struct vfio_device_info __user
*arg
)
113 unsigned long minsz
= offsetofend(struct vfio_device_info
, num_irqs
);
114 struct cdx_device
*cdx_dev
= to_cdx_device(vdev
->vdev
.dev
);
115 struct vfio_device_info info
;
117 if (copy_from_user(&info
, arg
, minsz
))
120 if (info
.argsz
< minsz
)
123 info
.flags
= VFIO_DEVICE_FLAGS_CDX
;
124 info
.flags
|= VFIO_DEVICE_FLAGS_RESET
;
126 info
.num_regions
= cdx_dev
->res_count
;
127 info
.num_irqs
= cdx_dev
->num_msi
? 1 : 0;
129 return copy_to_user(arg
, &info
, minsz
) ? -EFAULT
: 0;
132 static int vfio_cdx_ioctl_get_region_info(struct vfio_cdx_device
*vdev
,
133 struct vfio_region_info __user
*arg
)
135 unsigned long minsz
= offsetofend(struct vfio_region_info
, offset
);
136 struct cdx_device
*cdx_dev
= to_cdx_device(vdev
->vdev
.dev
);
137 struct vfio_region_info info
;
139 if (copy_from_user(&info
, arg
, minsz
))
142 if (info
.argsz
< minsz
)
145 if (info
.index
>= cdx_dev
->res_count
)
148 /* map offset to the physical address */
149 info
.offset
= vfio_cdx_index_to_offset(info
.index
);
150 info
.size
= vdev
->regions
[info
.index
].size
;
151 info
.flags
= vdev
->regions
[info
.index
].flags
;
153 return copy_to_user(arg
, &info
, minsz
) ? -EFAULT
: 0;
156 static int vfio_cdx_ioctl_get_irq_info(struct vfio_cdx_device
*vdev
,
157 struct vfio_irq_info __user
*arg
)
159 unsigned long minsz
= offsetofend(struct vfio_irq_info
, count
);
160 struct cdx_device
*cdx_dev
= to_cdx_device(vdev
->vdev
.dev
);
161 struct vfio_irq_info info
;
163 if (copy_from_user(&info
, arg
, minsz
))
166 if (info
.argsz
< minsz
)
172 if (!cdx_dev
->num_msi
)
175 info
.flags
= VFIO_IRQ_INFO_EVENTFD
| VFIO_IRQ_INFO_NORESIZE
;
176 info
.count
= cdx_dev
->num_msi
;
178 return copy_to_user(arg
, &info
, minsz
) ? -EFAULT
: 0;
181 static int vfio_cdx_ioctl_set_irqs(struct vfio_cdx_device
*vdev
,
182 struct vfio_irq_set __user
*arg
)
184 unsigned long minsz
= offsetofend(struct vfio_irq_set
, count
);
185 struct cdx_device
*cdx_dev
= to_cdx_device(vdev
->vdev
.dev
);
186 struct vfio_irq_set hdr
;
187 size_t data_size
= 0;
191 if (copy_from_user(&hdr
, arg
, minsz
))
194 ret
= vfio_set_irqs_validate_and_prepare(&hdr
, cdx_dev
->num_msi
,
200 data
= memdup_user(arg
->data
, data_size
);
202 return PTR_ERR(data
);
205 ret
= vfio_cdx_set_irqs_ioctl(vdev
, hdr
.flags
, hdr
.index
,
206 hdr
.start
, hdr
.count
, data
);
212 static long vfio_cdx_ioctl(struct vfio_device
*core_vdev
,
213 unsigned int cmd
, unsigned long arg
)
215 struct vfio_cdx_device
*vdev
=
216 container_of(core_vdev
, struct vfio_cdx_device
, vdev
);
217 void __user
*uarg
= (void __user
*)arg
;
220 case VFIO_DEVICE_GET_INFO
:
221 return vfio_cdx_ioctl_get_info(vdev
, uarg
);
222 case VFIO_DEVICE_GET_REGION_INFO
:
223 return vfio_cdx_ioctl_get_region_info(vdev
, uarg
);
224 case VFIO_DEVICE_GET_IRQ_INFO
:
225 return vfio_cdx_ioctl_get_irq_info(vdev
, uarg
);
226 case VFIO_DEVICE_SET_IRQS
:
227 return vfio_cdx_ioctl_set_irqs(vdev
, uarg
);
228 case VFIO_DEVICE_RESET
:
229 return cdx_dev_reset(core_vdev
->dev
);
235 static int vfio_cdx_mmap_mmio(struct vfio_cdx_region region
,
236 struct vm_area_struct
*vma
)
238 u64 size
= vma
->vm_end
- vma
->vm_start
;
241 pgoff
= vma
->vm_pgoff
&
242 ((1U << (VFIO_CDX_OFFSET_SHIFT
- PAGE_SHIFT
)) - 1);
243 base
= pgoff
<< PAGE_SHIFT
;
245 if (base
+ size
> region
.size
)
248 vma
->vm_pgoff
= (region
.addr
>> PAGE_SHIFT
) + pgoff
;
249 vma
->vm_page_prot
= pgprot_device(vma
->vm_page_prot
);
251 return io_remap_pfn_range(vma
, vma
->vm_start
, vma
->vm_pgoff
,
252 size
, vma
->vm_page_prot
);
255 static int vfio_cdx_mmap(struct vfio_device
*core_vdev
,
256 struct vm_area_struct
*vma
)
258 struct vfio_cdx_device
*vdev
=
259 container_of(core_vdev
, struct vfio_cdx_device
, vdev
);
260 struct cdx_device
*cdx_dev
= to_cdx_device(core_vdev
->dev
);
263 index
= vma
->vm_pgoff
>> (VFIO_CDX_OFFSET_SHIFT
- PAGE_SHIFT
);
265 if (index
>= cdx_dev
->res_count
)
268 if (!(vdev
->regions
[index
].flags
& VFIO_REGION_INFO_FLAG_MMAP
))
271 if (!(vdev
->regions
[index
].flags
& VFIO_REGION_INFO_FLAG_READ
) &&
272 (vma
->vm_flags
& VM_READ
))
275 if (!(vdev
->regions
[index
].flags
& VFIO_REGION_INFO_FLAG_WRITE
) &&
276 (vma
->vm_flags
& VM_WRITE
))
279 return vfio_cdx_mmap_mmio(vdev
->regions
[index
], vma
);
282 static const struct vfio_device_ops vfio_cdx_ops
= {
284 .open_device
= vfio_cdx_open_device
,
285 .close_device
= vfio_cdx_close_device
,
286 .ioctl
= vfio_cdx_ioctl
,
287 .device_feature
= vfio_cdx_ioctl_feature
,
288 .mmap
= vfio_cdx_mmap
,
289 .bind_iommufd
= vfio_iommufd_physical_bind
,
290 .unbind_iommufd
= vfio_iommufd_physical_unbind
,
291 .attach_ioas
= vfio_iommufd_physical_attach_ioas
,
294 static int vfio_cdx_probe(struct cdx_device
*cdx_dev
)
296 struct vfio_cdx_device
*vdev
;
297 struct device
*dev
= &cdx_dev
->dev
;
300 vdev
= vfio_alloc_device(vfio_cdx_device
, vdev
, dev
,
303 return PTR_ERR(vdev
);
305 ret
= vfio_register_group_dev(&vdev
->vdev
);
309 dev_set_drvdata(dev
, vdev
);
313 vfio_put_device(&vdev
->vdev
);
317 static int vfio_cdx_remove(struct cdx_device
*cdx_dev
)
319 struct device
*dev
= &cdx_dev
->dev
;
320 struct vfio_cdx_device
*vdev
= dev_get_drvdata(dev
);
322 vfio_unregister_group_dev(&vdev
->vdev
);
323 vfio_put_device(&vdev
->vdev
);
328 static const struct cdx_device_id vfio_cdx_table
[] = {
329 { CDX_DEVICE_DRIVER_OVERRIDE(CDX_ANY_ID
, CDX_ANY_ID
,
330 CDX_ID_F_VFIO_DRIVER_OVERRIDE
) }, /* match all by default */
334 MODULE_DEVICE_TABLE(cdx
, vfio_cdx_table
);
336 static struct cdx_driver vfio_cdx_driver
= {
337 .probe
= vfio_cdx_probe
,
338 .remove
= vfio_cdx_remove
,
339 .match_id_table
= vfio_cdx_table
,
343 .driver_managed_dma
= true,
346 module_driver(vfio_cdx_driver
, cdx_driver_register
, cdx_driver_unregister
);
348 MODULE_LICENSE("GPL");
349 MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver");
350 MODULE_IMPORT_NS(CDX_BUS
);