| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- /* SPDX-License-Identifier: GPL-2.0-only */
- /*
- * Copyright (C) 2012 Red Hat, Inc. All rights reserved.
- * Author: Alex Williamson <alex.williamson@redhat.com>
- */
- #ifndef __VFIO_VFIO_H__
- #define __VFIO_VFIO_H__
- #include <linux/file.h>
- #include <linux/device.h>
- #include <linux/cdev.h>
- #include <linux/module.h>
- #include <linux/vfio.h>
- struct iommufd_ctx;
- struct iommu_group;
- struct vfio_container;
- struct vfio_device_file {
- struct vfio_device *device;
- struct vfio_group *group;
- u8 access_granted;
- u32 devid; /* only valid when iommufd is valid */
- spinlock_t kvm_ref_lock; /* protect kvm field */
- struct kvm *kvm;
- struct iommufd_ctx *iommufd; /* protected by struct vfio_device_set::lock */
- };
- void vfio_device_put_registration(struct vfio_device *device);
- bool vfio_device_try_get_registration(struct vfio_device *device);
- int vfio_df_open(struct vfio_device_file *df);
- void vfio_df_close(struct vfio_device_file *df);
- struct vfio_device_file *
- vfio_allocate_device_file(struct vfio_device *device);
- extern const struct file_operations vfio_device_fops;
- #ifdef CONFIG_VFIO_NOIOMMU
- extern bool vfio_noiommu __read_mostly;
- #else
- enum { vfio_noiommu = false };
- #endif
- enum vfio_group_type {
- /*
- * Physical device with IOMMU backing.
- */
- VFIO_IOMMU,
- /*
- * Virtual device without IOMMU backing. The VFIO core fakes up an
- * iommu_group as the iommu_group sysfs interface is part of the
- * userspace ABI. The user of these devices must not be able to
- * directly trigger unmediated DMA.
- */
- VFIO_EMULATED_IOMMU,
- /*
- * Physical device without IOMMU backing. The VFIO core fakes up an
- * iommu_group as the iommu_group sysfs interface is part of the
- * userspace ABI. Users can trigger unmediated DMA by the device,
- * usage is highly dangerous, requires an explicit opt-in and will
- * taint the kernel.
- */
- VFIO_NO_IOMMU,
- };
- #if IS_ENABLED(CONFIG_VFIO_GROUP)
- struct vfio_group {
- struct device dev;
- struct cdev cdev;
- /*
- * When drivers is non-zero a driver is attached to the struct device
- * that provided the iommu_group and thus the iommu_group is a valid
- * pointer. When drivers is 0 the driver is being detached. Once users
- * reaches 0 then the iommu_group is invalid.
- */
- refcount_t drivers;
- unsigned int container_users;
- struct iommu_group *iommu_group;
- struct vfio_container *container;
- struct list_head device_list;
- struct mutex device_lock;
- struct list_head vfio_next;
- #if IS_ENABLED(CONFIG_VFIO_CONTAINER)
- struct list_head container_next;
- #endif
- enum vfio_group_type type;
- struct mutex group_lock;
- struct kvm *kvm;
- struct file *opened_file;
- struct blocking_notifier_head notifier;
- struct iommufd_ctx *iommufd;
- spinlock_t kvm_ref_lock;
- unsigned int cdev_device_open_cnt;
- };
- int vfio_device_block_group(struct vfio_device *device);
- void vfio_device_unblock_group(struct vfio_device *device);
- int vfio_device_set_group(struct vfio_device *device,
- enum vfio_group_type type);
- void vfio_device_remove_group(struct vfio_device *device);
- void vfio_device_group_register(struct vfio_device *device);
- void vfio_device_group_unregister(struct vfio_device *device);
- int vfio_device_group_use_iommu(struct vfio_device *device);
- void vfio_device_group_unuse_iommu(struct vfio_device *device);
- void vfio_df_group_close(struct vfio_device_file *df);
- struct vfio_group *vfio_group_from_file(struct file *file);
- bool vfio_group_enforced_coherent(struct vfio_group *group);
- void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm);
- bool vfio_device_has_container(struct vfio_device *device);
- int __init vfio_group_init(void);
- void vfio_group_cleanup(void);
- static inline bool vfio_device_is_noiommu(struct vfio_device *vdev)
- {
- return IS_ENABLED(CONFIG_VFIO_NOIOMMU) &&
- vdev->group->type == VFIO_NO_IOMMU;
- }
- #else
- struct vfio_group;
- static inline int vfio_device_block_group(struct vfio_device *device)
- {
- return 0;
- }
- static inline void vfio_device_unblock_group(struct vfio_device *device)
- {
- }
- static inline int vfio_device_set_group(struct vfio_device *device,
- enum vfio_group_type type)
- {
- return 0;
- }
- static inline void vfio_device_remove_group(struct vfio_device *device)
- {
- }
- static inline void vfio_device_group_register(struct vfio_device *device)
- {
- }
- static inline void vfio_device_group_unregister(struct vfio_device *device)
- {
- }
- static inline int vfio_device_group_use_iommu(struct vfio_device *device)
- {
- return -EOPNOTSUPP;
- }
- static inline void vfio_device_group_unuse_iommu(struct vfio_device *device)
- {
- }
- static inline void vfio_df_group_close(struct vfio_device_file *df)
- {
- }
- static inline struct vfio_group *vfio_group_from_file(struct file *file)
- {
- return NULL;
- }
- static inline bool vfio_group_enforced_coherent(struct vfio_group *group)
- {
- return true;
- }
- static inline void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
- {
- }
- static inline bool vfio_device_has_container(struct vfio_device *device)
- {
- return false;
- }
- static inline int __init vfio_group_init(void)
- {
- return 0;
- }
- static inline void vfio_group_cleanup(void)
- {
- }
- static inline bool vfio_device_is_noiommu(struct vfio_device *vdev)
- {
- return false;
- }
- #endif /* CONFIG_VFIO_GROUP */
- #if IS_ENABLED(CONFIG_VFIO_CONTAINER)
- /**
- * struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks
- */
- struct vfio_iommu_driver_ops {
- char *name;
- struct module *owner;
- void *(*open)(unsigned long arg);
- void (*release)(void *iommu_data);
- long (*ioctl)(void *iommu_data, unsigned int cmd,
- unsigned long arg);
- int (*attach_group)(void *iommu_data,
- struct iommu_group *group,
- enum vfio_group_type);
- void (*detach_group)(void *iommu_data,
- struct iommu_group *group);
- int (*pin_pages)(void *iommu_data,
- struct iommu_group *group,
- dma_addr_t user_iova,
- int npage, int prot,
- struct page **pages);
- void (*unpin_pages)(void *iommu_data,
- dma_addr_t user_iova, int npage);
- void (*register_device)(void *iommu_data,
- struct vfio_device *vdev);
- void (*unregister_device)(void *iommu_data,
- struct vfio_device *vdev);
- int (*dma_rw)(void *iommu_data, dma_addr_t user_iova,
- void *data, size_t count, bool write);
- struct iommu_domain *(*group_iommu_domain)(void *iommu_data,
- struct iommu_group *group);
- };
- struct vfio_iommu_driver {
- const struct vfio_iommu_driver_ops *ops;
- struct list_head vfio_next;
- };
- int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops);
- void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops);
- struct vfio_container *vfio_container_from_file(struct file *filep);
- int vfio_group_use_container(struct vfio_group *group);
- void vfio_group_unuse_container(struct vfio_group *group);
- int vfio_container_attach_group(struct vfio_container *container,
- struct vfio_group *group);
- void vfio_group_detach_container(struct vfio_group *group);
- void vfio_device_container_register(struct vfio_device *device);
- void vfio_device_container_unregister(struct vfio_device *device);
- int vfio_device_container_pin_pages(struct vfio_device *device,
- dma_addr_t iova, int npage,
- int prot, struct page **pages);
- void vfio_device_container_unpin_pages(struct vfio_device *device,
- dma_addr_t iova, int npage);
- int vfio_device_container_dma_rw(struct vfio_device *device,
- dma_addr_t iova, void *data,
- size_t len, bool write);
- int __init vfio_container_init(void);
- void vfio_container_cleanup(void);
- #else
- static inline struct vfio_container *
- vfio_container_from_file(struct file *filep)
- {
- return NULL;
- }
- static inline int vfio_group_use_container(struct vfio_group *group)
- {
- return -EOPNOTSUPP;
- }
- static inline void vfio_group_unuse_container(struct vfio_group *group)
- {
- }
- static inline int vfio_container_attach_group(struct vfio_container *container,
- struct vfio_group *group)
- {
- return -EOPNOTSUPP;
- }
- static inline void vfio_group_detach_container(struct vfio_group *group)
- {
- }
- static inline void vfio_device_container_register(struct vfio_device *device)
- {
- }
- static inline void vfio_device_container_unregister(struct vfio_device *device)
- {
- }
- static inline int vfio_device_container_pin_pages(struct vfio_device *device,
- dma_addr_t iova, int npage,
- int prot, struct page **pages)
- {
- return -EOPNOTSUPP;
- }
- static inline void vfio_device_container_unpin_pages(struct vfio_device *device,
- dma_addr_t iova, int npage)
- {
- }
- static inline int vfio_device_container_dma_rw(struct vfio_device *device,
- dma_addr_t iova, void *data,
- size_t len, bool write)
- {
- return -EOPNOTSUPP;
- }
- static inline int vfio_container_init(void)
- {
- return 0;
- }
- static inline void vfio_container_cleanup(void)
- {
- }
- #endif
- #if IS_ENABLED(CONFIG_IOMMUFD)
- bool vfio_iommufd_device_has_compat_ioas(struct vfio_device *vdev,
- struct iommufd_ctx *ictx);
- int vfio_df_iommufd_bind(struct vfio_device_file *df);
- void vfio_df_iommufd_unbind(struct vfio_device_file *df);
- int vfio_iommufd_compat_attach_ioas(struct vfio_device *device,
- struct iommufd_ctx *ictx);
- #else
- static inline bool
- vfio_iommufd_device_has_compat_ioas(struct vfio_device *vdev,
- struct iommufd_ctx *ictx)
- {
- return false;
- }
- static inline int vfio_df_iommufd_bind(struct vfio_device_file *fd)
- {
- return -EOPNOTSUPP;
- }
- static inline void vfio_df_iommufd_unbind(struct vfio_device_file *df)
- {
- }
- static inline int
- vfio_iommufd_compat_attach_ioas(struct vfio_device *device,
- struct iommufd_ctx *ictx)
- {
- return -EOPNOTSUPP;
- }
- #endif
- int vfio_df_ioctl_attach_pt(struct vfio_device_file *df,
- struct vfio_device_attach_iommufd_pt __user *arg);
- int vfio_df_ioctl_detach_pt(struct vfio_device_file *df,
- struct vfio_device_detach_iommufd_pt __user *arg);
- #if IS_ENABLED(CONFIG_VFIO_DEVICE_CDEV)
- void vfio_init_device_cdev(struct vfio_device *device);
- static inline int vfio_device_add(struct vfio_device *device)
- {
- /* cdev does not support noiommu device */
- if (vfio_device_is_noiommu(device))
- return device_add(&device->device);
- vfio_init_device_cdev(device);
- return cdev_device_add(&device->cdev, &device->device);
- }
- static inline void vfio_device_del(struct vfio_device *device)
- {
- if (vfio_device_is_noiommu(device))
- device_del(&device->device);
- else
- cdev_device_del(&device->cdev, &device->device);
- }
- int vfio_device_fops_cdev_open(struct inode *inode, struct file *filep);
- long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df,
- struct vfio_device_bind_iommufd __user *arg);
- void vfio_df_unbind_iommufd(struct vfio_device_file *df);
- int vfio_cdev_init(struct class *device_class);
- void vfio_cdev_cleanup(void);
- #else
- static inline void vfio_init_device_cdev(struct vfio_device *device)
- {
- }
- static inline int vfio_device_add(struct vfio_device *device)
- {
- return device_add(&device->device);
- }
- static inline void vfio_device_del(struct vfio_device *device)
- {
- device_del(&device->device);
- }
- static inline int vfio_device_fops_cdev_open(struct inode *inode,
- struct file *filep)
- {
- return 0;
- }
- static inline long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df,
- struct vfio_device_bind_iommufd __user *arg)
- {
- return -ENOTTY;
- }
- static inline void vfio_df_unbind_iommufd(struct vfio_device_file *df)
- {
- }
- static inline int vfio_cdev_init(struct class *device_class)
- {
- return 0;
- }
- static inline void vfio_cdev_cleanup(void)
- {
- }
- #endif /* CONFIG_VFIO_DEVICE_CDEV */
- #if IS_ENABLED(CONFIG_VFIO_VIRQFD)
- int __init vfio_virqfd_init(void);
- void vfio_virqfd_exit(void);
- #else
- static inline int __init vfio_virqfd_init(void)
- {
- return 0;
- }
- static inline void vfio_virqfd_exit(void)
- {
- }
- #endif
- #if IS_ENABLED(CONFIG_KVM)
- void vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm);
- void vfio_device_put_kvm(struct vfio_device *device);
- #else
- static inline void vfio_device_get_kvm_safe(struct vfio_device *device,
- struct kvm *kvm)
- {
- }
- static inline void vfio_device_put_kvm(struct vfio_device *device)
- {
- }
- #endif
- #ifdef CONFIG_VFIO_DEBUGFS
- void vfio_debugfs_create_root(void);
- void vfio_debugfs_remove_root(void);
- void vfio_device_debugfs_init(struct vfio_device *vdev);
- void vfio_device_debugfs_exit(struct vfio_device *vdev);
- #else
- static inline void vfio_debugfs_create_root(void) { }
- static inline void vfio_debugfs_remove_root(void) { }
- static inline void vfio_device_debugfs_init(struct vfio_device *vdev) { }
- static inline void vfio_device_debugfs_exit(struct vfio_device *vdev) { }
- #endif /* CONFIG_VFIO_DEBUGFS */
- #endif
|