mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
Merge tag 'vfio-v7.0-rc1' of https://github.com/awilliam/linux-vfio
Pull VFIO updates from Alex Williamson:
"A small cycle with the bulk in selftests and reintroducing poison
handling in the nvgrace-gpu driver. The rest are fixes, cleanups, and
some dmabuf structure consolidation.
- Update outdated mdev comment referencing the renamed
mdev_type_add() function (Julia Lawall)
- Introduce selftest support for IOMMU mapping of PCI MMIO BARs (Alex
Mastro)
- Relax selftest assertion relative to differences in huge page
handling between legacy (v1) TYPE1 IOMMU mapping behavior and the
compatibility mode supported by IOMMUFD (David Matlack)
- Reintroduce memory poison handling support for non-struct-page-
backed memory in the nvgrace-gpu variant driver (Ankit Agrawal)
- Replace dma_buf_phys_vec with phys_vec to avoid duplicate structure
and semantics (Leon Romanovsky)
- Add missing upstream bridge locking across PCI function reset,
resolving an assertion failure when secondary bus reset is used to
provide that reset (Anthony Pighin)
- Fixes to hisi_acc vfio-pci variant driver to resolve corner case
issues related to resets, repeated migration, and error injection
scenarios (Longfang Liu, Weili Qian)
- Restrict vfio selftest builds to arm64 and x86_64, resolving
compiler warnings on 32-bit archs (Ted Logan)
- Un-deprecate the fsl-mc vfio bus driver as a new maintainer has
stepped up (Ioana Ciornei)"
* tag 'vfio-v7.0-rc1' of https://github.com/awilliam/linux-vfio:
vfio/fsl-mc: add myself as maintainer
vfio: selftests: only build tests on arm64 and x86_64
hisi_acc_vfio_pci: fix the queue parameter anomaly issue
hisi_acc_vfio_pci: resolve duplicate migration states
hisi_acc_vfio_pci: update status after RAS error
hisi_acc_vfio_pci: fix VF reset timeout issue
vfio/pci: Lock upstream bridge for vfio_pci_core_disable()
types: reuse common phys_vec type instead of DMABUF open‑coded variant
vfio/nvgrace-gpu: register device memory for poison handling
mm: add stubs for PFNMAP memory failure registration functions
vfio: selftests: Drop IOMMU mapping size assertions for VFIO_TYPE1_IOMMU
vfio: selftests: Add vfio_dma_mapping_mmio_test
vfio: selftests: Align BAR mmaps for efficient IOMMU mapping
vfio: selftests: Centralize IOMMU mode name definitions
vfio/mdev: update outdated comment
This commit is contained in:
@@ -2,12 +2,9 @@ menu "VFIO support for FSL_MC bus devices"
|
||||
depends on FSL_MC_BUS
|
||||
|
||||
config VFIO_FSL_MC
|
||||
tristate "VFIO support for QorIQ DPAA2 fsl-mc bus devices (DEPRECATED)"
|
||||
tristate "VFIO support for QorIQ DPAA2 fsl-mc bus devices"
|
||||
select EVENTFD
|
||||
help
|
||||
The vfio-fsl-mc driver is deprecated and will be removed in a
|
||||
future kernel release.
|
||||
|
||||
Driver to enable support for the VFIO QorIQ DPAA2 fsl-mc
|
||||
(Management Complex) devices. This is required to passthrough
|
||||
fsl-mc bus devices using the VFIO framework.
|
||||
|
||||
@@ -531,8 +531,6 @@ static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev)
|
||||
struct device *dev = &mc_dev->dev;
|
||||
int ret;
|
||||
|
||||
dev_err_once(dev, "DEPRECATION: vfio-fsl-mc is deprecated and will be removed in a future kernel release\n");
|
||||
|
||||
vdev = vfio_alloc_device(vfio_fsl_mc_device, vdev, dev,
|
||||
&vfio_fsl_mc_ops);
|
||||
if (IS_ERR(vdev))
|
||||
|
||||
@@ -156,7 +156,7 @@ static void mdev_type_release(struct kobject *kobj)
|
||||
struct mdev_type *type = to_mdev_type(kobj);
|
||||
|
||||
pr_debug("Releasing group %s\n", kobj->name);
|
||||
/* Pairs with the get in add_mdev_supported_type() */
|
||||
/* Pairs with the get in mdev_type_add() */
|
||||
put_device(type->parent->dev);
|
||||
}
|
||||
|
||||
|
||||
@@ -426,7 +426,7 @@ static int vf_qm_check_match(struct hisi_acc_vf_core_device *hisi_acc_vdev,
|
||||
ret = qm_get_vft(vf_qm, &vf_qm->qp_base);
|
||||
if (ret <= 0) {
|
||||
dev_err(dev, "failed to get vft qp nums\n");
|
||||
return ret;
|
||||
return ret < 0 ? ret : -EINVAL;
|
||||
}
|
||||
|
||||
if (ret != vf_data->qp_num) {
|
||||
@@ -1188,12 +1188,34 @@ hisi_acc_vfio_pci_get_device_state(struct vfio_device *vdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hisi_acc_vf_pci_reset_prepare(struct pci_dev *pdev)
|
||||
{
|
||||
struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_drvdata(pdev);
|
||||
struct hisi_qm *qm = hisi_acc_vdev->pf_qm;
|
||||
struct device *dev = &qm->pdev->dev;
|
||||
u32 delay = 0;
|
||||
|
||||
/* All reset requests need to be queued for processing */
|
||||
while (test_and_set_bit(QM_RESETTING, &qm->misc_ctl)) {
|
||||
msleep(1);
|
||||
if (++delay > QM_RESET_WAIT_TIMEOUT) {
|
||||
dev_err(dev, "reset prepare failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hisi_acc_vdev->set_reset_flag = true;
|
||||
}
|
||||
|
||||
static void hisi_acc_vf_pci_aer_reset_done(struct pci_dev *pdev)
|
||||
{
|
||||
struct hisi_acc_vf_core_device *hisi_acc_vdev = hisi_acc_drvdata(pdev);
|
||||
struct hisi_qm *qm = hisi_acc_vdev->pf_qm;
|
||||
|
||||
if (hisi_acc_vdev->core_device.vdev.migration_flags !=
|
||||
VFIO_MIGRATION_STOP_COPY)
|
||||
if (hisi_acc_vdev->set_reset_flag)
|
||||
clear_bit(QM_RESETTING, &qm->misc_ctl);
|
||||
|
||||
if (!hisi_acc_vdev->core_device.vdev.mig_ops)
|
||||
return;
|
||||
|
||||
mutex_lock(&hisi_acc_vdev->state_mutex);
|
||||
@@ -1547,6 +1569,7 @@ static int hisi_acc_vfio_pci_open_device(struct vfio_device *core_vdev)
|
||||
}
|
||||
hisi_acc_vdev->mig_state = VFIO_DEVICE_STATE_RUNNING;
|
||||
hisi_acc_vdev->dev_opened = true;
|
||||
hisi_acc_vdev->match_done = 0;
|
||||
mutex_unlock(&hisi_acc_vdev->open_mutex);
|
||||
}
|
||||
|
||||
@@ -1734,6 +1757,7 @@ static const struct pci_device_id hisi_acc_vfio_pci_table[] = {
|
||||
MODULE_DEVICE_TABLE(pci, hisi_acc_vfio_pci_table);
|
||||
|
||||
static const struct pci_error_handlers hisi_acc_vf_err_handlers = {
|
||||
.reset_prepare = hisi_acc_vf_pci_reset_prepare,
|
||||
.reset_done = hisi_acc_vf_pci_aer_reset_done,
|
||||
.error_detected = vfio_pci_core_aer_err_detected,
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#define ERROR_CHECK_TIMEOUT 100
|
||||
#define CHECK_DELAY_TIME 100
|
||||
#define QM_RESET_WAIT_TIMEOUT 60000
|
||||
|
||||
#define QM_SQC_VFT_BASE_SHIFT_V2 28
|
||||
#define QM_SQC_VFT_BASE_MASK_V2 GENMASK(15, 0)
|
||||
@@ -128,6 +129,7 @@ struct hisi_acc_vf_migration_file {
|
||||
struct hisi_acc_vf_core_device {
|
||||
struct vfio_pci_core_device core_device;
|
||||
u8 match_done;
|
||||
bool set_reset_flag;
|
||||
/*
|
||||
* io_base is only valid when dev_opened is true,
|
||||
* which is protected by open_mutex.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/pci-p2pdma.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/memory-failure.h>
|
||||
|
||||
/*
|
||||
* The device memory usable to the workloads running in the VM is cached
|
||||
@@ -49,6 +50,7 @@ struct mem_region {
|
||||
void *memaddr;
|
||||
void __iomem *ioaddr;
|
||||
}; /* Base virtual address of the region */
|
||||
struct pfn_address_space pfn_address_space;
|
||||
};
|
||||
|
||||
struct nvgrace_gpu_pci_core_device {
|
||||
@@ -88,6 +90,80 @@ nvgrace_gpu_memregion(int index,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int pfn_memregion_offset(struct nvgrace_gpu_pci_core_device *nvdev,
|
||||
unsigned int index,
|
||||
unsigned long pfn,
|
||||
pgoff_t *pfn_offset_in_region)
|
||||
{
|
||||
struct mem_region *region;
|
||||
unsigned long start_pfn, num_pages;
|
||||
|
||||
region = nvgrace_gpu_memregion(index, nvdev);
|
||||
if (!region)
|
||||
return -EINVAL;
|
||||
|
||||
start_pfn = PHYS_PFN(region->memphys);
|
||||
num_pages = region->memlength >> PAGE_SHIFT;
|
||||
|
||||
if (pfn < start_pfn || pfn >= start_pfn + num_pages)
|
||||
return -EFAULT;
|
||||
|
||||
*pfn_offset_in_region = pfn - start_pfn;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct nvgrace_gpu_pci_core_device *vma_to_nvdev(struct vm_area_struct *vma);
|
||||
|
||||
static int nvgrace_gpu_pfn_to_vma_pgoff(struct vm_area_struct *vma,
|
||||
unsigned long pfn,
|
||||
pgoff_t *pgoff)
|
||||
{
|
||||
struct nvgrace_gpu_pci_core_device *nvdev;
|
||||
unsigned int index =
|
||||
vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT);
|
||||
pgoff_t vma_offset_in_region = vma->vm_pgoff &
|
||||
((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
|
||||
pgoff_t pfn_offset_in_region;
|
||||
int ret;
|
||||
|
||||
nvdev = vma_to_nvdev(vma);
|
||||
if (!nvdev)
|
||||
return -ENOENT;
|
||||
|
||||
ret = pfn_memregion_offset(nvdev, index, pfn, &pfn_offset_in_region);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Ensure PFN is not before VMA's start within the region */
|
||||
if (pfn_offset_in_region < vma_offset_in_region)
|
||||
return -EFAULT;
|
||||
|
||||
/* Calculate offset from VMA start */
|
||||
*pgoff = vma->vm_pgoff +
|
||||
(pfn_offset_in_region - vma_offset_in_region);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvgrace_gpu_vfio_pci_register_pfn_range(struct vfio_device *core_vdev,
|
||||
struct mem_region *region)
|
||||
{
|
||||
unsigned long pfn, nr_pages;
|
||||
|
||||
pfn = PHYS_PFN(region->memphys);
|
||||
nr_pages = region->memlength >> PAGE_SHIFT;
|
||||
|
||||
region->pfn_address_space.node.start = pfn;
|
||||
region->pfn_address_space.node.last = pfn + nr_pages - 1;
|
||||
region->pfn_address_space.mapping = core_vdev->inode->i_mapping;
|
||||
region->pfn_address_space.pfn_to_vma_pgoff = nvgrace_gpu_pfn_to_vma_pgoff;
|
||||
|
||||
return register_pfn_address_space(®ion->pfn_address_space);
|
||||
}
|
||||
|
||||
static int nvgrace_gpu_open_device(struct vfio_device *core_vdev)
|
||||
{
|
||||
struct vfio_pci_core_device *vdev =
|
||||
@@ -114,14 +190,28 @@ static int nvgrace_gpu_open_device(struct vfio_device *core_vdev)
|
||||
* memory mapping.
|
||||
*/
|
||||
ret = vfio_pci_core_setup_barmap(vdev, 0);
|
||||
if (ret) {
|
||||
vfio_pci_core_disable(vdev);
|
||||
return ret;
|
||||
if (ret)
|
||||
goto error_exit;
|
||||
|
||||
if (nvdev->resmem.memlength) {
|
||||
ret = nvgrace_gpu_vfio_pci_register_pfn_range(core_vdev, &nvdev->resmem);
|
||||
if (ret && ret != -EOPNOTSUPP)
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
vfio_pci_core_finish_enable(vdev);
|
||||
ret = nvgrace_gpu_vfio_pci_register_pfn_range(core_vdev, &nvdev->usemem);
|
||||
if (ret && ret != -EOPNOTSUPP)
|
||||
goto register_mem_failed;
|
||||
|
||||
vfio_pci_core_finish_enable(vdev);
|
||||
return 0;
|
||||
|
||||
register_mem_failed:
|
||||
if (nvdev->resmem.memlength)
|
||||
unregister_pfn_address_space(&nvdev->resmem.pfn_address_space);
|
||||
error_exit:
|
||||
vfio_pci_core_disable(vdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nvgrace_gpu_close_device(struct vfio_device *core_vdev)
|
||||
@@ -130,6 +220,11 @@ static void nvgrace_gpu_close_device(struct vfio_device *core_vdev)
|
||||
container_of(core_vdev, struct nvgrace_gpu_pci_core_device,
|
||||
core_device.vdev);
|
||||
|
||||
if (nvdev->resmem.memlength)
|
||||
unregister_pfn_address_space(&nvdev->resmem.pfn_address_space);
|
||||
|
||||
unregister_pfn_address_space(&nvdev->usemem.pfn_address_space);
|
||||
|
||||
/* Unmap the mapping to the device memory cached region */
|
||||
if (nvdev->usemem.memaddr) {
|
||||
memunmap(nvdev->usemem.memaddr);
|
||||
@@ -247,6 +342,16 @@ static const struct vm_operations_struct nvgrace_gpu_vfio_pci_mmap_ops = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline
|
||||
struct nvgrace_gpu_pci_core_device *vma_to_nvdev(struct vm_area_struct *vma)
|
||||
{
|
||||
/* Check if this VMA belongs to us */
|
||||
if (vma->vm_ops != &nvgrace_gpu_vfio_pci_mmap_ops)
|
||||
return NULL;
|
||||
|
||||
return vma->vm_private_data;
|
||||
}
|
||||
|
||||
static int nvgrace_gpu_mmap(struct vfio_device *core_vdev,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
@@ -784,7 +889,7 @@ nvgrace_gpu_write(struct vfio_device *core_vdev,
|
||||
static int nvgrace_get_dmabuf_phys(struct vfio_pci_core_device *core_vdev,
|
||||
struct p2pdma_provider **provider,
|
||||
unsigned int region_index,
|
||||
struct dma_buf_phys_vec *phys_vec,
|
||||
struct phys_vec *phys_vec,
|
||||
struct vfio_region_dma_range *dma_ranges,
|
||||
size_t nr_ranges)
|
||||
{
|
||||
|
||||
@@ -588,6 +588,7 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_enable);
|
||||
|
||||
void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
|
||||
{
|
||||
struct pci_dev *bridge;
|
||||
struct pci_dev *pdev = vdev->pdev;
|
||||
struct vfio_pci_dummy_resource *dummy_res, *tmp;
|
||||
struct vfio_pci_ioeventfd *ioeventfd, *ioeventfd_tmp;
|
||||
@@ -694,12 +695,20 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev)
|
||||
* We can not use the "try" reset interface here, which will
|
||||
* overwrite the previously restored configuration information.
|
||||
*/
|
||||
if (vdev->reset_works && pci_dev_trylock(pdev)) {
|
||||
if (!__pci_reset_function_locked(pdev))
|
||||
vdev->needs_reset = false;
|
||||
pci_dev_unlock(pdev);
|
||||
if (vdev->reset_works) {
|
||||
bridge = pci_upstream_bridge(pdev);
|
||||
if (bridge && !pci_dev_trylock(bridge))
|
||||
goto out_restore_state;
|
||||
if (pci_dev_trylock(pdev)) {
|
||||
if (!__pci_reset_function_locked(pdev))
|
||||
vdev->needs_reset = false;
|
||||
pci_dev_unlock(pdev);
|
||||
}
|
||||
if (bridge)
|
||||
pci_dev_unlock(bridge);
|
||||
}
|
||||
|
||||
out_restore_state:
|
||||
pci_restore_state(pdev);
|
||||
out:
|
||||
pci_disable_device(pdev);
|
||||
|
||||
@@ -14,7 +14,7 @@ struct vfio_pci_dma_buf {
|
||||
struct vfio_pci_core_device *vdev;
|
||||
struct list_head dmabufs_elm;
|
||||
size_t size;
|
||||
struct dma_buf_phys_vec *phys_vec;
|
||||
struct phys_vec *phys_vec;
|
||||
struct p2pdma_provider *provider;
|
||||
u32 nr_ranges;
|
||||
u8 revoked : 1;
|
||||
@@ -106,7 +106,7 @@ static const struct dma_buf_ops vfio_pci_dmabuf_ops = {
|
||||
* will fail if it is currently revoked
|
||||
*/
|
||||
int vfio_pci_dma_buf_iommufd_map(struct dma_buf_attachment *attachment,
|
||||
struct dma_buf_phys_vec *phys)
|
||||
struct phys_vec *phys)
|
||||
{
|
||||
struct vfio_pci_dma_buf *priv;
|
||||
|
||||
@@ -128,7 +128,7 @@ int vfio_pci_dma_buf_iommufd_map(struct dma_buf_attachment *attachment,
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_MODULES(vfio_pci_dma_buf_iommufd_map, "iommufd");
|
||||
|
||||
int vfio_pci_core_fill_phys_vec(struct dma_buf_phys_vec *phys_vec,
|
||||
int vfio_pci_core_fill_phys_vec(struct phys_vec *phys_vec,
|
||||
struct vfio_region_dma_range *dma_ranges,
|
||||
size_t nr_ranges, phys_addr_t start,
|
||||
phys_addr_t len)
|
||||
@@ -160,7 +160,7 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_fill_phys_vec);
|
||||
int vfio_pci_core_get_dmabuf_phys(struct vfio_pci_core_device *vdev,
|
||||
struct p2pdma_provider **provider,
|
||||
unsigned int region_index,
|
||||
struct dma_buf_phys_vec *phys_vec,
|
||||
struct phys_vec *phys_vec,
|
||||
struct vfio_region_dma_range *dma_ranges,
|
||||
size_t nr_ranges)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user