Commit | Line | Data |
---|---|---|
8cc02d22 CH |
1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* | |
3 | * Copyright (C) 2012 Red Hat, Inc. All rights reserved. | |
4 | * Author: Alex Williamson <alex.williamson@redhat.com> | |
5 | */ | |
e3bb4de0 JG |
6 | #ifndef __VFIO_VFIO_H__ |
7 | #define __VFIO_VFIO_H__ | |
8 | ||
9eefba80 | 9 | #include <linux/file.h> |
e3bb4de0 JG |
10 | #include <linux/device.h> |
11 | #include <linux/cdev.h> | |
12 | #include <linux/module.h> | |
c9a397ce | 13 | #include <linux/vfio.h> |
e3bb4de0 | 14 | |
2a3dab19 | 15 | struct iommufd_ctx; |
e3bb4de0 | 16 | struct iommu_group; |
cdc71fe4 | 17 | struct vfio_container; |
8cc02d22 | 18 | |
b1a3b5c6 YL |
19 | struct vfio_device_file { |
20 | struct vfio_device *device; | |
839e692f | 21 | struct vfio_group *group; |
34aeeecd | 22 | |
82d93f58 | 23 | u8 access_granted; |
31014aef | 24 | u32 devid; /* only valid when iommufd is valid */ |
34aeeecd YL |
25 | spinlock_t kvm_ref_lock; /* protect kvm field */ |
26 | struct kvm *kvm; | |
05f37e1c | 27 | struct iommufd_ctx *iommufd; /* protected by struct vfio_device_set::lock */ |
b1a3b5c6 YL |
28 | }; |
29 | ||
9eefba80 YL |
30 | void vfio_device_put_registration(struct vfio_device *device); |
31 | bool vfio_device_try_get_registration(struct vfio_device *device); | |
05f37e1c YL |
32 | int vfio_df_open(struct vfio_device_file *df); |
33 | void vfio_df_close(struct vfio_device_file *df); | |
b1a3b5c6 YL |
34 | struct vfio_device_file * |
35 | vfio_allocate_device_file(struct vfio_device *device); | |
9eefba80 YL |
36 | |
37 | extern const struct file_operations vfio_device_fops; | |
38 | ||
c1cce6d0 YL |
39 | #ifdef CONFIG_VFIO_NOIOMMU |
40 | extern bool vfio_noiommu __read_mostly; | |
41 | #else | |
42 | enum { vfio_noiommu = false }; | |
43 | #endif | |
44 | ||
c3c0fa9d CH |
45 | enum vfio_group_type { |
46 | /* | |
47 | * Physical device with IOMMU backing. | |
48 | */ | |
49 | VFIO_IOMMU, | |
50 | ||
51 | /* | |
52 | * Virtual device without IOMMU backing. The VFIO core fakes up an | |
53 | * iommu_group as the iommu_group sysfs interface is part of the | |
54 | * userspace ABI. The user of these devices must not be able to | |
55 | * directly trigger unmediated DMA. | |
56 | */ | |
57 | VFIO_EMULATED_IOMMU, | |
58 | ||
59 | /* | |
60 | * Physical device without IOMMU backing. The VFIO core fakes up an | |
61 | * iommu_group as the iommu_group sysfs interface is part of the | |
62 | * userspace ABI. Users can trigger unmediated DMA by the device, | |
63 | * usage is highly dangerous, requires an explicit opt-in and will | |
64 | * taint the kernel. | |
65 | */ | |
66 | VFIO_NO_IOMMU, | |
67 | }; | |
68 | ||
c1cce6d0 | 69 | #if IS_ENABLED(CONFIG_VFIO_GROUP) |
cdc71fe4 JG |
70 | struct vfio_group { |
71 | struct device dev; | |
72 | struct cdev cdev; | |
ca5f21b2 JG |
73 | /* |
74 | * When drivers is non-zero a driver is attached to the struct device | |
75 | * that provided the iommu_group and thus the iommu_group is a valid | |
76 | * pointer. When drivers is 0 the driver is being detached. Once users | |
77 | * reaches 0 then the iommu_group is invalid. | |
78 | */ | |
79 | refcount_t drivers; | |
cdc71fe4 JG |
80 | unsigned int container_users; |
81 | struct iommu_group *iommu_group; | |
82 | struct vfio_container *container; | |
83 | struct list_head device_list; | |
84 | struct mutex device_lock; | |
85 | struct list_head vfio_next; | |
e5a9ec7e | 86 | #if IS_ENABLED(CONFIG_VFIO_CONTAINER) |
cdc71fe4 | 87 | struct list_head container_next; |
e5a9ec7e | 88 | #endif |
cdc71fe4 | 89 | enum vfio_group_type type; |
c82e81ab | 90 | struct mutex group_lock; |
cdc71fe4 JG |
91 | struct kvm *kvm; |
92 | struct file *opened_file; | |
93 | struct blocking_notifier_head notifier; | |
2a3dab19 | 94 | struct iommufd_ctx *iommufd; |
2b48f52f | 95 | spinlock_t kvm_ref_lock; |
270bf4c0 | 96 | unsigned int cdev_device_open_cnt; |
cdc71fe4 JG |
97 | }; |
98 | ||
270bf4c0 YL |
99 | int vfio_device_block_group(struct vfio_device *device); |
100 | void vfio_device_unblock_group(struct vfio_device *device); | |
9eefba80 YL |
101 | int vfio_device_set_group(struct vfio_device *device, |
102 | enum vfio_group_type type); | |
103 | void vfio_device_remove_group(struct vfio_device *device); | |
104 | void vfio_device_group_register(struct vfio_device *device); | |
105 | void vfio_device_group_unregister(struct vfio_device *device); | |
106 | int vfio_device_group_use_iommu(struct vfio_device *device); | |
107 | void vfio_device_group_unuse_iommu(struct vfio_device *device); | |
05f37e1c | 108 | void vfio_df_group_close(struct vfio_device_file *df); |
b1a59be8 YL |
109 | struct vfio_group *vfio_group_from_file(struct file *file); |
110 | bool vfio_group_enforced_coherent(struct vfio_group *group); | |
111 | void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm); | |
9eefba80 YL |
112 | bool vfio_device_has_container(struct vfio_device *device); |
113 | int __init vfio_group_init(void); | |
114 | void vfio_group_cleanup(void); | |
115 | ||
c9a397ce JG |
116 | static inline bool vfio_device_is_noiommu(struct vfio_device *vdev) |
117 | { | |
118 | return IS_ENABLED(CONFIG_VFIO_NOIOMMU) && | |
119 | vdev->group->type == VFIO_NO_IOMMU; | |
120 | } | |
c1cce6d0 YL |
121 | #else |
122 | struct vfio_group; | |
123 | ||
124 | static inline int vfio_device_block_group(struct vfio_device *device) | |
125 | { | |
126 | return 0; | |
127 | } | |
128 | ||
129 | static inline void vfio_device_unblock_group(struct vfio_device *device) | |
130 | { | |
131 | } | |
132 | ||
133 | static inline int vfio_device_set_group(struct vfio_device *device, | |
134 | enum vfio_group_type type) | |
135 | { | |
136 | return 0; | |
137 | } | |
138 | ||
139 | static inline void vfio_device_remove_group(struct vfio_device *device) | |
140 | { | |
141 | } | |
142 | ||
143 | static inline void vfio_device_group_register(struct vfio_device *device) | |
144 | { | |
145 | } | |
146 | ||
147 | static inline void vfio_device_group_unregister(struct vfio_device *device) | |
148 | { | |
149 | } | |
150 | ||
151 | static inline int vfio_device_group_use_iommu(struct vfio_device *device) | |
152 | { | |
153 | return -EOPNOTSUPP; | |
154 | } | |
155 | ||
156 | static inline void vfio_device_group_unuse_iommu(struct vfio_device *device) | |
157 | { | |
158 | } | |
159 | ||
160 | static inline void vfio_df_group_close(struct vfio_device_file *df) | |
161 | { | |
162 | } | |
163 | ||
164 | static inline struct vfio_group *vfio_group_from_file(struct file *file) | |
165 | { | |
166 | return NULL; | |
167 | } | |
168 | ||
169 | static inline bool vfio_group_enforced_coherent(struct vfio_group *group) | |
170 | { | |
171 | return true; | |
172 | } | |
173 | ||
174 | static inline void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm) | |
175 | { | |
176 | } | |
177 | ||
178 | static inline bool vfio_device_has_container(struct vfio_device *device) | |
179 | { | |
180 | return false; | |
181 | } | |
182 | ||
183 | static inline int __init vfio_group_init(void) | |
184 | { | |
185 | return 0; | |
186 | } | |
187 | ||
188 | static inline void vfio_group_cleanup(void) | |
189 | { | |
190 | } | |
191 | ||
192 | static inline bool vfio_device_is_noiommu(struct vfio_device *vdev) | |
193 | { | |
194 | return false; | |
195 | } | |
196 | #endif /* CONFIG_VFIO_GROUP */ | |
c9a397ce | 197 | |
e5a9ec7e | 198 | #if IS_ENABLED(CONFIG_VFIO_CONTAINER) |
8cc02d22 CH |
199 | /** |
200 | * struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks | |
201 | */ | |
202 | struct vfio_iommu_driver_ops { | |
203 | char *name; | |
204 | struct module *owner; | |
205 | void *(*open)(unsigned long arg); | |
206 | void (*release)(void *iommu_data); | |
207 | long (*ioctl)(void *iommu_data, unsigned int cmd, | |
208 | unsigned long arg); | |
209 | int (*attach_group)(void *iommu_data, | |
c3c0fa9d CH |
210 | struct iommu_group *group, |
211 | enum vfio_group_type); | |
8cc02d22 CH |
212 | void (*detach_group)(void *iommu_data, |
213 | struct iommu_group *group); | |
214 | int (*pin_pages)(void *iommu_data, | |
215 | struct iommu_group *group, | |
44abdd16 | 216 | dma_addr_t user_iova, |
8cc02d22 | 217 | int npage, int prot, |
34a255e6 | 218 | struct page **pages); |
e8f90717 | 219 | void (*unpin_pages)(void *iommu_data, |
44abdd16 | 220 | dma_addr_t user_iova, int npage); |
8cfc5b60 JG |
221 | void (*register_device)(void *iommu_data, |
222 | struct vfio_device *vdev); | |
223 | void (*unregister_device)(void *iommu_data, | |
224 | struct vfio_device *vdev); | |
8cc02d22 CH |
225 | int (*dma_rw)(void *iommu_data, dma_addr_t user_iova, |
226 | void *data, size_t count, bool write); | |
227 | struct iommu_domain *(*group_iommu_domain)(void *iommu_data, | |
228 | struct iommu_group *group); | |
8cc02d22 CH |
229 | }; |
230 | ||
cdc71fe4 JG |
231 | struct vfio_iommu_driver { |
232 | const struct vfio_iommu_driver_ops *ops; | |
233 | struct list_head vfio_next; | |
234 | }; | |
235 | ||
8cc02d22 CH |
236 | int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops); |
237 | void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops); | |
e3bb4de0 | 238 | |
cdc71fe4 | 239 | struct vfio_container *vfio_container_from_file(struct file *filep); |
04f930c3 JG |
240 | int vfio_group_use_container(struct vfio_group *group); |
241 | void vfio_group_unuse_container(struct vfio_group *group); | |
cdc71fe4 JG |
242 | int vfio_container_attach_group(struct vfio_container *container, |
243 | struct vfio_group *group); | |
244 | void vfio_group_detach_container(struct vfio_group *group); | |
245 | void vfio_device_container_register(struct vfio_device *device); | |
246 | void vfio_device_container_unregister(struct vfio_device *device); | |
8da7a0e7 YL |
247 | int vfio_device_container_pin_pages(struct vfio_device *device, |
248 | dma_addr_t iova, int npage, | |
249 | int prot, struct page **pages); | |
250 | void vfio_device_container_unpin_pages(struct vfio_device *device, | |
251 | dma_addr_t iova, int npage); | |
252 | int vfio_device_container_dma_rw(struct vfio_device *device, | |
253 | dma_addr_t iova, void *data, | |
254 | size_t len, bool write); | |
4741f2e9 | 255 | |
cdc71fe4 JG |
256 | int __init vfio_container_init(void); |
257 | void vfio_container_cleanup(void); | |
e5a9ec7e JG |
258 | #else |
259 | static inline struct vfio_container * | |
260 | vfio_container_from_file(struct file *filep) | |
261 | { | |
262 | return NULL; | |
263 | } | |
264 | ||
265 | static inline int vfio_group_use_container(struct vfio_group *group) | |
266 | { | |
267 | return -EOPNOTSUPP; | |
268 | } | |
269 | ||
270 | static inline void vfio_group_unuse_container(struct vfio_group *group) | |
271 | { | |
272 | } | |
273 | ||
274 | static inline int vfio_container_attach_group(struct vfio_container *container, | |
275 | struct vfio_group *group) | |
276 | { | |
277 | return -EOPNOTSUPP; | |
278 | } | |
279 | ||
280 | static inline void vfio_group_detach_container(struct vfio_group *group) | |
281 | { | |
282 | } | |
283 | ||
284 | static inline void vfio_device_container_register(struct vfio_device *device) | |
285 | { | |
286 | } | |
287 | ||
288 | static inline void vfio_device_container_unregister(struct vfio_device *device) | |
289 | { | |
290 | } | |
291 | ||
8da7a0e7 YL |
292 | static inline int vfio_device_container_pin_pages(struct vfio_device *device, |
293 | dma_addr_t iova, int npage, | |
294 | int prot, struct page **pages) | |
e5a9ec7e JG |
295 | { |
296 | return -EOPNOTSUPP; | |
297 | } | |
298 | ||
8da7a0e7 YL |
299 | static inline void vfio_device_container_unpin_pages(struct vfio_device *device, |
300 | dma_addr_t iova, int npage) | |
e5a9ec7e JG |
301 | { |
302 | } | |
303 | ||
8da7a0e7 YL |
304 | static inline int vfio_device_container_dma_rw(struct vfio_device *device, |
305 | dma_addr_t iova, void *data, | |
306 | size_t len, bool write) | |
e5a9ec7e JG |
307 | { |
308 | return -EOPNOTSUPP; | |
309 | } | |
310 | ||
311 | static inline int vfio_container_init(void) | |
312 | { | |
313 | return 0; | |
314 | } | |
315 | static inline void vfio_container_cleanup(void) | |
316 | { | |
317 | } | |
318 | #endif | |
cdc71fe4 | 319 | |
a4d1f91d | 320 | #if IS_ENABLED(CONFIG_IOMMUFD) |
6086efe7 YL |
321 | bool vfio_iommufd_device_has_compat_ioas(struct vfio_device *vdev, |
322 | struct iommufd_ctx *ictx); | |
31014aef YL |
323 | int vfio_df_iommufd_bind(struct vfio_device_file *df); |
324 | void vfio_df_iommufd_unbind(struct vfio_device_file *df); | |
6f240ee6 YL |
325 | int vfio_iommufd_compat_attach_ioas(struct vfio_device *device, |
326 | struct iommufd_ctx *ictx); | |
a4d1f91d | 327 | #else |
6086efe7 YL |
328 | static inline bool |
329 | vfio_iommufd_device_has_compat_ioas(struct vfio_device *vdev, | |
330 | struct iommufd_ctx *ictx) | |
331 | { | |
332 | return false; | |
333 | } | |
334 | ||
31014aef | 335 | static inline int vfio_df_iommufd_bind(struct vfio_device_file *fd) |
a4d1f91d JG |
336 | { |
337 | return -EOPNOTSUPP; | |
338 | } | |
339 | ||
31014aef | 340 | static inline void vfio_df_iommufd_unbind(struct vfio_device_file *df) |
a4d1f91d JG |
341 | { |
342 | } | |
6f240ee6 YL |
343 | |
344 | static inline int | |
345 | vfio_iommufd_compat_attach_ioas(struct vfio_device *device, | |
346 | struct iommufd_ctx *ictx) | |
347 | { | |
348 | return -EOPNOTSUPP; | |
349 | } | |
a4d1f91d JG |
350 | #endif |
351 | ||
b290a05f YL |
352 | int vfio_df_ioctl_attach_pt(struct vfio_device_file *df, |
353 | struct vfio_device_attach_iommufd_pt __user *arg); | |
354 | int vfio_df_ioctl_detach_pt(struct vfio_device_file *df, | |
355 | struct vfio_device_detach_iommufd_pt __user *arg); | |
356 | ||
8b6f173a YL |
357 | #if IS_ENABLED(CONFIG_VFIO_DEVICE_CDEV) |
358 | void vfio_init_device_cdev(struct vfio_device *device); | |
359 | ||
360 | static inline int vfio_device_add(struct vfio_device *device) | |
361 | { | |
362 | /* cdev does not support noiommu device */ | |
363 | if (vfio_device_is_noiommu(device)) | |
364 | return device_add(&device->device); | |
365 | vfio_init_device_cdev(device); | |
366 | return cdev_device_add(&device->cdev, &device->device); | |
367 | } | |
368 | ||
369 | static inline void vfio_device_del(struct vfio_device *device) | |
370 | { | |
371 | if (vfio_device_is_noiommu(device)) | |
372 | device_del(&device->device); | |
373 | else | |
374 | cdev_device_del(&device->cdev, &device->device); | |
375 | } | |
376 | ||
377 | int vfio_device_fops_cdev_open(struct inode *inode, struct file *filep); | |
5fcc2696 YL |
378 | long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df, |
379 | struct vfio_device_bind_iommufd __user *arg); | |
380 | void vfio_df_unbind_iommufd(struct vfio_device_file *df); | |
8b6f173a YL |
381 | int vfio_cdev_init(struct class *device_class); |
382 | void vfio_cdev_cleanup(void); | |
383 | #else | |
384 | static inline void vfio_init_device_cdev(struct vfio_device *device) | |
385 | { | |
386 | } | |
387 | ||
388 | static inline int vfio_device_add(struct vfio_device *device) | |
389 | { | |
390 | return device_add(&device->device); | |
391 | } | |
392 | ||
393 | static inline void vfio_device_del(struct vfio_device *device) | |
394 | { | |
395 | device_del(&device->device); | |
396 | } | |
397 | ||
398 | static inline int vfio_device_fops_cdev_open(struct inode *inode, | |
399 | struct file *filep) | |
400 | { | |
401 | return 0; | |
402 | } | |
403 | ||
5fcc2696 YL |
404 | static inline long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df, |
405 | struct vfio_device_bind_iommufd __user *arg) | |
406 | { | |
407 | return -ENOTTY; | |
408 | } | |
409 | ||
410 | static inline void vfio_df_unbind_iommufd(struct vfio_device_file *df) | |
411 | { | |
412 | } | |
413 | ||
8b6f173a YL |
414 | static inline int vfio_cdev_init(struct class *device_class) |
415 | { | |
416 | return 0; | |
417 | } | |
418 | ||
419 | static inline void vfio_cdev_cleanup(void) | |
420 | { | |
421 | } | |
422 | #endif /* CONFIG_VFIO_DEVICE_CDEV */ | |
423 | ||
e2d55709 JG |
424 | #if IS_ENABLED(CONFIG_VFIO_VIRQFD) |
425 | int __init vfio_virqfd_init(void); | |
426 | void vfio_virqfd_exit(void); | |
427 | #else | |
428 | static inline int __init vfio_virqfd_init(void) | |
429 | { | |
430 | return 0; | |
431 | } | |
432 | static inline void vfio_virqfd_exit(void) | |
433 | { | |
434 | } | |
435 | #endif | |
436 | ||
09e33b04 | 437 | #if IS_ENABLED(CONFIG_KVM) |
5c6de3ea | 438 | void vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm); |
2b48f52f MR |
439 | void vfio_device_put_kvm(struct vfio_device *device); |
440 | #else | |
5c6de3ea YL |
441 | static inline void vfio_device_get_kvm_safe(struct vfio_device *device, |
442 | struct kvm *kvm) | |
2b48f52f MR |
443 | { |
444 | } | |
445 | ||
446 | static inline void vfio_device_put_kvm(struct vfio_device *device) | |
447 | { | |
448 | } | |
449 | #endif | |
450 | ||
2202844e LL |
451 | #ifdef CONFIG_VFIO_DEBUGFS |
452 | void vfio_debugfs_create_root(void); | |
453 | void vfio_debugfs_remove_root(void); | |
454 | ||
455 | void vfio_device_debugfs_init(struct vfio_device *vdev); | |
456 | void vfio_device_debugfs_exit(struct vfio_device *vdev); | |
457 | #else | |
458 | static inline void vfio_debugfs_create_root(void) { } | |
459 | static inline void vfio_debugfs_remove_root(void) { } | |
460 | ||
461 | static inline void vfio_device_debugfs_init(struct vfio_device *vdev) { } | |
462 | static inline void vfio_device_debugfs_exit(struct vfio_device *vdev) { } | |
463 | #endif /* CONFIG_VFIO_DEBUGFS */ | |
464 | ||
e3bb4de0 | 465 | #endif |