cac85e4616
- Remove redundant resource check in vfio-platform. (Angus Chen) - Use GFP_KERNEL_ACCOUNT for persistent userspace allocations, allowing removal of arbitrary kernel limits in favor of cgroup control. (Yishai Hadas) - mdev tidy-ups, including removing the module-only build restriction for sample drivers, Kconfig changes to select mdev support, documentation movement to keep sample driver usage instructions with sample drivers rather than with API docs, remove references to out-of-tree drivers in docs. (Christoph Hellwig) - Fix collateral breakages from mdev Kconfig changes. (Arnd Bergmann) - Make mlx5 migration support match device support, improve source and target flows to improve pre-copy support and reduce downtime. (Yishai Hadas) - Convert additional mdev sysfs case to use sysfs_emit(). (Bo Liu) - Resolve copy-paste error in mdev mbochs sample driver Kconfig. (Ye Xingchen) - Avoid propagating missing reset error in vfio-platform if reset requirement is relaxed by module option. (Tomasz Duszynski) - Range size fixes in mlx5 variant driver for missed last byte and stricter range calculation. (Yishai Hadas) - Fixes to suspended vaddr support and locked_vm accounting, excluding mdev configurations from the former due to potential to indefinitely block kernel threads, fix underflow and restore locked_vm on new mm. (Steve Sistare) - Update outdated vfio documentation due to new IOMMUFD interfaces in recent kernels. (Yi Liu) - Resolve deadlock between group_lock and kvm_lock, finally. (Matthew Rosato) - Fix NULL pointer in group initialization error path with IOMMUFD. (Yan Zhao) -----BEGIN PGP SIGNATURE----- iQJPBAABCAA5FiEEQvbATlQL0amee4qQI5ubbjuwiyIFAmP5GC0bHGFsZXgud2ls bGlhbXNvbkByZWRoYXQuY29tAAoJECObm247sIsiGoMP/Ajgc05dq2HGt0ZdTj3d /2fgFa/8GXv9t/Md4neHkvKppeHsyL6R9s/OlGb2zQMrZ9wTurW5s4pW4fLIcpNV v1vyQSLYMCtj/FT3kG38fZdJwF9NGnC+B+bY4ak+V2rWaKs2vT6fUG6YpzxuBU3T jRD41frtszXIp3i8bIPfaoKt/SydUrx12UJAKSks4eDM4aOlxKhpc3VB1vwaSmHB MgZMRPVQOGUubKJWb3u07tYOd8NHpBpD3HVUb8IlB2//tSqSPgq3GaKr/B25YzH+ 192vgGrm19aKYQ4U0KPLSH4QGG01bia4LqArbVAhBMwzgKK1dE24dk2YBVj+yePx 5XXHWv85gLpkev5aLAxsN75/qCtwhYYYB9vBohp8jhXjQU1GXdj9DAht5+c5I3sk SZcczmtuZ10X2XXT7fA5iRsG7o3Uxg1VikxYLT0Zhu/0DLc+wQrvum+mmu3sKscx qcJyTQXhNTDFzBRRTw6KdyCShbG9gFITysf9Xw/n2y3bxzlfy3Ttf617auYFv6fQ ed3kGiT+S16U/dr2b99qQZyn1eIbzOSkz/oWOXwvCWoBdPTEks9f7pDn9Kk6O641 8tf7qj3vpkOccg71EbVCF6JV5JrhtXDOJVzWIkfQWkoi7qI4ONZ/EdEGTnWY77RY urbhuR4UO1iG0nX+yQIFXhDR =QqPa -----END PGP SIGNATURE----- Merge tag 'vfio-v6.3-rc1' of https://github.com/awilliam/linux-vfio Pull VFIO updates from Alex Williamson: - Remove redundant resource check in vfio-platform (Angus Chen) - Use GFP_KERNEL_ACCOUNT for persistent userspace allocations, allowing removal of arbitrary kernel limits in favor of cgroup control (Yishai Hadas) - mdev tidy-ups, including removing the module-only build restriction for sample drivers, Kconfig changes to select mdev support, documentation movement to keep sample driver usage instructions with sample drivers rather than with API docs, remove references to out-of-tree drivers in docs (Christoph Hellwig) - Fix collateral breakages from mdev Kconfig changes (Arnd Bergmann) - Make mlx5 migration support match device support, improve source and target flows to improve pre-copy support and reduce downtime (Yishai Hadas) - Convert additional mdev sysfs case to use sysfs_emit() (Bo Liu) - Resolve copy-paste error in mdev mbochs sample driver Kconfig (Ye Xingchen) - Avoid propagating missing reset error in vfio-platform if reset requirement is relaxed by module option (Tomasz Duszynski) - Range size fixes in mlx5 variant driver for missed last byte and stricter range calculation (Yishai Hadas) - Fixes to suspended vaddr support and locked_vm accounting, excluding mdev configurations from the former due to potential to indefinitely block kernel threads, fix underflow and restore locked_vm on new mm (Steve Sistare) - Update outdated vfio documentation due to new IOMMUFD interfaces in recent kernels (Yi Liu) - Resolve deadlock between group_lock and kvm_lock, finally (Matthew Rosato) - Fix NULL pointer in group initialization error path with IOMMUFD (Yan Zhao) * tag 'vfio-v6.3-rc1' of https://github.com/awilliam/linux-vfio: (32 commits) vfio: Fix NULL pointer dereference caused by uninitialized group->iommufd docs: vfio: Update vfio.rst per latest interfaces vfio: Update the kdoc for vfio_device_ops vfio/mlx5: Fix range size calculation upon tracker creation vfio: no need to pass kvm pointer during device open vfio: fix deadlock between group lock and kvm lock vfio: revert "iommu driver notify callback" vfio/type1: revert "implement notify callback" vfio/type1: revert "block on invalid vaddr" vfio/type1: restore locked_vm vfio/type1: track locked_vm per dma vfio/type1: prevent underflow of locked_vm via exec() vfio/type1: exclude mdevs from VFIO_UPDATE_VADDR vfio: platform: ignore missing reset if disabled at module init vfio/mlx5: Improve the target side flow to reduce downtime vfio/mlx5: Improve the source side flow upon pre_copy vfio/mlx5: Check whether VF is migratable samples: fix the prompt about SAMPLE_VFIO_MDEV_MBOCHS vfio/mdev: Use sysfs_emit() to instead of sprintf() vfio-mdev: add back CONFIG_VFIO dependency ...
268 lines
7.5 KiB
C
268 lines
7.5 KiB
C
/* 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;
|
|
|
|
void vfio_device_put_registration(struct vfio_device *device);
|
|
bool vfio_device_try_get_registration(struct vfio_device *device);
|
|
int vfio_device_open(struct vfio_device *device, struct iommufd_ctx *iommufd);
|
|
void vfio_device_close(struct vfio_device *device,
|
|
struct iommufd_ctx *iommufd);
|
|
|
|
extern const struct file_operations vfio_device_fops;
|
|
|
|
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,
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
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_device_group_close(struct vfio_device *device);
|
|
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;
|
|
}
|
|
|
|
#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)
|
|
int vfio_iommufd_bind(struct vfio_device *device, struct iommufd_ctx *ictx);
|
|
void vfio_iommufd_unbind(struct vfio_device *device);
|
|
#else
|
|
static inline int vfio_iommufd_bind(struct vfio_device *device,
|
|
struct iommufd_ctx *ictx)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline void vfio_iommufd_unbind(struct vfio_device *device)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
#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
|
|
|
|
#ifdef CONFIG_VFIO_NOIOMMU
|
|
extern bool vfio_noiommu __read_mostly;
|
|
#else
|
|
enum { vfio_noiommu = false };
|
|
#endif
|
|
|
|
#ifdef CONFIG_HAVE_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
|
|
|
|
#endif
|