xref: /linux/drivers/vfio/cdx/main.c (revision 670e8864b1a218d72f08db40d0103adf38fa1d9b)
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_init_dev(struct vfio_device *core_vdev)
12 {
13 	struct vfio_cdx_device *vdev =
14 		container_of(core_vdev, struct vfio_cdx_device, vdev);
15 
16 	mutex_init(&vdev->cdx_irqs_lock);
17 	return 0;
18 }
19 
20 static void vfio_cdx_release_dev(struct vfio_device *core_vdev)
21 {
22 	struct vfio_cdx_device *vdev =
23 		container_of(core_vdev, struct vfio_cdx_device, vdev);
24 
25 	mutex_destroy(&vdev->cdx_irqs_lock);
26 }
27 
28 static int vfio_cdx_open_device(struct vfio_device *core_vdev)
29 {
30 	struct vfio_cdx_device *vdev =
31 		container_of(core_vdev, struct vfio_cdx_device, vdev);
32 	struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
33 	int count = cdx_dev->res_count;
34 	int i, ret;
35 
36 	vdev->regions = kzalloc_objs(struct vfio_cdx_region, count,
37 				     GFP_KERNEL_ACCOUNT);
38 	if (!vdev->regions)
39 		return -ENOMEM;
40 
41 	for (i = 0; i < count; i++) {
42 		struct resource *res = &cdx_dev->res[i];
43 
44 		vdev->regions[i].addr = res->start;
45 		vdev->regions[i].size = resource_size(res);
46 		vdev->regions[i].type = res->flags;
47 		/*
48 		 * Only regions addressed with PAGE granularity may be
49 		 * MMAP'ed securely.
50 		 */
51 		if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
52 		    !(vdev->regions[i].size & ~PAGE_MASK))
53 			vdev->regions[i].flags |=
54 					VFIO_REGION_INFO_FLAG_MMAP;
55 		vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
56 		if (!(cdx_dev->res[i].flags & IORESOURCE_READONLY))
57 			vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE;
58 	}
59 	ret = cdx_dev_reset(core_vdev->dev);
60 	if (ret) {
61 		kfree(vdev->regions);
62 		vdev->regions = NULL;
63 		return ret;
64 	}
65 	ret = cdx_clear_master(cdx_dev);
66 	if (ret)
67 		vdev->flags &= ~BME_SUPPORT;
68 	else
69 		vdev->flags |= BME_SUPPORT;
70 
71 	return 0;
72 }
73 
74 static void vfio_cdx_close_device(struct vfio_device *core_vdev)
75 {
76 	struct vfio_cdx_device *vdev =
77 		container_of(core_vdev, struct vfio_cdx_device, vdev);
78 
79 	kfree(vdev->regions);
80 	cdx_dev_reset(core_vdev->dev);
81 	vfio_cdx_irqs_cleanup(vdev);
82 }
83 
84 static int vfio_cdx_bm_ctrl(struct vfio_device *core_vdev, u32 flags,
85 			    void __user *arg, size_t argsz)
86 {
87 	size_t minsz =
88 		offsetofend(struct vfio_device_feature_bus_master, op);
89 	struct vfio_cdx_device *vdev =
90 		container_of(core_vdev, struct vfio_cdx_device, vdev);
91 	struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
92 	struct vfio_device_feature_bus_master ops;
93 	int ret;
94 
95 	if (!(vdev->flags & BME_SUPPORT))
96 		return -ENOTTY;
97 
98 	ret = vfio_check_feature(flags, argsz, VFIO_DEVICE_FEATURE_SET,
99 				 sizeof(ops));
100 	if (ret != 1)
101 		return ret;
102 
103 	if (copy_from_user(&ops, arg, minsz))
104 		return -EFAULT;
105 
106 	switch (ops.op) {
107 	case VFIO_DEVICE_FEATURE_CLEAR_MASTER:
108 		return cdx_clear_master(cdx_dev);
109 	case VFIO_DEVICE_FEATURE_SET_MASTER:
110 		return cdx_set_master(cdx_dev);
111 	default:
112 		return -EINVAL;
113 	}
114 }
115 
116 static int vfio_cdx_ioctl_feature(struct vfio_device *device, u32 flags,
117 				  void __user *arg, size_t argsz)
118 {
119 	switch (flags & VFIO_DEVICE_FEATURE_MASK) {
120 	case VFIO_DEVICE_FEATURE_BUS_MASTER:
121 		return vfio_cdx_bm_ctrl(device, flags, arg, argsz);
122 	default:
123 		return -ENOTTY;
124 	}
125 }
126 
127 static int vfio_cdx_ioctl_get_info(struct vfio_cdx_device *vdev,
128 				   struct vfio_device_info __user *arg)
129 {
130 	unsigned long minsz = offsetofend(struct vfio_device_info, num_irqs);
131 	struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
132 	struct vfio_device_info info;
133 
134 	if (copy_from_user(&info, arg, minsz))
135 		return -EFAULT;
136 
137 	if (info.argsz < minsz)
138 		return -EINVAL;
139 
140 	info.flags = VFIO_DEVICE_FLAGS_CDX;
141 	info.flags |= VFIO_DEVICE_FLAGS_RESET;
142 
143 	info.num_regions = cdx_dev->res_count;
144 	info.num_irqs = cdx_dev->num_msi ? 1 : 0;
145 
146 	return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
147 }
148 
149 static int vfio_cdx_ioctl_get_region_info(struct vfio_device *core_vdev,
150 					  struct vfio_region_info *info,
151 					  struct vfio_info_cap *caps)
152 {
153 	struct vfio_cdx_device *vdev =
154 		container_of(core_vdev, struct vfio_cdx_device, vdev);
155 	struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
156 
157 	if (info->index >= cdx_dev->res_count)
158 		return -EINVAL;
159 
160 	/* map offset to the physical address */
161 	info->offset = vfio_cdx_index_to_offset(info->index);
162 	info->size = vdev->regions[info->index].size;
163 	info->flags = vdev->regions[info->index].flags;
164 	return 0;
165 }
166 
167 static int vfio_cdx_ioctl_get_irq_info(struct vfio_cdx_device *vdev,
168 				       struct vfio_irq_info __user *arg)
169 {
170 	unsigned long minsz = offsetofend(struct vfio_irq_info, count);
171 	struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
172 	struct vfio_irq_info info;
173 
174 	if (copy_from_user(&info, arg, minsz))
175 		return -EFAULT;
176 
177 	if (info.argsz < minsz)
178 		return -EINVAL;
179 
180 	if (info.index >= 1)
181 		return -EINVAL;
182 
183 	if (!cdx_dev->num_msi)
184 		return -EINVAL;
185 
186 	info.flags = VFIO_IRQ_INFO_EVENTFD | VFIO_IRQ_INFO_NORESIZE;
187 	info.count = cdx_dev->num_msi;
188 
189 	return copy_to_user(arg, &info, minsz) ? -EFAULT : 0;
190 }
191 
192 static int vfio_cdx_ioctl_set_irqs(struct vfio_cdx_device *vdev,
193 				   struct vfio_irq_set __user *arg)
194 {
195 	unsigned long minsz = offsetofend(struct vfio_irq_set, count);
196 	struct cdx_device *cdx_dev = to_cdx_device(vdev->vdev.dev);
197 	struct vfio_irq_set hdr;
198 	size_t data_size = 0;
199 	u8 *data = NULL;
200 	int ret = 0;
201 
202 	if (copy_from_user(&hdr, arg, minsz))
203 		return -EFAULT;
204 
205 	ret = vfio_set_irqs_validate_and_prepare(&hdr, cdx_dev->num_msi,
206 						 1, &data_size);
207 	if (ret)
208 		return ret;
209 
210 	if (data_size) {
211 		data = memdup_user(arg->data, data_size);
212 		if (IS_ERR(data))
213 			return PTR_ERR(data);
214 	}
215 
216 	ret = vfio_cdx_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
217 				      hdr.start, hdr.count, data);
218 	kfree(data);
219 
220 	return ret;
221 }
222 
223 static long vfio_cdx_ioctl(struct vfio_device *core_vdev,
224 			   unsigned int cmd, unsigned long arg)
225 {
226 	struct vfio_cdx_device *vdev =
227 		container_of(core_vdev, struct vfio_cdx_device, vdev);
228 	void __user *uarg = (void __user *)arg;
229 
230 	switch (cmd) {
231 	case VFIO_DEVICE_GET_INFO:
232 		return vfio_cdx_ioctl_get_info(vdev, uarg);
233 	case VFIO_DEVICE_GET_IRQ_INFO:
234 		return vfio_cdx_ioctl_get_irq_info(vdev, uarg);
235 	case VFIO_DEVICE_SET_IRQS:
236 		return vfio_cdx_ioctl_set_irqs(vdev, uarg);
237 	case VFIO_DEVICE_RESET:
238 		return cdx_dev_reset(core_vdev->dev);
239 	default:
240 		return -ENOTTY;
241 	}
242 }
243 
244 static int vfio_cdx_mmap_mmio(struct vfio_cdx_region region,
245 			      struct vm_area_struct *vma)
246 {
247 	u64 size = vma->vm_end - vma->vm_start;
248 	u64 pgoff, base;
249 
250 	pgoff = vma->vm_pgoff &
251 		((1U << (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
252 	base = pgoff << PAGE_SHIFT;
253 
254 	if (base + size > region.size)
255 		return -EINVAL;
256 
257 	vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
258 	vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
259 
260 	return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
261 				  size, vma->vm_page_prot);
262 }
263 
264 static int vfio_cdx_mmap(struct vfio_device *core_vdev,
265 			 struct vm_area_struct *vma)
266 {
267 	struct vfio_cdx_device *vdev =
268 		container_of(core_vdev, struct vfio_cdx_device, vdev);
269 	struct cdx_device *cdx_dev = to_cdx_device(core_vdev->dev);
270 	unsigned int index;
271 
272 	index = vma->vm_pgoff >> (VFIO_CDX_OFFSET_SHIFT - PAGE_SHIFT);
273 
274 	if (index >= cdx_dev->res_count)
275 		return -EINVAL;
276 
277 	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
278 		return -EINVAL;
279 
280 	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ) &&
281 	    (vma->vm_flags & VM_READ))
282 		return -EPERM;
283 
284 	if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE) &&
285 	    (vma->vm_flags & VM_WRITE))
286 		return -EPERM;
287 
288 	return vfio_cdx_mmap_mmio(vdev->regions[index], vma);
289 }
290 
291 static const struct vfio_device_ops vfio_cdx_ops = {
292 	.name		= "vfio-cdx",
293 	.init		= vfio_cdx_init_dev,
294 	.release	= vfio_cdx_release_dev,
295 	.open_device	= vfio_cdx_open_device,
296 	.close_device	= vfio_cdx_close_device,
297 	.ioctl		= vfio_cdx_ioctl,
298 	.get_region_info_caps = vfio_cdx_ioctl_get_region_info,
299 	.device_feature = vfio_cdx_ioctl_feature,
300 	.mmap		= vfio_cdx_mmap,
301 	.bind_iommufd	= vfio_iommufd_physical_bind,
302 	.unbind_iommufd	= vfio_iommufd_physical_unbind,
303 	.attach_ioas	= vfio_iommufd_physical_attach_ioas,
304 };
305 
306 static int vfio_cdx_probe(struct cdx_device *cdx_dev)
307 {
308 	struct vfio_cdx_device *vdev;
309 	struct device *dev = &cdx_dev->dev;
310 	int ret;
311 
312 	vdev = vfio_alloc_device(vfio_cdx_device, vdev, dev,
313 				 &vfio_cdx_ops);
314 	if (IS_ERR(vdev))
315 		return PTR_ERR(vdev);
316 
317 	ret = vfio_register_group_dev(&vdev->vdev);
318 	if (ret)
319 		goto out_uninit;
320 
321 	dev_set_drvdata(dev, vdev);
322 	return 0;
323 
324 out_uninit:
325 	vfio_put_device(&vdev->vdev);
326 	return ret;
327 }
328 
329 static int vfio_cdx_remove(struct cdx_device *cdx_dev)
330 {
331 	struct device *dev = &cdx_dev->dev;
332 	struct vfio_cdx_device *vdev = dev_get_drvdata(dev);
333 
334 	vfio_unregister_group_dev(&vdev->vdev);
335 	vfio_put_device(&vdev->vdev);
336 
337 	return 0;
338 }
339 
340 static const struct cdx_device_id vfio_cdx_table[] = {
341 	{ CDX_DEVICE_DRIVER_OVERRIDE(CDX_ANY_ID, CDX_ANY_ID,
342 				     CDX_ID_F_VFIO_DRIVER_OVERRIDE) }, /* match all by default */
343 	{}
344 };
345 
346 MODULE_DEVICE_TABLE(cdx, vfio_cdx_table);
347 
348 static struct cdx_driver vfio_cdx_driver = {
349 	.probe		= vfio_cdx_probe,
350 	.remove		= vfio_cdx_remove,
351 	.match_id_table	= vfio_cdx_table,
352 	.driver	= {
353 		.name	= "vfio-cdx",
354 	},
355 	.driver_managed_dma = true,
356 };
357 
358 module_driver(vfio_cdx_driver, cdx_driver_register, cdx_driver_unregister);
359 
360 MODULE_LICENSE("GPL");
361 MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver");
362 MODULE_IMPORT_NS("CDX_BUS");
363