Ensure that a PCI BAR cannot be registered for native ZONE_DEVICE P2P if it is already being used as a source for exported DMABUFs. Add region_index to struct vfio_pci_dma_buf to track the source BAR. Introduce a new helper function, vfio_pci_bar_is_dmabuf() to scan the device's active DMABUF list. When a registration request is received via VFIO_DEVICE_FEATURE_P2P_REGISTER, VFIO rejects the request with -EBUSY if any active DMABUF originates from the target BAR. Signed-off-by: Pranjal Shrivastava --- drivers/vfio/pci/vfio_pci_core.c | 6 ++++++ drivers/vfio/pci/vfio_pci_dmabuf.c | 16 ++++++++++++++++ drivers/vfio/pci/vfio_pci_priv.h | 6 ++++++ 3 files changed, 28 insertions(+) diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index 9cf494b765e7..7913b8916df9 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -1579,6 +1579,12 @@ static int vfio_pci_core_feature_p2p_register(struct vfio_pci_core_device *vdev, if (vdev->p2p_registered_bars & (1 << bar_index)) return 0; + if (vfio_pci_bar_is_dmabuf(vdev, bar_index)) { + pci_warn(vdev->pdev, "BAR %d has active DMABUFs. Cannot register for P2P.\n", + bar_index); + return -EBUSY; + } + ret = pci_p2pdma_add_resource(vdev->pdev, bar_index, 0, 0); if (ret && ret != -EEXIST) return ret; diff --git a/drivers/vfio/pci/vfio_pci_dmabuf.c b/drivers/vfio/pci/vfio_pci_dmabuf.c index 6635a8681291..194d74724422 100644 --- a/drivers/vfio/pci/vfio_pci_dmabuf.c +++ b/drivers/vfio/pci/vfio_pci_dmabuf.c @@ -17,6 +17,7 @@ struct vfio_pci_dma_buf { struct phys_vec *phys_vec; struct p2pdma_provider *provider; u32 nr_ranges; + u32 region_index; struct kref kref; struct completion comp; u8 revoked : 1; @@ -279,6 +280,7 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, priv->vdev = vdev; priv->nr_ranges = get_dma_buf.nr_ranges; + priv->region_index = get_dma_buf.region_index; priv->size = length; ret = vdev->pci_ops->get_dmabuf_phys(vdev, &priv->provider, get_dma_buf.region_index, @@ -410,3 +412,17 @@ void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev) } up_write(&vdev->memory_lock); } + +bool vfio_pci_bar_is_dmabuf(struct vfio_pci_core_device *vdev, int index) +{ + struct vfio_pci_dma_buf *priv; + + lockdep_assert_held(&vdev->memory_lock); + + list_for_each_entry(priv, &vdev->dmabufs, dmabufs_elm) { + if (priv->region_index == index) + return true; + } + return false; +} +EXPORT_SYMBOL_GPL(vfio_pci_bar_is_dmabuf); diff --git a/drivers/vfio/pci/vfio_pci_priv.h b/drivers/vfio/pci/vfio_pci_priv.h index fca9d0dfac90..0a5da4d5edc4 100644 --- a/drivers/vfio/pci/vfio_pci_priv.h +++ b/drivers/vfio/pci/vfio_pci_priv.h @@ -120,6 +120,7 @@ int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, size_t argsz); void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev); void vfio_pci_dma_buf_move(struct vfio_pci_core_device *vdev, bool revoked); +bool vfio_pci_bar_is_dmabuf(struct vfio_pci_core_device *vdev, int index); #else static inline int vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, @@ -128,6 +129,11 @@ vfio_pci_core_feature_dma_buf(struct vfio_pci_core_device *vdev, u32 flags, { return -ENOTTY; } +static inline bool vfio_pci_bar_is_dmabuf(struct vfio_pci_core_device *vdev, + int index) +{ + return false; +} static inline void vfio_pci_dma_buf_cleanup(struct vfio_pci_core_device *vdev) { } -- 2.54.0.1099.g489fc7bff1-goog